This commit is contained in:
cfif 2025-06-02 14:32:56 +03:00
commit 239d74d8de
21 changed files with 3664 additions and 0 deletions

13
Inc/EgtsTimestamp.h Normal file
View File

@ -0,0 +1,13 @@
//
// Created by xemon on 06.07.23.
//
#ifndef MODULE_EGTSTIMESTAMP_H
#define MODULE_EGTSTIMESTAMP_H
#include "stdint.h"
uint32_t Egts_EpochTimestampToEgtsTime(uint32_t ts);
uint32_t Egts_EpochEgtsTimeToTimestamp(uint32_t ts);
#endif //MODULE_EGTSTIMESTAMP_H

298
Inc/egts.h Normal file
View File

@ -0,0 +1,298 @@
/*
* egts.h
*
* Created on: Jun 4, 2021
* Author: zemon
*/
#ifndef EGTS_INC_EGTS_H_
#define EGTS_INC_EGTS_H_
#include <stdint.h>
#include "stdbool.h"
#define TRANSPORT_HEADER_LENGTH 11
#define EGTS_SERVICE_FLAGS_MSD 0x94
#define EGTS_SERVICE_FLAGS_POS 0x04
#define EGTS_SERVICE_FLAGS_AUTH 0x9c
#define EGTS_SERVICE_FLAGS_COMMAND 0x9c
#define EGTS_SERVICE_FLAGS_TELEDATA 0x9c
#define EGTS_SERVICE_FLAGS_FIRMWARE 0x9c
#define EGTS_SERVICE_FLAGS_COMMAND 0x9c
typedef enum {
EGTS_SR_RECORD_RESPONSE = 0x00,
//EGTS_AUTH_SERVICE
EGTS_SR_TERM_IDENTITY = 0x01,
EGTS_SR_MODULE_DATA = 0x02,
//EGTS_COMMANDS_SERVICE
EGTS_SR_COMMAND_DATA = 0x33,
//EGTS_TELEDATA_SERVICE
EGTS_SR_POS_DATA = 0x10,
EGTS_SR_EXT_POS_DATA = 0x11,
//EGTS_TELEDATA_SERVICE
EGTS_SR_AD_SENSORS_DATA = 0x12,
//EGTS_ECALL_SERVICE
EGTS_SR_RAW_MSD_DATA = 0x28,
//EGTS_EUROPROTOCOL_SERVICE
EGTS_SR_EP_MAIN_DATA = 0x01,
EGTS_SR_EP_TRACK_DATA = 0x02,
EGTS_SR_EP_ACCEL_DATA = 0x03,
EGTS_SR_ABS_DIG_SENS_DATA = 0x17,
EGTS_SR_ABS_AN_SENS_DATA = 0x18,
EGTS_SR_SERVICE_PART_DATA = 0x21,
EGTS_SR_RESULT_CODE = 0x09,
} eEgtsSubRecordId;
typedef enum {
EGTS_AUTH_SERVICE = 0x01,
EGTS_TELEDATA_SERVICE = 0x02,
EGTS_COMMANDS_SERVICE = 0x04,
EGTS_FIRMWARE_SERVICE = 0x09,
EGTS_ECALL_SERVICE = 0x0A,
EGTS_EUROPROTOCOL_SERVICE = 0x16,
EGTS_NOTIFICATION_SERVICE = 0x28,
} eEgtsServiceId;
typedef enum {
EGTS_PT_RESPONSE = 0x00,//(подтверждение на пакет транспортного уровня);
EGTS_PT_APPDATA = 0x01, //(пакет, содержащий данные протокола уровня поддержки услуг);
EGTS_PT_SIGNED_APPDATA = 0x02,
} eEgtsPacketTypeId;
typedef uint16_t(*tEgtsServiceSubRecordGenerator)(uint8_t *out, void *args);
uint32_t toEgtsTimestamp(uint32_t ts);
////TERM_IDENTITY##########
typedef struct {
uint8_t *IMEI;
uint8_t IMEI_len;
uint32_t TerminalID;
// uint32_t epochTimestamp;
} tEgtsTermIdentityArgs;
#define vEgtsPackTermIdentityGen (tEgtsServiceSubRecordGenerator) vEgtsPackTermIdentity
uint16_t vEgtsPackTermIdentity(uint8_t *out, tEgtsTermIdentityArgs *args);
////##################
////CMD CONFIRMATION DATA ##########
typedef struct {
uint16_t ADR;
uint8_t SZ;
uint8_t ACT;
uint16_t CCD;
uint16_t DT;
} tEgtsSrCmdConfirmationComData;
////CMD CONFIRMATION ##########
typedef struct {
uint8_t CT;
uint8_t CCT;
uint32_t CID;
uint32_t SID;
uint8_t ACFE;
uint8_t CHSFE;
uint8_t CHS;
uint8_t ACL;
uint16_t AC;
tEgtsSrCmdConfirmationComData CmdData;
} tEgtsSrCmdConfirmation;
uint16_t vEgtsPacSrCommandDataResponse(uint8_t *out, tEgtsSrCmdConfirmation *args);
#define vEgtsPacSrCommandDataResponseGen (tEgtsServiceSubRecordGenerator) vEgtsPacSrCommandDataResponse
////##################
////RESPONSE ##########
typedef struct {
uint16_t CRN;
uint8_t RST;
} tEgtsRecordResponseData;
uint16_t vEgtsPackResponse(uint8_t *out, tEgtsRecordResponseData *args);
#define vEgtsPackResponseGen (tEgtsServiceSubRecordGenerator) vEgtsPackResponse
////##################
////POS DATA##########
typedef struct {
double latitude;
double longitude;
uint16_t velocity;
uint32_t epochTimestamp;
} tEgtsPosDataArgs;
#define vEgtsPackPosDataGen (tEgtsServiceSubRecordGenerator) vEgtsPackPosData
uint16_t vEgtsPackPosData(uint8_t *out, tEgtsPosDataArgs *args);
////##################
#define SENSOR_NO (0x00)
#define SENSOR_1 (0x01)
#define SENSOR_2 (0x01<<1)
#define SENSOR_3 (0x01<<2)
#define SENSOR_4 (0x01<<3)
#define SENSOR_5 (0x01<<4)
#define SENSOR_6 (0x01<<5)
#define SENSOR_7 (0x01<<6)
#define SENSOR_8 (0x01<<7)
////SENSORS DATA##########
typedef struct {
uint8_t digitalInPresent;
uint8_t digitalOutPresent;
uint8_t analogInPresent;
uint8_t digitalIn[8];
uint32_t analogIn[8];
} tEgtsSensorsDataArgs;
#define vEgtsPackSensorsDataGen (tEgtsServiceSubRecordGenerator) vEgtsPackSensorsData
uint16_t vEgtsPackSensorsData(uint8_t *out, tEgtsSensorsDataArgs *args);
////##################
////MSD DATA##########
typedef struct {
uint8_t *msd;
uint8_t msdLength;
} tEgtsMsdDataArgs;
#define vEgtsPackMsdDataGen (tEgtsServiceSubRecordGenerator) vEgtsPackMsdData
uint16_t vEgtsPackMsdData(uint8_t *out, tEgtsMsdDataArgs *args);
//
//uint16_t vEgtsPackMsdResp(uint8_t *out, tEgtsRecordResponseData *args);
////##################
////MSD DATA##########
typedef struct {
bool LOHS;
bool LAHS;
uint16_t speed;
bool TrackDataExist;
uint32_t Latitude;
uint32_t Longitude;
bool AltitudeDirection;
uint16_t Altitude;
uint16_t Direction;
} tEgtsTrackData;
typedef struct {
bool DataValid;
uint8_t TimeShift;
bool type;
} tEgtsRelativeTrackData;
typedef struct {
uint16_t blockNumber;
uint32_t absoluteTime;
uint8_t relativeAmount;
uint8_t timeShift;
bool CoordinateSystem;
bool RTU;
tEgtsTrackData originPoint;
} tEgtsSrEpTrackDataArgs;
uint16_t vEgtsPackSrEpTrackData(uint8_t *out, tEgtsSrEpTrackDataArgs *args);
#define vEgtsPackSrEpTrackDataGen (tEgtsServiceSubRecordGenerator) vEgtsPackSrEpTrackData
////##################
uint16_t vEgtsPackSrv(
uint8_t *out,
uint8_t flags,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGenerator subRecGen,
void *subRecArgs
);
uint16_t vEgtsPackTransport(
uint16_t cid,
uint16_t packetId,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGenerator subRecGen,
void *subRecArgs
);
uint16_t vEgtsPackMsdTransport(uint16_t packetId, uint8_t *out, uint8_t *msd, uint8_t msdLength, uint32_t timestamp);
uint16_t
vEgtsPackEgtsResponse(uint16_t packetId, uint8_t *out, uint8_t rst, uint16_t crn, uint16_t cid, uint32_t timestamp);
uint16_t vEgtsPackSrCmdConfirmation(
uint8_t *out,
uint16_t packetId,
uint16_t cmdType,
uint16_t cmdConfirType,
uint16_t cid,
uint16_t sid,
uint16_t acfe,
uint16_t chsfe,
uint16_t adr,
uint8_t sz,
uint8_t act,
uint16_t ccd,
uint32_t dt
);
uint16_t vEgtsPackTeledataTransport(
uint16_t packetId,
uint8_t *out,
double Latitude,
double Longitude,
uint16_t velocity,
uint32_t timestamp
);
uint16_t vEgtsPackTermIdentityTransport(
uint16_t packetId, uint8_t *out, uint8_t *IMEI, uint8_t IMEI_len, uint32_t TerminalID, uint32_t timestamp
);
uint16_t vEgtsPackSensorsTransport(
uint16_t packetId,
uint8_t *out,
uint32_t epochTimestamp,
tEgtsSensorsDataArgs *sensors
);
#endif /* EGTS_INC_EGTS_H_ */

253
Inc/egtsWorker.h Normal file
View File

@ -0,0 +1,253 @@
//
// Created by zemon on 05.01.23.
//
#ifndef UVEOS_ON_NATION_EGTSWORKER_H
#define UVEOS_ON_NATION_EGTSWORKER_H
#include "stdint.h"
#include "stdbool.h"
#include "stddef.h"
#include "stdbool.h"
#include "egts.h"
#include "BaseTypes/Strings.h"
#define EGTS_WORKING_BUFFER_LENGTH 512
//#define EGTS_SR_COMMAND_DATA 0x04
#define EGTS_FLEET_GET_POS_DATA 0x000C
//CMDS
// AURUS
#define EGTS_AURUS_SET_TIME 0xFAC4
//#define EGTS_RAW_DATA 0x0000
#define EGTS_ECALL_MSD_REQ 0x0113
#define EGTS_START_SEND_READY 0x510A
#define EGTS_STOP_SEND_READY 0x510B
#define EGTS_SEND_ACCIDENT_DATA 0x060C
#define EGTS_ECALL_REQ 0x0112
#define EGTS_ECALL_TEST_NUMBER 0x020d
#define EGTS_ECALL_SMS_FALLBACK_NUMBER 0x0223
#define EGTS_FLEET_MAX_SPEED_THRESHOLD 0x0266
// Command Туре
#define CT_COMCONF 0b0001
#define CT_MSGCONF 0b0010
#define CT_MSGFROM 0b0011
#define CT_MSGTO 0b0100
#define CT_COM 0b0101
#define CT_DELCOM 0b0110
#define CT_SUBREQ 0b0111
#define CT_DELIV 0b1000
// Command Confirmation Type
#define CC_OK 0b0000
#define CC_ERROR 0b0001
#define CC_ILL 0b0010
#define CC_DEL 0b0011
#define CC_NFOUND 0b0100
#define CC_NCONF 0b0101
#define CC_INPROG 0b0110
// Command Codes
#define EGTS_RAW_DATA 0b0000
#define EGTS_TEST_MODE 0b0001
#define EGTS_CONFIG_RESET 0b0006
#define EGTS_SET_AUTH_CODE 0b0007
#define EGTS_RESTART 0b0108
//SR
#define EGTS_SR_COMMAND_DATA_CMD_OFFSET 13
#define EGTS_SR_NOTIFICATION_DATA 3
#define EGTS_SR_NOTIFICATION_PART_DATA 4
#define EGTS_SR_NOTIFICATION_FULL_DATA 5
//EGTS_ECALL_REQ_TYPE
#define EGTS_ECALL_REQ_MANUAL 0
#define EGTS_ECALL_REQ_AUTOMATIC 1
//EGTS_ECALL_MSD_REQ_TRANSPORT_TYPE
#define EGTS_ECALL_MSD_REQ_TRANSPORT_ANY 0
#define EGTS_ECALL_MSD_REQ_TRANSPORT_SMS 2
typedef struct {
uint8_t flags;
uint8_t count;
uint16_t notifications[128];
uint8_t storeHours;
uint8_t repeatCount;
uint8_t repeatIntervalMin;
} EgtsSrNotificationData;
typedef struct {
uint8_t headerLength;
uint8_t *header;
uint8_t mandatory;
uint8_t expiration;
uint8_t storeHours;
uint8_t repeatCount;
uint8_t repeatIntervalMin;
} EgtsSrNotificationFullData;
typedef struct {
uint16_t reqType;
} tEgtsEcallReq;
typedef struct {
int32_t mid;
uint8_t transport;
} tEgtsEcallMsdReq;
typedef struct {
uint32_t profile;
bool enabled;
} tEgtsNextCmd;
typedef union {
tEgtsEcallReq ecallReq;
tEgtsEcallMsdReq msdReq;
tEgtsNextCmd next;
tString32 newFallbackNumber;
int32_t arr[5];
} uEgtsSrCommandData;
typedef struct {
uint8_t cmdType;
uint8_t cmdConfirmationType;
uint32_t cmdId;
uint32_t srcId;
bool hasAuth;
bool hasCharset;
uint8_t charset;
uint8_t authLen;
uint8_t auth[255];
uint16_t address;
uint8_t size;
uint8_t act;
uint16_t cmd;
uEgtsSrCommandData data;
void *dataPointer;
} EgtsSrCommand;
typedef struct __attribute__ ((packed)) {
uint8_t MT: 2;
uint8_t OT: 2;
uint8_t Reserve: 4;
} tOA;
typedef struct {
uint16_t Identity;
uint16_t PartNumber;
uint16_t ExpectedPartsQuantity;
tOA ObjectAttribute;
uint8_t ComponentOrModuleIdentifier;
uint16_t Version;
uint16_t WholeObjectSignature;
char FileName[65];
void *dataPointer;
uint16_t dataLength;
} EgtsFirmware;
typedef union {
EgtsFirmware firmware;
EgtsSrCommand cmd;
EgtsSrNotificationData notificationData;
} EgtsSubRecMemAlloc;
typedef struct {
uint8_t protocol;
uint8_t SecKeyID;
uint8_t flags;
uint8_t headerLength;
uint16_t frameDataLength;
uint16_t packetId;
uint8_t encoding;
uint8_t type;
uint8_t crc;
} EgtsHeader;
typedef struct {
uint16_t responsePacketId;
uint8_t status;
} EgtsPtResponse;
typedef struct {
size_t (*readData)(void *env, uint8_t *data, size_t size);
void *readDataEnv;
EgtsHeader header;
EgtsPtResponse ptResponse;
uint8_t *workingBuffer;
uint16_t workingBufferLength;
uint32_t workingBufferLimit;
uint8_t headerLength;
uint16_t frameDataLength;
uint8_t frameDataSrcLength;
uint8_t *frameData;
uint8_t *record;
uint16_t recordLength;
uint16_t recordNumber;
uint8_t recordFlags;
bool recHasTime;
bool recHasEvent;
bool recHasObj;
eEgtsServiceId recSourceService;
eEgtsServiceId recRecipientService;
uint8_t *recordData;
uint8_t subRecType;
uint16_t subRecLength;
uint8_t *subRecData;
EgtsSubRecMemAlloc subRecMemAlloc;
EgtsSrNotificationData *srNotificationData;
EgtsSrCommand *srCommand;
EgtsFirmware *firmware;
} EgtsWorkerEnvironment;
//void EgtsWorkerLoadPreBuffer(EgtsWorkerEnvironment *env, uint8_t *data, uint16_t dataLength);
//bool EgtsWorkerReadPreBuffer(EgtsWorkerEnvironment *env, uint8_t *data);
bool EgtsCompleteTransport(EgtsWorkerEnvironment *env);
bool EgtsIsTransportComplete(EgtsWorkerEnvironment *env);
void EgtsParseHeader(EgtsWorkerEnvironment *env);
void EgtsParseFrameData(EgtsWorkerEnvironment *env);
void EgtsParseSrvRecord(EgtsWorkerEnvironment *env);
void EgtsResetBuffer(EgtsWorkerEnvironment *env);
uint16_t EgtsGetTransportFullLength(EgtsWorkerEnvironment *env);
void EgtsParseSrvNotificationData(uint8_t *rec, EgtsSrNotificationData *notificationData);
void EgtsParseSrvSubRecord(EgtsWorkerEnvironment *env, uint8_t *subRecRaw);
#endif //UVEOS_ON_NATION_EGTSWORKER_H

37
Inc/egtsWorkerExt.h Normal file
View File

@ -0,0 +1,37 @@
//
// Created by cfif on 18.05.2024.
//
#ifndef SMART_COMPONENTS_EGTSWORKEREXT_H
#define SMART_COMPONENTS_EGTSWORKEREXT_H
#include "egtsWorker.h"
typedef enum {
EGTS_COMPLETE_OK = 0x00,
EGTS_COMPLETE_WAIT = 0x01,
EGTS_COMPLETE_HEADER_ERR_CRC = 0x02,
EGTS_COMPLETE_BODY_ERR_CRC = 0x03,
EGTS_COMPLETE_ERR_VER = 0x04,
EGTS_COMPLETE_ERR_OVERFLOW = 0x05
} eEgts_CompleteResult;
typedef struct {
eEgts_CompleteResult completeResult;
uint8_t calcHeaderCrc;
uint8_t receivedHeaderCrc;
uint16_t calcBodyCrc;
uint16_t receivedBodyCrc;
uint16_t fullLength;
} EgtsCompleteResult;
bool EgtsParseHeaderExt(EgtsWorkerEnvironment *env);
uint16_t EgtsParseSrvRecordExt(EgtsWorkerEnvironment *env, uint8_t *record);
EgtsCompleteResult* EgtsCompleteTransportExt(EgtsWorkerEnvironment *env);
eEgts_CompleteResult EgtsIsTransportCompleteExt(EgtsWorkerEnvironment *env);
#endif //SMART_COMPONENTS_EGTSWORKEREXT_H

124
Inc/egts_commonExt.h Normal file
View File

@ -0,0 +1,124 @@
//
// Created by cfif on 22.04.2024.
//
#ifndef SMART_COMPONENTS_EGTS_COMMONEXT_H
#define SMART_COMPONENTS_EGTS_COMMONEXT_H
#include "egts.h"
#include "egts_crc.h"
typedef uint16_t(*tEgtsServiceSubRecordGeneratorEx)(uint8_t *out, void *args, uint16_t step);
uint16_t vEgtsPackSrvEx(
uint8_t *out,
uint16_t counter,
uint8_t flags,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t epochTimestamp,
uint16_t subRecordCount,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGeneratorEx subRecGen,
void *subRecArgs
);
uint16_t vEgtsPackTransportEx1(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGeneratorEx subRecGen,
void *subRecArgs
);
uint16_t vEgtsPackTransportEx2(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount1,
eEgtsSubRecordId subRecordType1,
tEgtsServiceSubRecordGeneratorEx subRecGen1,
void *subRecArgs1,
uint16_t subRecordCount2,
eEgtsSubRecordId subRecordType2,
tEgtsServiceSubRecordGeneratorEx subRecGen2,
void *subRecArgs2
);
uint16_t vEgtsPackTransportEx3(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount1,
eEgtsSubRecordId subRecordType1,
tEgtsServiceSubRecordGeneratorEx subRecGen1,
void *subRecArgs1,
uint16_t subRecordCount2,
eEgtsSubRecordId subRecordType2,
tEgtsServiceSubRecordGeneratorEx subRecGen2,
void *subRecArgs2,
uint16_t subRecordCount3,
eEgtsSubRecordId subRecordType3,
tEgtsServiceSubRecordGeneratorEx subRecGen3,
void *subRecArgs3
);
uint16_t vEgtsPackTransportEx4(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount1,
eEgtsSubRecordId subRecordType1,
tEgtsServiceSubRecordGeneratorEx subRecGen1,
void *subRecArgs1,
uint16_t subRecordCount2,
eEgtsSubRecordId subRecordType2,
tEgtsServiceSubRecordGeneratorEx subRecGen2,
void *subRecArgs2,
uint16_t subRecordCount3,
eEgtsSubRecordId subRecordType3,
tEgtsServiceSubRecordGeneratorEx subRecGen3,
void *subRecArgs3,
uint16_t subRecordCount4,
eEgtsSubRecordId subRecordType4,
tEgtsServiceSubRecordGeneratorEx subRecGen4,
void *subRecArgs4
);
#endif //SMART_COMPONENTS_EGTS_COMMONEXT_H

16
Inc/egts_crc.h Normal file
View File

@ -0,0 +1,16 @@
/*
* egts_crc.h
*
* Created on: Oct 2, 2020
* Author: FICOM-IT LTD
*/
#ifndef INC_EGTS_CRC_H_
#define INC_EGTS_CRC_H_
#include <stdint.h>
uint8_t CRC8EGTS(unsigned char *lpBlock, unsigned char len);
uint16_t CRC16EGTS(unsigned char * pcBlock, unsigned int len);
#endif /* INC_EGTS_CRC_H_ */

14
Src/EgtsTimestamp.c Normal file
View File

@ -0,0 +1,14 @@
//
// Created by xemon on 06.07.23.
//
#include "EgtsTimestamp.h"
#define EGTS_TIMESTAMP_EPOCH_OFFSET 1262304000 // epoch timestamp of Fri, 01 Jan 2010 00:00:00 GMT
uint32_t Egts_EpochTimestampToEgtsTime(uint32_t ts) {
return ts - EGTS_TIMESTAMP_EPOCH_OFFSET;
}
uint32_t Egts_EpochEgtsTimeToTimestamp(uint32_t ts) {
return ts + EGTS_TIMESTAMP_EPOCH_OFFSET;
}

289
Src/egtsWorker.c Normal file
View File

@ -0,0 +1,289 @@
//
// Created by zemon on 23.12.2021.
//
#include "SystemDelayInterface.h"
#include <egts.h>
#include "egtsWorker.h"
#include "string.h"
//bool EgtsWorkerLoadPreBuffer(EgtsWorkerEnvironment *env, uint8_t *data, uint16_t dataLength) {
//
// uint8_t *data_end = data + dataLength;
// uint32_t END = HAL_GetTick() + 10000;
//
// while (data != data_end) {
// xQueueSend(env->xQueueRxData, data, 1);
// ++data;
//
// if(END < HAL_GetTick()){
// return false;
// }
// }
//
// return true;
//
//}
//
//bool EgtsWorkerReadPreBuffer(EgtsWorkerEnvironment *env, uint8_t *data) {
// return xQueueReceive(env->xQueueRxData, data, 0) != pdTRUE ? false : true;
//}
#define EGTS_STATIC_HEADER_LENGTH 10
uint8_t EgtsGetTransportHeaderLength(EgtsWorkerEnvironment *env) {
return env->workingBuffer[3];
}
void EgtsResetBuffer(EgtsWorkerEnvironment *env) {
memset(env->workingBuffer, 0, env->workingBufferLength);
memset(&env->subRecMemAlloc, 0, sizeof(EgtsSubRecMemAlloc));
memset(&env->header, 0, sizeof(EgtsHeader));
memset(&env->ptResponse, 0, sizeof(EgtsPtResponse));
env->srNotificationData = NULL;
env->srCommand = NULL;
env->workingBufferLength = 0;
}
uint16_t EgtsGetTransportFrameDataLength(EgtsWorkerEnvironment *env) {
return *((uint16_t *) (env->workingBuffer + 5));
}
uint16_t EgtsGetTransportFullLength(EgtsWorkerEnvironment *env) {
env->headerLength = EgtsGetTransportHeaderLength(env);
env->frameDataLength = EgtsGetTransportFrameDataLength(env);
env->frameDataSrcLength = (env->frameDataLength > 0) ? 2 : 0;
return env->headerLength + env->frameDataLength + env->frameDataSrcLength;
}
bool EgtsCompleteTransport(EgtsWorkerEnvironment *env) {
size_t read = env->readData(
env->readDataEnv,
env->workingBuffer + env->workingBufferLength,
EGTS_STATIC_HEADER_LENGTH - env->workingBufferLength
);
env->workingBufferLength += read;
if (env->workingBufferLength < EGTS_STATIC_HEADER_LENGTH) {
return false;
}
uint16_t fullLength = EgtsGetTransportFullLength(env);
read = env->readData(
env->readDataEnv,
env->workingBuffer + env->workingBufferLength,
fullLength - env->workingBufferLength
);
env->workingBufferLength += read;
if (env->workingBufferLength < fullLength) {
return false;
}
return true;
}
bool EgtsIsTransportComplete(EgtsWorkerEnvironment *env) {
if (env->workingBufferLength < EGTS_STATIC_HEADER_LENGTH) {
return false;
}
uint16_t fullLength = EgtsGetTransportFullLength(env);
if (env->workingBufferLength < fullLength) {
return false;
}
return true;
}
void EgtsParseHeader(EgtsWorkerEnvironment *env) {
// uint8_t protocol;
// uint8_t SecKeyID;
// uint8_t flags;
// uint16_t length;
// uint8_t encoding;
// uint16_t id;
// uint8_t type;
// uint8_t crc;
env->header.protocol = *env->workingBuffer;
env->header.SecKeyID = *(env->workingBuffer + 1);
env->header.flags = *(env->workingBuffer + 2);
env->header.headerLength = *(uint8_t *) (env->workingBuffer + 3);
env->header.encoding = *(env->workingBuffer + 4);
env->header.frameDataLength = *(uint16_t *) (env->workingBuffer + 5);
env->header.packetId = *(uint16_t *) (env->workingBuffer + 7);
env->header.type = *(uint8_t *) (env->workingBuffer + 9);
env->header.crc = *(env->workingBuffer + 10);
}
void EgtsParseFrameData(EgtsWorkerEnvironment *env) {
env->frameData = env->workingBuffer + env->headerLength;
if (env->header.type == EGTS_PT_RESPONSE) {
env->ptResponse.responsePacketId = *(uint16_t *) (env->frameData);
env->ptResponse.status = *(env->frameData + 2);
env->record = (env->frameData + 3);
} else {
env->record = env->frameData;
}
}
void EgtsParseSrvSubRecordSrCommand(EgtsWorkerEnvironment *env) {
uint16_t inRecOffset = 0;
env->srCommand->cmdType = *((uint8_t *) env->subRecData + inRecOffset) >> 0x4;
env->srCommand->cmdConfirmationType = *((uint8_t *) env->subRecData + inRecOffset) & 0b1111;
inRecOffset += 1;
env->srCommand->cmdId = *((uint32_t *) (env->subRecData + inRecOffset));
inRecOffset += 4;
env->srCommand->srcId = *((uint32_t *) (env->subRecData + inRecOffset));
inRecOffset += 4;
uint8_t flags = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
env->srCommand->hasCharset = flags & 0b1;
env->srCommand->hasAuth = (flags >> 0x1) & 0b1;
if (env->srCommand->hasCharset) {
env->srCommand->charset = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
}
if (env->srCommand->hasAuth) {
env->srCommand->authLen = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
memcpy(env->srCommand->auth, (env->subRecData + inRecOffset), env->srCommand->authLen);
inRecOffset += env->srCommand->authLen;
}
env->srCommand->address = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
uint8_t actFlags = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
env->srCommand->act = actFlags & 0xF;
env->srCommand->size = (actFlags >> 0x4) & 0xF;
env->srCommand->cmd = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
if (env->srCommand->cmd == EGTS_SEND_ACCIDENT_DATA) {
env->srCommand->data.next.profile = *((bool *) (env->subRecData + inRecOffset));
inRecOffset += 1;
} else if (env->srCommand->cmd == EGTS_START_SEND_READY) {
env->srCommand->data.next.enabled = *((uint32_t *) (env->subRecData + inRecOffset));
inRecOffset += 4;
} else if (env->srCommand->cmd == EGTS_ECALL_MSD_REQ) {
env->srCommand->data.msdReq.mid = *((int32_t *) (env->subRecData + inRecOffset));
inRecOffset += 4;
env->srCommand->data.msdReq.transport = *((uint8_t *) (env->subRecData + inRecOffset));
} else if (env->srCommand->cmd == EGTS_ECALL_REQ) {
env->srCommand->data.ecallReq.reqType = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
} else if ((env->srCommand->cmd == EGTS_ECALL_TEST_NUMBER) ||
(env->srCommand->cmd == EGTS_ECALL_SMS_FALLBACK_NUMBER)) {
tString32 *number = &env->srCommand->data.newFallbackNumber;
number->length = env->subRecLength - inRecOffset;
memcpy(number->data, env->subRecData + inRecOffset, number->length);
inRecOffset += number->length;
} else if (env->srCommand->cmd == EGTS_FLEET_MAX_SPEED_THRESHOLD) {
int32_t *arr = env->srCommand->data.arr;
memcpy(arr, env->subRecData + inRecOffset, 5 * 4);
inRecOffset += (5 * 4);
}
}
void EgtsParseSrvNotificationData(uint8_t *rec, EgtsSrNotificationData *notificationData) {
notificationData->flags = rec[0];
notificationData->count = rec[1];
if (notificationData->count) {
memcpy((uint8_t *) notificationData->notifications, rec + 2, (notificationData->count * 2));
}
uint8_t afterArray = (notificationData->count * 2) + 2;
notificationData->storeHours = rec[afterArray + 0];
notificationData->repeatCount = rec[afterArray + 1];
notificationData->repeatIntervalMin = rec[afterArray + 2];
}
void EgtsParseSrvSubRecord(EgtsWorkerEnvironment *env, uint8_t *subRecRaw) {
env->subRecType = subRecRaw[0];
env->subRecLength = *((uint16_t *) (subRecRaw + 1));
env->subRecData = subRecRaw + 3;
env->srNotificationData = NULL;
env->srCommand = NULL;
if (env->recSourceService == EGTS_COMMANDS_SERVICE) {
env->srCommand = &env->subRecMemAlloc.cmd;
EgtsParseSrvSubRecordSrCommand(env);
} else if (env->recSourceService == EGTS_NOTIFICATION_SERVICE) {
switch (env->subRecType) {
case EGTS_SR_NOTIFICATION_DATA:
env->srNotificationData = &env->subRecMemAlloc.notificationData;
EgtsParseSrvNotificationData(env->subRecData, env->srNotificationData);
break;
case EGTS_SR_NOTIFICATION_FULL_DATA:
// LOG("EGTS_SR_NOTIFICATION_FULL_DATA")
break;
}
} else {
// LOG("UNKNOWN EGTS SERVICE, CODE: ")
}
}
void EgtsParseSrvRecord(EgtsWorkerEnvironment *env) {
env->recordLength = *((uint16_t *) env->record);
env->recordNumber = *((uint16_t *) (env->record + 2));
env->recordFlags = env->record[4];
env->recHasTime = env->recordFlags & 0b00000100 ? true : false;
env->recHasEvent = env->recordFlags & 0b00000010 ? true : false;
env->recHasObj = env->recordFlags & 0b00000001 ? true : false;
uint8_t variableOffset = (env->recHasTime ? 4 : 0) + (env->recHasEvent ? 4 : 0) + (env->recHasObj ? 4 : 0);
env->recSourceService = env->record[5 + variableOffset];
env->recRecipientService = env->record[6 + variableOffset];
env->recordData = env->record + 7 + variableOffset;
EgtsParseSrvSubRecord(env, env->recordData);
}

282
Src/egtsWorkerExt.c Normal file
View File

@ -0,0 +1,282 @@
//
// Created by cfif on 18.05.2024.
//
#include "egtsWorkerExt.h"
#include "egts_crc.h"
#include "string.h"
#define EGTS_STATIC_HEADER_EXT_LENGTH 11
bool EgtsParseHeaderExt(EgtsWorkerEnvironment *env) {
// uint8_t protocol;
// uint8_t SecKeyID;
// uint8_t flags;
// uint16_t length;
// uint8_t encoding;
// uint16_t id;
// uint8_t type;
// uint8_t crc;
env->header.protocol = *env->workingBuffer;
env->header.SecKeyID = *(env->workingBuffer + 1);
env->header.flags = *(env->workingBuffer + 2);
env->header.headerLength = *(uint8_t *) (env->workingBuffer + 3);
env->header.encoding = *(env->workingBuffer + 4);
env->header.frameDataLength = *(uint16_t *) (env->workingBuffer + 5);
env->header.packetId = *(uint16_t *) (env->workingBuffer + 7);
env->header.type = *(uint8_t *) (env->workingBuffer + 9);
env->header.crc = *(env->workingBuffer + 10);
if (env->header.protocol != 1)
return false;
uint8_t crc = CRC8EGTS((uint8_t *) &env->header, 10);//Header CRC
if (crc != env->header.crc)
return false;
return true;
}
void EgtsParseSrvSubRecordSrCommandExt(EgtsWorkerEnvironment *env) {
uint16_t inRecOffset = 0;
env->srCommand->cmdType = *((uint8_t *) env->subRecData + inRecOffset) >> 0x4;
env->srCommand->cmdConfirmationType = *((uint8_t *) env->subRecData + inRecOffset) & 0b1111;
inRecOffset += 1;
env->srCommand->cmdId = *((uint32_t *) (env->subRecData + inRecOffset));
inRecOffset += 4;
env->srCommand->srcId = *((uint32_t *) (env->subRecData + inRecOffset));
inRecOffset += 4;
uint8_t flags = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
env->srCommand->hasCharset = flags & 0b1;
env->srCommand->hasAuth = (flags >> 0x1) & 0b1;
if (env->srCommand->hasCharset) {
env->srCommand->charset = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
}
if (env->srCommand->hasAuth) {
env->srCommand->authLen = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
memcpy(env->srCommand->auth, (env->subRecData + inRecOffset), env->srCommand->authLen);
inRecOffset += env->srCommand->authLen;
}
env->srCommand->address = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
uint8_t actFlags = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
env->srCommand->act = actFlags & 0xF;
env->srCommand->size = (actFlags >> 0x4) & 0xF;
env->srCommand->cmd = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
env->srCommand->dataPointer = (env->subRecData + inRecOffset);
}
void EgtsParseSrvSubRecordFirmwareExt(EgtsWorkerEnvironment *env) {
uint16_t inRecOffset = 0;
env->firmware->Identity = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
env->firmware->PartNumber = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
env->firmware->ExpectedPartsQuantity = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
if (env->firmware->PartNumber == 1) {
uint8_t OA = *((uint8_t *) (env->subRecData + inRecOffset));
((uint8_t *) ((uint8_t *) &env->firmware->ObjectAttribute))[0] = OA;
inRecOffset += 1;
env->firmware->ComponentOrModuleIdentifier = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
env->firmware->Version = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
env->firmware->WholeObjectSignature = *((uint16_t *) (env->subRecData + inRecOffset));
inRecOffset += 2;
for (size_t i = 0; i < 64 + 1; ++i) {
env->firmware->FileName[i] = *((uint8_t *) (env->subRecData + inRecOffset));
inRecOffset += 1;
if (env->firmware->FileName[i] == 0)
break;
}
}
env->firmware->dataPointer = env->subRecData + inRecOffset;
env->firmware->dataLength = env->subRecLength - inRecOffset;
}
void EgtsParseSrvSubRecordExt(EgtsWorkerEnvironment *env, uint8_t *subRecRaw) {
env->subRecType = subRecRaw[0];
env->subRecLength = *((uint16_t *) (subRecRaw + 1));
env->subRecData = subRecRaw + 3;
env->srNotificationData = NULL;
env->srCommand = NULL;
if (env->recSourceService == EGTS_COMMANDS_SERVICE) {
env->srCommand = &env->subRecMemAlloc.cmd;
EgtsParseSrvSubRecordSrCommandExt(env);
} else if (env->recSourceService == EGTS_FIRMWARE_SERVICE) {
env->firmware = &env->subRecMemAlloc.firmware;
EgtsParseSrvSubRecordFirmwareExt(env);
} else if (env->recSourceService == EGTS_NOTIFICATION_SERVICE) {
switch (env->subRecType) {
case EGTS_SR_NOTIFICATION_DATA:
env->srNotificationData = &env->subRecMemAlloc.notificationData;
EgtsParseSrvNotificationData(env->subRecData, env->srNotificationData);
break;
case EGTS_SR_NOTIFICATION_FULL_DATA:
// LOG("EGTS_SR_NOTIFICATION_FULL_DATA")
break;
}
} else {
// LOG("UNKNOWN EGTS SERVICE, CODE: ")
}
}
uint16_t EgtsParseSrvRecordExt(EgtsWorkerEnvironment *env, uint8_t *record) {
env->recordLength = *((uint16_t *) record);
env->recordNumber = *((uint16_t *) (record + 2));
env->recordFlags = record[4];
env->recHasTime = env->recordFlags & 0b00000100 ? true : false;
env->recHasEvent = env->recordFlags & 0b00000010 ? true : false;
env->recHasObj = env->recordFlags & 0b00000001 ? true : false;
uint8_t variableOffset = (env->recHasTime ? 4 : 0) + (env->recHasEvent ? 4 : 0) + (env->recHasObj ? 4 : 0);
env->recSourceService = record[5 + variableOffset];
env->recRecipientService = record[6 + variableOffset];
env->recordData = record + 7 + variableOffset;
EgtsParseSrvSubRecordExt(env, env->recordData);
// 3 - env->subRecType + env->subRecLength
return 7 + variableOffset + 3 + env->subRecLength;
}
EgtsCompleteResult egtsCompleteResult;
EgtsCompleteResult *EgtsCompleteTransportExt(EgtsWorkerEnvironment *env) {
uint16_t read;
if (env->workingBufferLength < EGTS_STATIC_HEADER_EXT_LENGTH) {
read = env->readData(
env->readDataEnv,
env->workingBuffer + env->workingBufferLength,
EGTS_STATIC_HEADER_EXT_LENGTH - env->workingBufferLength
);
env->workingBufferLength += read;
if (env->workingBufferLength < EGTS_STATIC_HEADER_EXT_LENGTH) {
egtsCompleteResult.completeResult = EGTS_COMPLETE_WAIT;
return &egtsCompleteResult;
}
if (env->workingBuffer[0] != 1) {
env->workingBufferLength = 0;
egtsCompleteResult.completeResult = EGTS_COMPLETE_ERR_VER;
return &egtsCompleteResult;
}
uint8_t crc = CRC8EGTS(env->workingBuffer, EGTS_STATIC_HEADER_EXT_LENGTH - 1); //Header CRC
if (crc != env->workingBuffer[EGTS_STATIC_HEADER_EXT_LENGTH - 1]) {
env->workingBufferLength = 0;
egtsCompleteResult.calcHeaderCrc = crc;
egtsCompleteResult.receivedHeaderCrc = env->workingBuffer[EGTS_STATIC_HEADER_EXT_LENGTH - 1];
egtsCompleteResult.completeResult = EGTS_COMPLETE_HEADER_ERR_CRC;
return &egtsCompleteResult;
}
}
uint16_t fullLength = EgtsGetTransportFullLength(env);
// Переполнение приемного буфера
if ((env->workingBufferLength + fullLength) >= env->workingBufferLimit) {
egtsCompleteResult.completeResult = EGTS_COMPLETE_ERR_OVERFLOW;
env->workingBufferLength = 0;
return &egtsCompleteResult;
}
if (env->workingBufferLength < fullLength) {
read = env->readData(
env->readDataEnv,
env->workingBuffer + env->workingBufferLength,
fullLength - env->workingBufferLength
);
env->workingBufferLength += read;
if (env->workingBufferLength < fullLength) {
egtsCompleteResult.completeResult = EGTS_COMPLETE_WAIT;
return &egtsCompleteResult;
}
uint16_t crc = CRC16EGTS(env->workingBuffer + EGTS_STATIC_HEADER_EXT_LENGTH,
fullLength - EGTS_STATIC_HEADER_EXT_LENGTH - 2);
uint16_t crcBody = *(uint16_t *) &env->workingBuffer[fullLength - 2];
if (crc != crcBody) {
env->workingBufferLength = 0;
egtsCompleteResult.fullLength = fullLength;
egtsCompleteResult.calcBodyCrc = crc;
egtsCompleteResult.receivedBodyCrc = crcBody;
egtsCompleteResult.completeResult = EGTS_COMPLETE_BODY_ERR_CRC;
return &egtsCompleteResult;
}
}
egtsCompleteResult.completeResult = EGTS_COMPLETE_OK;
return &egtsCompleteResult;
}
eEgts_CompleteResult EgtsIsTransportCompleteExt(EgtsWorkerEnvironment *env) {
if (env->workingBufferLength < EGTS_STATIC_HEADER_EXT_LENGTH) {
return EGTS_COMPLETE_WAIT;
}
uint16_t fullLength = EgtsGetTransportFullLength(env);
if (env->workingBufferLength < fullLength) {
return EGTS_COMPLETE_WAIT;
}
return EGTS_COMPLETE_OK;
}

116
Src/egts_common.c Normal file
View File

@ -0,0 +1,116 @@
/*
* egts.c
*
* Created on: Jun 4, 2021
* Author: zemon
*/
#include "egts.h"
#include "egts_crc.h"
#include "string.h"
#define EGTS_TIMESTAMP_EPOCH_OFFSET 1262304000 // epoch timestamp of Fri, 01 Jan 2010 00:00:00 GMT
uint32_t toEgtsTimestamp(uint32_t ts) {
return ts - EGTS_TIMESTAMP_EPOCH_OFFSET;
}
uint16_t vEgtsPackSrv(
uint8_t *out,
uint8_t flags,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t epochTimestamp,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGenerator subRecGen,
void *subRecArgs
) {
uint16_t subRecordLength = subRecGen(out + 14, subRecArgs);
*(uint16_t *) (out + 0) = subRecordLength + 3; //data length
*(uint16_t *) (out + 2) = 0x0001; //counter
////////////////////////////////////////////////////////////////////////////////////////////////////////
// | flags |
// Sender Rcver Group Prior hasTime hasEvntID hasObjId
// DEV SRV None value exist not not
// 1 0 0 10 1 0 0 => 10010100 => 0x94
out[4] = flags;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//time
*(uint32_t *) (out + 5) = toEgtsTimestamp(epochTimestamp);
//SourceServType
*(uint8_t *) (out + 9) = (uint8_t) sourceServiceId;
//RecipientServType
*(uint8_t *) (out + 10) = (uint8_t) recipientServiceId;
//SRT
*(uint8_t *) (out + 11) = subRecordType; //(uint8_t) SRT;
//SRL
*(uint16_t *) (out + 12) = subRecordLength;
return subRecordLength + 14;
}
uint16_t vEgtsPackTransport(
uint16_t cid,
uint16_t packetId,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGenerator subRecGen,
void *subRecArgs
) {
uint8_t ptOffset = 0;
if (packetTypeId == EGTS_PT_RESPONSE) {
ptOffset = 3;
}
uint16_t srvLen = ptOffset + vEgtsPackSrv(
out + TRANSPORT_HEADER_LENGTH+ptOffset,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordType,
subRecGen,
subRecArgs
);
out[0] = 0x01;//version
out[1] = 0x00;//secure key
out[2] = 0x01;//flags
out[3] = 0x0B;//header length
out[4] = 0x00;//header encoding
*((uint16_t *) (out + 5)) = srvLen;
*((uint16_t *) (out + 7)) = packetId;//package Id
out[9] = packetTypeId;//Packet type
out[10] = CRC8EGTS(out, 10);//Header CRC
if (packetTypeId == EGTS_PT_RESPONSE) {
*((uint16_t *) (out + 11)) = cid;// response packet id
out[13] = 0b0000;//Packet type
}
*((uint16_t *) (out + TRANSPORT_HEADER_LENGTH + srvLen)) = CRC16EGTS(out + TRANSPORT_HEADER_LENGTH, srvLen);
return TRANSPORT_HEADER_LENGTH + srvLen + 2;
}

458
Src/egts_commonExt.c Normal file
View File

@ -0,0 +1,458 @@
//
// Created by cfif on 22.04.2024.
//
#include "egts_commonExt.h"
#include "EgtsTimestamp.h"
uint16_t vEgtsPackSrvEx(
uint8_t *out,
uint16_t counter,
uint8_t flags,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t epochTimestamp,
uint16_t subRecordCount,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGeneratorEx subRecGen,
void *subRecArgs
) {
uint16_t subRecordLengthFull = 0;
// 3 - Для SRT + SRT
// 11 - Заголовок
uint16_t subRecordLengthOffsetHeader = 11;
bool isPresentSubRecord = false;
for (uint16_t i = 0; i < subRecordCount; ++i) {
uint16_t subRecordLength = subRecGen(out + subRecordLengthOffsetHeader + 3, subRecArgs, i);
if (subRecordLength > 0) {
isPresentSubRecord = true;
subRecordLengthFull += (subRecordLength + 3);
//SRT
*(uint8_t *) (out + subRecordLengthOffsetHeader) = subRecordType;
//SRL
*(uint16_t *) (out + subRecordLengthOffsetHeader + 1) = subRecordLength;
subRecordLengthOffsetHeader += (subRecordLength + 3);
}
}
if (!isPresentSubRecord)
return 0;
// uint16_t subRecordLength = subRecGen(out + 14, subRecArgs);
// *(uint16_t *) (out + 0) = subRecordLength + 3; //data length
*(uint16_t *) (out + 0) = subRecordLengthFull;
*(uint16_t *) (out + 2) = counter; //counter
////////////////////////////////////////////////////////////////////////////////////////////////////////
// | flags |
// Sender Rcver Group Prior hasTime hasEvntID hasObjId
// DEV SRV None value exist not not
// 1 0 0 10 1 0 0 => 10010100 => 0x94
out[4] = flags;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//time
*(uint32_t *) (out + 5) = Egts_EpochTimestampToEgtsTime(epochTimestamp);
//SourceServType
*(uint8_t *) (out + 9) = (uint8_t) sourceServiceId;
//RecipientServType
*(uint8_t *) (out + 10) = (uint8_t) recipientServiceId;
//SRT
// *(uint8_t *) (out + 11) = subRecordType; //(uint8_t) SRT;
//SRL
// *(uint16_t *) (out + 12) = subRecordLength;
// return subRecordLength + 14;
return subRecordLengthFull + 11;
}
uint16_t vEgtsPackTransportEx1(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount,
eEgtsSubRecordId subRecordType,
tEgtsServiceSubRecordGeneratorEx subRecGen,
void *subRecArgs
) {
uint8_t ptOffset = 0;
if (packetTypeId == EGTS_PT_RESPONSE) {
ptOffset = 3;
}
uint16_t srvLen = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount,
subRecordType,
subRecGen,
subRecArgs
);
++*counter;
out[0] = 0x01;//version
out[1] = 0x00;//secure key
out[2] = 0x01;//flags
out[3] = 0x0B;//header length
out[4] = 0x00;//header encoding
*((uint16_t *) (out + 5)) = srvLen;
*((uint16_t *) (out + 7)) = packetId;//package Id
out[9] = packetTypeId;//Packet type
out[10] = CRC8EGTS(out, 10);//Header CRC
if (packetTypeId == EGTS_PT_RESPONSE) {
*((uint16_t *) (out + 11)) = cid;// response packet id
out[13] = 0b0000;//Packet type
}
*((uint16_t *) (out + TRANSPORT_HEADER_LENGTH + srvLen)) = CRC16EGTS(out + TRANSPORT_HEADER_LENGTH, srvLen);
return TRANSPORT_HEADER_LENGTH + srvLen + 2;
}
uint16_t vEgtsPackTransportEx2(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount1,
eEgtsSubRecordId subRecordType1,
tEgtsServiceSubRecordGeneratorEx subRecGen1,
void *subRecArgs1,
uint16_t subRecordCount2,
eEgtsSubRecordId subRecordType2,
tEgtsServiceSubRecordGeneratorEx subRecGen2,
void *subRecArgs2
) {
uint8_t ptOffset = 0;
if (packetTypeId == EGTS_PT_RESPONSE) {
ptOffset = 3;
}
uint16_t srvLen1 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount1,
subRecordType1,
subRecGen1,
subRecArgs1
);
++*counter;
uint16_t srvLen2 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + srvLen1 + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount2,
subRecordType2,
subRecGen2,
subRecArgs2
);
++*counter;
uint16_t srvLen = srvLen1 + srvLen2;
out[0] = 0x01;//version
out[1] = 0x00;//secure key
out[2] = 0x01;//flags
out[3] = 0x0B;//header length
out[4] = 0x00;//header encoding
*((uint16_t *) (out + 5)) = srvLen;
*((uint16_t *) (out + 7)) = packetId;//package Id
out[9] = packetTypeId;//Packet type
out[10] = CRC8EGTS(out, 10);//Header CRC
if (packetTypeId == EGTS_PT_RESPONSE) {
*((uint16_t *) (out + 11)) = cid;// response packet id
out[13] = 0b0000;//Packet type
}
*((uint16_t *) (out + TRANSPORT_HEADER_LENGTH + srvLen)) = CRC16EGTS(out + TRANSPORT_HEADER_LENGTH, srvLen);
return TRANSPORT_HEADER_LENGTH + srvLen + 2;
}
uint16_t vEgtsPackTransportEx3(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount1,
eEgtsSubRecordId subRecordType1,
tEgtsServiceSubRecordGeneratorEx subRecGen1,
void *subRecArgs1,
uint16_t subRecordCount2,
eEgtsSubRecordId subRecordType2,
tEgtsServiceSubRecordGeneratorEx subRecGen2,
void *subRecArgs2,
uint16_t subRecordCount3,
eEgtsSubRecordId subRecordType3,
tEgtsServiceSubRecordGeneratorEx subRecGen3,
void *subRecArgs3
) {
uint8_t ptOffset = 0;
if (packetTypeId == EGTS_PT_RESPONSE) {
ptOffset = 3;
}
uint16_t srvLen1 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount1,
subRecordType1,
subRecGen1,
subRecArgs1
);
++*counter;
uint16_t srvLen2 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + srvLen1 + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount2,
subRecordType2,
subRecGen2,
subRecArgs2
);
++*counter;
uint16_t srvLen3 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + srvLen1 + srvLen2 + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount3,
subRecordType3,
subRecGen3,
subRecArgs3
);
++*counter;
uint16_t srvLen = srvLen1 + srvLen2 + srvLen3;
out[0] = 0x01;//version
out[1] = 0x00;//secure key
out[2] = 0x01;//flags
out[3] = 0x0B;//header length
out[4] = 0x00;//header encoding
*((uint16_t *) (out + 5)) = srvLen;
*((uint16_t *) (out + 7)) = packetId;//package Id
out[9] = packetTypeId;//Packet type
out[10] = CRC8EGTS(out, 10);//Header CRC
if (packetTypeId == EGTS_PT_RESPONSE) {
*((uint16_t *) (out + 11)) = cid;// response packet id
out[13] = 0b0000;//Packet type
}
*((uint16_t *) (out + TRANSPORT_HEADER_LENGTH + srvLen)) = CRC16EGTS(out + TRANSPORT_HEADER_LENGTH, srvLen);
return TRANSPORT_HEADER_LENGTH + srvLen + 2;
}
uint16_t vEgtsPackTransportEx4(
uint16_t cid,
uint16_t packetId,
uint16_t *counter,
uint8_t *out,
uint8_t srvFlags,
eEgtsPacketTypeId packetTypeId,
eEgtsServiceId sourceServiceId,
eEgtsServiceId recipientServiceId,
uint32_t timestamp,
uint16_t subRecordCount1,
eEgtsSubRecordId subRecordType1,
tEgtsServiceSubRecordGeneratorEx subRecGen1,
void *subRecArgs1,
uint16_t subRecordCount2,
eEgtsSubRecordId subRecordType2,
tEgtsServiceSubRecordGeneratorEx subRecGen2,
void *subRecArgs2,
uint16_t subRecordCount3,
eEgtsSubRecordId subRecordType3,
tEgtsServiceSubRecordGeneratorEx subRecGen3,
void *subRecArgs3,
uint16_t subRecordCount4,
eEgtsSubRecordId subRecordType4,
tEgtsServiceSubRecordGeneratorEx subRecGen4,
void *subRecArgs4
) {
uint8_t ptOffset = 0;
if (packetTypeId == EGTS_PT_RESPONSE) {
ptOffset = 3;
}
uint16_t srvLen1 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount1,
subRecordType1,
subRecGen1,
subRecArgs1
);
++*counter;
uint16_t srvLen2 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + srvLen1 + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount2,
subRecordType2,
subRecGen2,
subRecArgs2
);
++*counter;
uint16_t srvLen3 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + srvLen1 + srvLen2 + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount3,
subRecordType3,
subRecGen3,
subRecArgs3
);
++*counter;
uint16_t srvLen4 = ptOffset + vEgtsPackSrvEx(
out + TRANSPORT_HEADER_LENGTH + srvLen1 + srvLen2 + srvLen3 + ptOffset,
*counter,
srvFlags,
sourceServiceId,
recipientServiceId,
timestamp,
subRecordCount4,
subRecordType4,
subRecGen4,
subRecArgs4
);
++*counter;
uint16_t srvLen = srvLen1 + srvLen2 + srvLen3 + srvLen4;
out[0] = 0x01;//version
out[1] = 0x00;//secure key
out[2] = 0x01;//flags
out[3] = 0x0B;//header length
out[4] = 0x00;//header encoding
*((uint16_t *) (out + 5)) = srvLen;
*((uint16_t *) (out + 7)) = packetId;//package Id
out[9] = packetTypeId;//Packet type
out[10] = CRC8EGTS(out, 10);//Header CRC
if (packetTypeId == EGTS_PT_RESPONSE) {
*((uint16_t *) (out + 11)) = cid;// response packet id
out[13] = 0b0000;//Packet type
}
*((uint16_t *) (out + TRANSPORT_HEADER_LENGTH + srvLen)) = CRC16EGTS(out + TRANSPORT_HEADER_LENGTH, srvLen);
return TRANSPORT_HEADER_LENGTH + srvLen + 2;
}

128
Src/egts_crc.c Normal file
View File

@ -0,0 +1,128 @@
/*
* egts_crc.c
*
* Created on: Oct 2, 2020
* Author: FICOM-IT LTD
*/
#include "egts_crc.h"
const uint16_t Crc16Table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
uint16_t egts_crc16( uint8_t *data, uint16_t len )
{
uint16_t crc = 0xFFFF;
while (len--)
crc = (crc << 8) ^ Crc16Table[(crc >> 8) ^ *data++];
return crc;
}
/*
Name : CRC-8
Poly : 0x31 x^8 + x^5 + x^4 + 1
Init : 0xFF
Revert: false
XorOut: 0x00
Check : 0xF7 ("123456789")
*/
const uint8_t CRC8Table[256] = {
0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97,
0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E,
0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4,
0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D,
0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11,
0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8,
0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52,
0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB,
0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA,
0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13,
0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9,
0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50,
0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C,
0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95,
0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F,
0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6,
0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED,
0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54,
0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE,
0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17,
0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B,
0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2,
0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28,
0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91,
0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0,
0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69,
0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93,
0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A,
0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56,
0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF,
0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15,
0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC
};
/*
Name : CRC-8
Poly : 0x31 x^8 + x^5 + x^4 + 1
Init : 0xFF
Revert: false
XorOut: 0x00
Check : 0xF7 ("123456789")
*/
uint8_t CRC8EGTS(unsigned char *lpBlock, unsigned char len)
{
unsigned char crc = 0xFF;
while (len--)
crc = CRC8Table[crc ^ *lpBlock++];
return crc;
}
//------------------------------------------------------------------------------
/*
Name : CRC-16 CCITT
Poly : 0x1021 x^16 + x^12 + x^5 + 1
Init : 0xFFFF
Revert: false
XorOut: 0x0000
Check : 0x29B1 ("123456789")
*/
uint16_t CRC16EGTS(unsigned char * pcBlock, unsigned int len)
{
unsigned short crc = 0xFFFF;
while (len--)
crc = (crc << 8) ^ Crc16Table[(crc >> 8) ^ *pcBlock++];
return crc;
}
//------------------------------------------------------------------------------

52
Src/egts_europrotocol.c Normal file
View File

@ -0,0 +1,52 @@
//
// Created by zemon on 11.02.2022.
//
#include "egts.h"
//#include "BitOps.h"
#include "BitBuffer.h"
uint16_t vEgtsPackTrackData(uint8_t *out, uint16_t bitsOffset, tEgtsTrackData *trackData) {
bitsOffset += vBitBufferAppendByte(out, bitsOffset, trackData->LOHS ? 0b1 : 0b0, 1);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, trackData->LAHS ? 0b1 : 0b0, 1);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &trackData->speed)[1], 5);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, trackData->TrackDataExist ? 0b1 : 0b0, 1);
bitsOffset += vBitBufferAppendBitsReverseBytes(out, bitsOffset, (uint8_t *) &trackData->Latitude, 32);
bitsOffset += vBitBufferAppendBitsReverseBytes(out, bitsOffset, (uint8_t *) &trackData->Longitude, 32);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &trackData->speed)[0], 8);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &trackData->Altitude)[0], 8);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &trackData->Direction)[1], 1);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, trackData->AltitudeDirection ? 0b1 : 0b0, 1);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &trackData->Altitude)[1], 6);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &trackData->Direction)[0], 8);
}
uint16_t vEgtsPackSrEpTrackData(uint8_t *out, tEgtsSrEpTrackDataArgs *args) {
uint16_t bitsOffset = 0;
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &args->blockNumber)[0], 8);
bitsOffset += vBitBufferAppendBitsReverseBytes(out, bitsOffset, (uint8_t *) &args->absoluteTime, 32);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, args->relativeAmount, 8);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, args->timeShift, 4);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, args->CoordinateSystem ? 0b1 : 0b0, 1);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, ((uint8_t *) &args->blockNumber)[1], 2);
bitsOffset += vBitBufferAppendByte(out, bitsOffset, args->RTU ? 0b1 : 0b0, 1);
bitsOffset += vEgtsPackTrackData(out, bitsOffset, &args->originPoint);
return (bitsOffset / 8) + ((bitsOffset % 8) ? 1 : 0) + args->relativeAmount;
}

51
Src/egts_msd.c Normal file
View File

@ -0,0 +1,51 @@
/*
* egts.c
*
* Created on: Jun 4, 2021
* Author: zemon
*/
#include "egts.h"
#include "egts_crc.h"
#include "string.h"
uint16_t vEgtsPackMsdData(uint8_t *out, tEgtsMsdDataArgs *args) {
out[0] = EGTS_SR_RAW_MSD_DATA;
*(uint16_t *) (out + 1) = args->msdLength + 1;//+ 1 phantom
//Phantom Byte
*(uint8_t *) (out + 0) = 0x01;
memcpy(out + 1, args->msd, args->msdLength);
return args->msdLength + 1;
}
//
//uint16_t vEgtsPackMsdDataGen(uint8_t *out, void *args) {
// return vEgtsPackMsdData(out, (tEgtsMsdDataArgs *) args);
//}
uint16_t vEgtsPackMsdTransport(uint16_t packetId, uint8_t *out, uint8_t *msd, uint8_t msdLength, uint32_t timestamp) {
tEgtsMsdDataArgs args = {
.msdLength = msdLength,
.msd = msd,
};
return vEgtsPackTransport(
0,
packetId,
out,
EGTS_SERVICE_FLAGS_MSD,
EGTS_PT_APPDATA,
EGTS_ECALL_SERVICE,
EGTS_ECALL_SERVICE,
timestamp,
EGTS_SR_RAW_MSD_DATA,
// SRL,
// SRT,
vEgtsPackMsdDataGen,
&args
);
}

314
Src/egts_teledata.c Normal file
View File

@ -0,0 +1,314 @@
/*
* egts.c
*
* Created on: Jun 4, 2021
* Author: zemon
*/
#include "egts.h"
#include "egts_crc.h"
#include "string.h"
#include "stdint.h"
#include "math.h"
#include "egtsWorker.h"
#define ADD_TO_RESULT(DATA, LEN) memcpy(out + offset, (uint8_t * ) & DATA, LEN); offset+=LEN;
//flags
const uint8_t flags = 0b10000001;
//const uint16_t SPD = 50;
const uint8_t DIR = 0;
const uint32_t ODR = 0x000000;
const uint8_t DIN = 0;
const uint8_t SRC = 16;
const uint32_t ALT = 0x00;
//uint16_t vEgtsPackPosDataGen(uint8_t *out, void *args) {
// tEgtsPosDataArgs *posDataArgs = (tEgtsPosDataArgs *) args;
// return vEgtsPackPosData(out, posDataArgs);
//}
uint16_t vEgtsPackPosData(uint8_t *out, tEgtsPosDataArgs *args) {
uint32_t NTM = toEgtsTimestamp(args->epochTimestamp);
double lat = (fabs(args->latitude) / 90) * 0xFFFFFFFF;
double lon = (fabs(args->longitude) / 180) * 0xFFFFFFFF;
uint32_t LAT = (uint32_t) lat;
uint32_t LONG = (uint32_t) lon;
uint16_t offset = 0;
ADD_TO_RESULT(NTM, 4);
ADD_TO_RESULT(LAT, 4);
ADD_TO_RESULT(LONG, 4);
ADD_TO_RESULT(flags, 1);
ADD_TO_RESULT(args->velocity, 2);
ADD_TO_RESULT(DIR, 1);
ADD_TO_RESULT(ODR, 3);
ADD_TO_RESULT(DIN, 1);
ADD_TO_RESULT(SRC, 1);
ADD_TO_RESULT(ALT, 3);
return offset;
}
uint16_t vEgtsPackSensorsData(uint8_t *out, tEgtsSensorsDataArgs *args) {
uint16_t offset = 0;
ADD_TO_RESULT(args->digitalInPresent, 1);
ADD_TO_RESULT(args->digitalOutPresent, 1);
ADD_TO_RESULT(args->analogInPresent, 1);
for (uint16_t i = 0; i < 8; ++i) {
uint8_t mask = 0x1 << i;
if (args->digitalInPresent & mask) {
ADD_TO_RESULT(args->digitalIn[i], 1);
}
}
for (uint16_t i = 0; i < 8; ++i) {
uint8_t mask = 0x1 << i;
if (args->analogInPresent & mask) {
ADD_TO_RESULT(args->analogIn[i], 3);
}
}
return offset;
}
//uint32_t TID = 4168809385;
uint8_t TermIdentityFlags = 0b01000010;
//unit16_t TermIdentityHDID = ;
//unit32_t TermIdentityNID = ;
uint16_t TermIdentityBS = 512;
//uint16_t vEgtsPackTermIdentityGen(uint8_t *out, void *args) {
// tEgtsTermIdentityArgs *termIdentityArgs = (tEgtsTermIdentityArgs *) args;
// return vEgtsPackTermIdentity(out, termIdentityArgs);
//}
uint16_t vEgtsPackTermIdentity(uint8_t *out, tEgtsTermIdentityArgs *args) {
uint16_t offset = 0;
ADD_TO_RESULT(args->TerminalID, 4);
ADD_TO_RESULT(TermIdentityFlags, 1);
ADD_TO_RESULT((*args->IMEI), args->IMEI_len);
ADD_TO_RESULT(TermIdentityBS, 2);
return offset;
}
uint16_t vEgtsPackResponse(uint8_t *out, tEgtsRecordResponseData *args) {
uint16_t offset = 0;
ADD_TO_RESULT(args->CRN, 2);
ADD_TO_RESULT(args->RST, 1);
return offset;
}
uint16_t vEgtsPacSrCommandDataResponse(uint8_t *out, tEgtsSrCmdConfirmation *args) {
uint16_t offset = 0;
uint8_t flag = (args->CT << 0x4) | (args->CCT & 0xF);
ADD_TO_RESULT(flag, 1);
ADD_TO_RESULT(args->CID, 4);
ADD_TO_RESULT(args->SID, 4);
uint8_t hasFlags = (args->ACFE << 0x1) | (args->CHSFE & 0x1);
ADD_TO_RESULT(hasFlags, 1);
if (args->CHSFE) {
ADD_TO_RESULT(args->CHS, 1);
}
if (args->ACFE) {
ADD_TO_RESULT(args->ACL, 1);
ADD_TO_RESULT(args->AC, 4);
}
if ((args->CT == CT_COMCONF) && (args->CCT == CC_OK)) {
ADD_TO_RESULT(args->CmdData.ADR, 2);
uint8_t flagComData = (args->CmdData.SZ << 0x4) | (args->CmdData.ACT & 0xF);
ADD_TO_RESULT(flagComData, 1);
ADD_TO_RESULT(args->CmdData.CCD, 2);
}
if (args->CmdData.DT) {
//todo?
}
return offset;
}
uint16_t vEgtsPackTeledataTransport(
uint16_t packetId,
uint8_t *out,
double latitude,
double longitude,
uint16_t velocity,
uint32_t epochTimestamp
) {
tEgtsPosDataArgs args = {
.longitude = longitude,
.latitude = latitude,
.velocity = velocity,
.epochTimestamp = epochTimestamp,
};
return vEgtsPackTransport(
0,
packetId,
out,
EGTS_SERVICE_FLAGS_POS,
EGTS_PT_APPDATA,
EGTS_TELEDATA_SERVICE,
EGTS_TELEDATA_SERVICE,
epochTimestamp,
EGTS_SR_POS_DATA,
vEgtsPackPosDataGen,
&args
);
// return vEgtsPackPosData(out, &args);
}
uint16_t vEgtsPackSensorsTransport(
uint16_t packetId,
uint8_t *out,
uint32_t epochTimestamp,
tEgtsSensorsDataArgs *sensors
) {
return vEgtsPackTransport(
0,
packetId,
out,
EGTS_SERVICE_FLAGS_POS,
EGTS_PT_APPDATA,
EGTS_TELEDATA_SERVICE,
EGTS_TELEDATA_SERVICE,
epochTimestamp,
EGTS_SR_AD_SENSORS_DATA,
vEgtsPackSensorsDataGen,
sensors
);
// return vEgtsPackPosData(out, &args);
}
uint16_t vEgtsPackTermIdentityTransport(
uint16_t packetId,
uint8_t *out,
uint8_t *IMEI,
uint8_t IMEI_len,
uint32_t TerminalID,
uint32_t epochTimestamp
) {
tEgtsTermIdentityArgs args = {
.IMEI = IMEI,
.IMEI_len = IMEI_len,
.TerminalID = TerminalID,
// .epochTimestamp = epochTimestamp,
};
return vEgtsPackTransport(
0,
packetId,
out,
EGTS_SERVICE_FLAGS_AUTH,
EGTS_PT_APPDATA,
EGTS_AUTH_SERVICE,
EGTS_AUTH_SERVICE,
epochTimestamp,
EGTS_SR_TERM_IDENTITY,
vEgtsPackTermIdentityGen,
&args
);
// return vEgtsPackPosData(out, &args);
}
uint16_t
vEgtsPackEgtsResponse(uint16_t packetId, uint8_t *out, uint8_t rst, uint16_t crn, uint16_t cid, uint32_t timestamp) {
tEgtsRecordResponseData args = {
.CRN = crn,
.RST = rst,
};
return vEgtsPackTransport(
cid,
packetId,
out,
EGTS_SERVICE_FLAGS_POS,
EGTS_PT_RESPONSE,
EGTS_ECALL_SERVICE,
EGTS_ECALL_SERVICE,
timestamp,
EGTS_SR_RECORD_RESPONSE,
vEgtsPackResponseGen,
&args
);
}
uint16_t vEgtsPackSrCmdConfirmation(
uint8_t *out,
uint16_t packetId,
uint16_t cmdType,
uint16_t cmdConfirType,
uint16_t cid,
uint16_t sid,
uint16_t acfe,
uint16_t chsfe,
uint16_t adr,
uint8_t sz,
uint8_t act,
uint16_t ccd,
uint32_t dt
) {
bool authCodeExist = false;
bool charsetExist = false;
tEgtsSrCmdConfirmation args = {
.CT = cmdType,
.CCT = cmdConfirType,
.CID = cid,
.SID = sid,
.ACFE = acfe,
.CHSFE = chsfe,
.CmdData.ADR = adr,
.CmdData.SZ = sz,
.CmdData.ACT = act,
.CmdData.CCD = ccd,
.CmdData.DT = dt,
};
return vEgtsPackTransport(
0,
packetId,
out,
EGTS_SERVICE_FLAGS_POS,
EGTS_PT_APPDATA,
EGTS_COMMANDS_SERVICE,
EGTS_COMMANDS_SERVICE,
0,
EGTS_SR_COMMAND_DATA,
vEgtsPacSrCommandDataResponseGen,
&args
);
}

13
Tst/CMakeLists.txt Normal file
View File

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.17)
project(Module C)
set(CMAKE_C_STANDARD 11)
include(modular.cmake)
add_executable(test_module ${SOURCES} test_module.c)
#ADD_CUSTOM_COMMAND(
# TARGET test_module POST_BUILD
# COMMAND nc -l 5020&echo ok
#)

905
Tst/egts.lua Normal file
View File

@ -0,0 +1,905 @@
-- создаем описание нового протокола
local egts_proto = Proto("egts", "EGTS")
-- настройки плагина
local default_settings = {
port = 5020
}
local EGTS_PT_RESPONSE = "EGTS_PT_RESPONSE"
local EGTS_PT_APPDATA = "EGTS_PT_APPDATA"
local EGTS_PT_SIGNED_APPDATA = "EGTS_PT_SIGNED_APPDATA"
local egts_packet_type = {
[0] = EGTS_PT_RESPONSE,
[1] = EGTS_PT_APPDATA,
[2] = EGTS_PT_SIGNED_APPDATA,
}
local egts_subrecord_type = {
[0] = "EGTS_SR_RECORD_RESPONSE",
[1] = "EGTS_SR_TERM_IDENTITY",
[9] = "EGTS_SR_RESULT_CODE",
[15] = "EGTS_SR_EGTSPLUS_DATA",
[16] = "EGTS_SR_POS_DATA",
[17] = "EGTS_SR_EXT_POS_DATA",
[18] = "EGTS_SR_AD_SENSORS_DATA",
[19] = "EGTS_SR_COUNTERS_DATA",
[20] = "EGTS_SR_STATE_DATA",
[22] = "EGTS_SR_LOOPIN_DATA",
[23] = "EGTS_SR_ABS_DIG_SENS_DATA",
[24] = "EGTS_SR_ABS_AN_SENS_DATA",
[25] = "EGTS_SR_ABS_CNTR_DATA",
[26] = "EGTS_SR_ABS_LOOPIN_DATA",
[27] = "EGTS_SR_LIQUID_LEVEL_SENSOR",
-- Список подзаписей сервиса EGTS_ECALL_SERVICE
--[20] = "EGTS_SR_ACCEL_DATA",
[40] = "EGTS_SR_RAW_MSD_DATA",
[62] = "EGTS_SR_TRACK_DATA",
-- Описание подзаписей сервиса EGTS_COMMAND_SERVICE
[51] = "EGTS_SR_COMМAND_DАТА",
}
local result_code = {
[0] = "EGTS_PC_OK",
[1] = "EGTS_PC_IN_PROGRESS",
[128] = "EGTS_PC_UNS_PROTOCOL",
[129] = "EGTS_PC_DECRYPT_ERROR",
[130] = "EGTS_PC_PROC_DENIED",
[131] = "EGTS_PC_INC_HEADERFORM",
[132] = "EGTS_PC_INC_DATAFORM",
[133] = "EGTS_PC_UNS_TYPE",
[134] = "EGTS_PC_NOTEN_PARAMS",
[135] = "EGTS_PC_DBL_PROC",
[136] = "EGTS_PC_PROC_SRC_DENIED",
[137] = "EGTS_PC_HEADERCRC_ERROR",
[138] = "EGTS_PC_DATACRC_ERROR",
[139] = "EGTS_PC_INVDATALEN",
[140] = "EGTS_PC_ROUTE_NFOUND",
[141] = "EGTS_PC_ROUTE_CLOSED",
[142] = "EGTS_PC_ROUTE_DENIED",
[143] = "EGTS_PC_INVADDR",
[144] = "EGTS_PC_TTLEXPIRED",
[145] = "EGTS_PC_NO_ACK",
[146] = "EGTS_PC_OBJ_NFOUND",
[147] = "EGTS_PC_EVNT_NFOUND",
[148] = "EGTS_PC_SRVC_NFOUND",
[149] = "EGTS_PC_SRVC_DENIED",
[150] = "EGTS_PC_SRVC_UNKN",
[151] = "EGTS_PC_AUTH_DENIED",
[152] = "EGTS_PC_ALREADY_EXISTS",
[153] = "EGTS_PC_ID_NFOUND",
[154] = "EGTS_PC_INC_DATETIME",
[155] = "EGTS_PC_IO_ERROR",
[156] = "EGTS_PC_NO_RES_AVAIL",
[157] = "EGTS_PC_MODULE_FAULT",
[158] = "EGTS_PC_MODULE_PWR_FLT",
[159] = "EGTS_PC_MODULE_PROC_FLT",
[160] = "EGTS_PC_MODULE_SW_FLT",
[161] = "EGTS_PC_MODULE_FW_FLT",
[162] = "EGTS_PC_MODULE_IO_FLT",
[163] = "EGTS_PC_MODULE_MEM_FLT",
[164] = "EGTS_PC_TEST_FAILED",
}
local command_srv_command_type = {
[0001] = "СT_COMCONF",
[0010] = "CT_MSGCONF",
[0011] = "CT_MSGFROM",
[0100] = "CT_MSGTO",
[0101] = "CT_COM",
[0110] = "CT_DELCOM",
[0111] = "CT_SUBREQ",
[1000] = "CT_DELIV",
}
local command_srv_command_confirmation_type = {
[0000] = "CC_OK",
[0001] = "CC_ERROR",
[0010] = "CC_ILL",
[0011] = "CC_DEL",
[0100] = "CC_NFOUND",
[0101] = "CC_NCONF",
[0110] = "CC_INPROG",
}
local command_srv_command_code = {
[0x0000] = "EGTS_RAW_DATA",
[0x0001] = "EGTS_TEST_MODE",
[0x0006] = "EGTS_CONFIG_RESET",
[0x0007] = "EGTS_SET_AUTH_CODE",
[0x0108] = "EGTS_RESTART",
[0x020D] = "EGTS_ECALL_TEST_NUMBER",
[0x0223] = "EGTS_ECALL_SMS_FALLBACK_NUMBER",
}
local header = {
prv = ProtoField.new("ProtocolVersion", "egts.prv", ftypes.UINT8, nil, base.DEC),
skid = ProtoField.new("SecurityKeyID", "egts.skid", ftypes.UINT8, nil, base.DEC),
prf = ProtoField.new("Prefix", "egts.prf", ftypes.UINT8, nil, base.DEC, 0xc0),
rte = ProtoField.new("Route", "egts.rte", ftypes.UINT8, nil, base.DEC, 0x20),
ena = ProtoField.new("Encryption alg", "egts.ena", ftypes.UINT8, nil, base.DEC, 0x18),
cmp = ProtoField.new("Compression", "egts.cmp", ftypes.UINT8, nil, base.DEC, 0x4),
prt = ProtoField.new("Priority", "egts.prt", ftypes.UINT8, nil, base.DEC, 0x3),
hl = ProtoField.new("Header length", "egts.hl", ftypes.UINT8, nil, base.DEC),
he = ProtoField.new("Header encoding", "egts.he", ftypes.UINT8, nil, base.DEC),
fdl = ProtoField.new("Frame data length", "egts.fdl", ftypes.UINT16, nil, base.DEC),
pid = ProtoField.new("Packet identifier", "egts.pid", ftypes.UINT16, nil, base.DEC),
pt = ProtoField.new("Packet type", "egts.pt", ftypes.UINT8, egts_packet_type, base.DEC),
pra = ProtoField.new("Peer address", "egts.pra", ftypes.UINT16, nil, base.DEC),
rca = ProtoField.new("Recipient address", "egts.rca", ftypes.UINT16, nil, base.DEC),
ttl = ProtoField.new("Time to live", "egts.ttl", ftypes.UINT8, nil, base.DEC),
hcs = ProtoField.new("Header checksum", "egts.hcs", ftypes.UINT8, nil, base.HEX),
sfrd = ProtoField.new("Services frame data", "egts.sfrd", ftypes.BYTES),
rpid = ProtoField.new("Response packetID", "egts.rpid", ftypes.UINT16, nil, base.DEC),
pr = ProtoField.new("Processing result", "egts.pr", ftypes.UINT8, nil, base.DEC),
rl = ProtoField.new("Record length", "egts.rl", ftypes.UINT16, nil, base.DEC),
rn = ProtoField.new("Record number", "egts.rn", ftypes.UINT16, nil, base.DEC),
ssod = ProtoField.new("Source service on device", "egts.ssod", ftypes.UINT8, nil, base.DEC, 0x80),
rsod = ProtoField.new("Recipient service on device", "egts.rsod", ftypes.UINT8, nil, base.DEC, 0x40),
grp = ProtoField.new("Group", "egts.grp", ftypes.UINT8, nil, base.DEC, 0x20),
rpr = ProtoField.new("Record processing priority", "egts.rpr", ftypes.UINT8, nil, base.DEC, 0x18),
tmfe = ProtoField.new("Time field exists", "egts.tmfe", ftypes.UINT8, nil, base.DEC, 0x4),
evfe = ProtoField.new("Event ID field exists", "egts.evfe", ftypes.UINT8, nil, base.DEC, 0x2),
obfe = ProtoField.new("Object ID field exists", "egts.obfe", ftypes.UINT8, nil, base.DEC, 0x1),
oid = ProtoField.new("Object identifier", "egts.oid", ftypes.UINT32, nil, base.DEC),
evid = ProtoField.new("Event identifier", "egts.evid", ftypes.UINT32, nil, base.DEC),
tm = ProtoField.new("Time", "egts.tm", ftypes.UINT32, nil, base.DEC),
sst = ProtoField.new("Source service type", "egts.sst", ftypes.UINT8, nil, base.DEC),
rst = ProtoField.new("Recipient service type", "egts.rst", ftypes.UINT8, nil, base.DEC),
rd = ProtoField.new("Record data", "egts.rd", ftypes.BYTES),
srt = ProtoField.new("Subrecord type", "egts.srt", ftypes.UINT8, egts_subrecord_type, base.DEC),
srl = ProtoField.new("Subrecord length", "egts.srl", ftypes.UINT16, nil, base.DEC),
srd = ProtoField.new("Subrecord data", "egts.srd", ftypes.STRING),
crn = ProtoField.new("Confirmed record number", "egts.crn", ftypes.UINT16, nil, base.DEC),
rs = ProtoField.new("Record status", "egts.rs", ftypes.UINT8, result_code, base.DEC),
tid = ProtoField.new("Terminal identifier", "egts.tid", ftypes.UINT32, nil, base.DEC),
mne = ProtoField.new("MNE", "egts.mne", ftypes.UINT8, nil, base.DEC, 0x80),
bse = ProtoField.new("BSE", "egts.bse", ftypes.UINT8, nil, base.DEC, 0x40),
nide = ProtoField.new("NIDE", "egts.nide", ftypes.UINT8, nil, base.DEC, 0x20),
ssra = ProtoField.new("SSRA", "egts.ssra", ftypes.UINT8, nil, base.DEC, 0x10),
lngce = ProtoField.new("LNGCE", "egts.lngce", ftypes.UINT8, nil, base.DEC, 0x8),
imsie = ProtoField.new("IMSIE", "egts.imsie", ftypes.UINT8, nil, base.DEC, 0x4),
imeie = ProtoField.new("IMEIE", "egts.imeie", ftypes.UINT8, nil, base.DEC, 0x2),
hdide = ProtoField.new("HDIDE", "egts.hdide", ftypes.UINT8, nil, base.DEC, 0x1),
hdid = ProtoField.new("Home dispatcher identifier", "egts.hdid", ftypes.UINT16, nil, base.DEC),
imei = ProtoField.new("International mobile equipment identity", "egts.imei", ftypes.STRING),
imsi = ProtoField.new("International mobile subscriber identity", "egts.imsi", ftypes.STRING),
lngc = ProtoField.new("Language code", "egts.lngc", ftypes.STRING),
nid = ProtoField.new("Network identifier", "egts.nid", ftypes.UINT32, nil, base.DEC),
bs = ProtoField.new("Buffer size", "egts.bs", ftypes.UINT32, nil, base.DEC),
msisdn = ProtoField.new("Mobile station integrated services digital network number", "egts.msisdn", ftypes.STRING),
ntm = ProtoField.new("Navigation time", "egts.ntm", ftypes.ABSOLUTE_TIME),
lat = ProtoField.new("Latitude", "egts.lat", ftypes.DOUBLE),
long = ProtoField.new("Longitude", "egts.long", ftypes.DOUBLE),
alte = ProtoField.new("ALTE", "egts.alte", ftypes.UINT8, nil, base.DEC, 0x80),
lohs = ProtoField.new("LONS", "egts.lohs", ftypes.UINT8, nil, base.DEC, 0x40),
lahs = ProtoField.new("LAHS", "egts.lahs", ftypes.UINT8, nil, base.DEC, 0x20),
mv = ProtoField.new("MV", "egts.mv", ftypes.UINT8, nil, base.DEC, 0x10),
bb = ProtoField.new("BB", "egts.bb", ftypes.UINT8, nil, base.DEC, 0x8),
cs = ProtoField.new("CS", "egts.cs", ftypes.UINT8, nil, base.DEC, 0x4),
fix = ProtoField.new("FIX", "egts.fix", ftypes.UINT8, nil, base.DEC, 0x2),
vld = ProtoField.new("VLD", "egts.vld", ftypes.UINT8, nil, base.DEC, 0x1),
dirh = ProtoField.new("Direction the Highest bit", "egts.dirh", ftypes.UINT16, nil, base.DEC, 0x8000),
alts = ProtoField.new("Altitude sign", "egts.alts", ftypes.UINT16, nil, base.DEC, 0x4000),
spd = ProtoField.new("Speed", "egts.spd", ftypes.UINT16, nil, base.DEC, 0x3fff),
dir = ProtoField.new("Direction", "egts.dir", ftypes.UINT8, nil, base.DEC),
odm = ProtoField.new("Odometer", "egts.odm", ftypes.UINT32, nil, base.DEC),
din = ProtoField.new("Digital inputs", "egts.din", ftypes.UINT8, nil, base.DEC),
src = ProtoField.new("Source", "egts.src", ftypes.UINT8, nil, base.DEC),
alt = ProtoField.new("Altitude", "egts.alt", ftypes.UINT32, nil, base.DEC),
srcd = ProtoField.new("Source data", "egts.srcd", ftypes.UINT16, nil, base.DEC),
nsfe = ProtoField.new("NSFE", "egts.nsfe", ftypes.UINT8, nil, base.DEC, 0x10),
sfe = ProtoField.new("SFE", "egts.sfe", ftypes.UINT8, nil, base.DEC, 0x8),
pfe = ProtoField.new("PFE", "egts.pfe", ftypes.UINT8, nil, base.DEC, 0x4),
hfe = ProtoField.new("HFE", "egts.hfe", ftypes.UINT8, nil, base.DEC, 0x2),
vfe = ProtoField.new("VFE", "egts.vfe", ftypes.UINT8, nil, base.DEC, 0x1),
vdop = ProtoField.new("Vertical dilution of precision", "egts.vdop", ftypes.UINT16, nil, base.DEC),
hdop = ProtoField.new("Horizontal dilution of precision", "egts.hdop", ftypes.UINT16, nil, base.DEC),
pdop = ProtoField.new("Position dilution of precision", "egts.pdop", ftypes.UINT16, nil, base.DEC),
sat = ProtoField.new("Satellites", "egts.sat", ftypes.UINT8, nil, base.DEC),
ns = ProtoField.new("Navigation system", "egts.ns", ftypes.UINT16, nil, base.DEC),
st = ProtoField.new("State", "egts.ns", ftypes.UINT8, nil, base.DEC),
mpsv = ProtoField.new("Main power source voltage", "egts.mpsv", ftypes.UINT8, nil, base.DEC),
bbv = ProtoField.new("Back up battery voltage", "egts.bbv", ftypes.UINT8, nil, base.DEC),
ibv = ProtoField.new("Internal battery voltage", "egts.ibv", ftypes.UINT8, nil, base.DEC),
nms = ProtoField.new("NMS", "egts.nms", ftypes.UINT8, nil, base.DEC, 0x4),
ibu = ProtoField.new("IBU", "egts.ibu", ftypes.UINT8, nil, base.DEC, 0x2),
bbu = ProtoField.new("BBU", "egts.bbu", ftypes.UINT8, nil, base.DEC, 0x1),
sfrcs = ProtoField.new("Services frame data checksum", "egts.sfrcs", ftypes.UINT16, nil, base.HEX),
llsef = ProtoField.new("Liquid Level Sensor Error Flag", "egts.llsef", ftypes.UINT8, nil, base.DEC, 0x40),
llsvu = ProtoField.new("Liquid Level Sensor Value Unit", "egts.llsvu", ftypes.UINT8, nil, base.DEC, 0x30),
rdf = ProtoField.new("Raw Data Flag", "egts.rdf", ftypes.UINT8, nil, base.DEC, 0x8),
llsn = ProtoField.new("Liquid Level Sensor Number", "egts.llsn", ftypes.UINT8, nil, base.DEC, 0x7),
maddr = ProtoField.new("Module address", "egts.maddr", ftypes.UINT16, nil, base.DEC),
llsd = ProtoField.new("Liquid Level Sensor Data", "egts.llsd", ftypes.UINT32, nil, base.DEC),
llsdraw = ProtoField.new("Liquid Level Sensor Data bytes", "egts.llsdraw", ftypes.STRING),
dioe1 = ProtoField.new("Digital Inputs Octet Exists 1", "egts.dioe1", ftypes.UINT8, nil, base.DEC, 0x1),
dioe2 = ProtoField.new("Digital Inputs Octet Exists 2", "egts.dioe2", ftypes.UINT8, nil, base.DEC, 0x2),
dioe3 = ProtoField.new("Digital Inputs Octet Exists 3", "egts.dioe3", ftypes.UINT8, nil, base.DEC, 0x4),
dioe4 = ProtoField.new("Digital Inputs Octet Exists 4", "egts.dioe4", ftypes.UINT8, nil, base.DEC, 0x8),
dioe5 = ProtoField.new("Digital Inputs Octet Exists 5", "egts.dioe5", ftypes.UINT8, nil, base.DEC, 0x10),
dioe6 = ProtoField.new("Digital Inputs Octet Exists 6", "egts.dioe6", ftypes.UINT8, nil, base.DEC, 0x20),
dioe7 = ProtoField.new("Digital Inputs Octet Exists 7", "egts.dioe7", ftypes.UINT8, nil, base.DEC, 0x40),
dioe8 = ProtoField.new("Digital Inputs Octet Exists 8", "egts.dioe8", ftypes.UINT8, nil, base.DEC, 0x80),
dout = ProtoField.new("Digital Outputs", "egts.dout", ftypes.UINT8, nil, base.DEC),
asfe1 = ProtoField.new("Analog Sensor Fields Exist 1", "egts.asfe1", ftypes.UINT8, nil, base.DEC, 0x1),
asfe2 = ProtoField.new("Analog Sensor Fields Exist 2", "egts.asfe2", ftypes.UINT8, nil, base.DEC, 0x2),
asfe3 = ProtoField.new("Analog Sensor Fields Exist 3", "egts.asfe3", ftypes.UINT8, nil, base.DEC, 0x4),
asfe4 = ProtoField.new("Analog Sensor Fields Exist 4", "egts.asfe4", ftypes.UINT8, nil, base.DEC, 0x8),
asfe5 = ProtoField.new("Analog Sensor Fields Exist 5", "egts.asfe5", ftypes.UINT8, nil, base.DEC, 0x10),
asfe6 = ProtoField.new("Analog Sensor Fields Exist 6", "egts.asfe6", ftypes.UINT8, nil, base.DEC, 0x20),
asfe7 = ProtoField.new("Analog Sensor Fields Exist 7", "egts.asfe7", ftypes.UINT8, nil, base.DEC, 0x40),
asfe8 = ProtoField.new("Analog Sensor Fields Exist 8", "egts.asfe8", ftypes.UINT8, nil, base.DEC, 0x80),
adio1 = ProtoField.new("Additional Digital Inputs Octet 1", "egts.adio1", ftypes.UINT8, nil, base.DEC),
adio2 = ProtoField.new("Additional Digital Inputs Octet 2", "egts.adio2", ftypes.UINT8, nil, base.DEC),
adio3 = ProtoField.new("Additional Digital Inputs Octet 3", "egts.adio3", ftypes.UINT8, nil, base.DEC),
adio4 = ProtoField.new("Additional Digital Inputs Octet 4", "egts.adio4", ftypes.UINT8, nil, base.DEC),
adio5 = ProtoField.new("Additional Digital Inputs Octet 5", "egts.adio5", ftypes.UINT8, nil, base.DEC),
adio6 = ProtoField.new("Additional Digital Inputs Octet 6", "egts.adio6", ftypes.UINT8, nil, base.DEC),
adio7 = ProtoField.new("Additional Digital Inputs Octet 7", "egts.adio7", ftypes.UINT8, nil, base.DEC),
adio8 = ProtoField.new("Additional Digital Inputs Octet 8", "egts.adio8", ftypes.UINT8, nil, base.DEC),
ans1 = ProtoField.new("Analog Sensor 1", "egts.ans1", ftypes.UINT16, nil, base.DEC),
ans2 = ProtoField.new("Analog Sensor 2", "egts.ans2", ftypes.UINT16, nil, base.DEC),
ans3 = ProtoField.new("Analog Sensor 3", "egts.ans3", ftypes.UINT16, nil, base.DEC),
ans4 = ProtoField.new("Analog Sensor 4", "egts.ans4", ftypes.UINT16, nil, base.DEC),
ans5 = ProtoField.new("Analog Sensor 5", "egts.ans5", ftypes.UINT16, nil, base.DEC),
ans6 = ProtoField.new("Analog Sensor 6", "egts.ans6", ftypes.UINT16, nil, base.DEC),
ans7 = ProtoField.new("Analog Sensor 7", "egts.ans7", ftypes.UINT16, nil, base.DEC),
ans8 = ProtoField.new("Analog Sensor 8", "egts.ans8", ftypes.UINT16, nil, base.DEC),
cn = ProtoField.new("Counter Number", "egts.cn", ftypes.UINT8, nil, base.DEC),
cnv = ProtoField.new("Counter Value", "egts.cnv", ftypes.UINT16, nil, base.DEC),
-- EGTS_SR_COMMAND_DATA
CT = ProtoField.new("Command Type", "egts.CT", ftypes.UINT8, command_srv_command_type, base.DEC, 0xF0),
CCT = ProtoField.new("Command Confirmation Type", "egts.CCT", ftypes.UINT8, command_srv_command_confirmation_type, base.DEC, 0x0F),
CID = ProtoField.new("Command Identifier", "egts.CID", ftypes.UINT32, nil, base.DEC),
SID = ProtoField.new("Source Identifier", "egts.SID", ftypes.UINT32, nil, base.DEC),
ACFE = ProtoField.new("Authorization Code Field Exist", "egts.ACFE", ftypes.UINT8, nil, base.DEC, 0x02),
CHSFE = ProtoField.new("Charset Field Exists", "egts.CHSFE", ftypes.UINT8, nil, base.DEC, 0x01),
CHS = ProtoField.new("Charset", "egts.CHS", ftypes.UINT8, nil, base.DEC),
ACL = ProtoField.new("Authorization Code Length", "egts.ACL", ftypes.UINT8, nil, base.DEC),
AC = ProtoField.new("Authorization Code", "egts.AC", ftypes.STRING),
ADR = ProtoField.new("Address", "egts.ADR", ftypes.UINT16, nil, base.DEC),
SZ = ProtoField.new("Size", "egts.SZ", ftypes.UINT8, nil, base.DEC, 0xF0),
ACT = ProtoField.new("Action", "egts.ACT", ftypes.UINT8, nil, base.DEC, 0x0F),
CCD = ProtoField.new("Command Code", "egts.CCD", ftypes.UINT16, command_srv_command_code, base.HEX),
DT = ProtoField.new("Data", "egts.DT", ftypes.STRING),
}
-- регистрация полей протокола
egts_proto.fields = header
local function parse_sr_command_data_body(buf, tree)
local cur_offset = 0
tree:add(header.ADR, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
local sub = buf:range(cur_offset, 1):le_uint()
tree:add(header.SZ, sub)
tree:add(header.ACT, sub)
cur_offset = cur_offset + 1
tree:add(header.CCD, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
if cur_offset < buf:len() then
tree:add(header.DT, buf:range(cur_offset))
end
end
local function parse_sr_command_data(buf, tree)
local cur_offset = 0
local types = buf:range(cur_offset, 1):le_uint()
tree:add(header.CT, types)
tree:add(header.CCT, types)
cur_offset = cur_offset + 1
tree:add(header.CID, buf:range(cur_offset, 4):le_uint())
cur_offset = cur_offset + 4
tree:add(header.SID, buf:range(cur_offset, 4):le_uint())
cur_offset = cur_offset + 4
local flags = buf:range(cur_offset, 1):le_uint()
tree:add(header.ACFE, flags)
tree:add(header.CHSFE, flags)
cur_offset = cur_offset + 1
if bit.band(flags, 0x1) ~= 0 then
tree:add(header.CHS, buf:range(cur_offset, 1):le_uint())
cur_offset = cur_offset + 1
end
if bit.band(flags, 0x2) ~= 0 then
local len = buf:range(cur_offset, 1):le_uint();
tree:add(header.ACL, len)
cur_offset = cur_offset + 1
tree:add(header.AC, buf:range(cur_offset, len))
cur_offset = cur_offset + len
end
--tree:add(header.srd, buf:range(cur_offset):bytes():tohex())
local cmd_data = buf:range(cur_offset)
local cmd = tree:add(egts_proto, cmd_data, "Subrecord data")
parse_sr_command_data_body(cmd_data, cmd);
return buf:len()
end
local MIN_HEADE_LENGHT = 11
local function get_packet_type(type_id)
return egts_packet_type[type_id]
end
local function get_egts_length(tvbuf, pktinfo, offset)
local header_len = tvbuf:range(offset + 3, 1):uint()
local data_len = tvbuf:range(offset + 5, 2):le_uint()
return header_len + data_len + 2
end
local function parse_sr_response(buf, tree)
local cur_offset = 0
tree:add(header.crn, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
tree:add(header.rs, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
return buf:len()
end
local function parse_sr_term_identity(buf, tree)
local cur_offset = 0
tree:add(header.tid, buf:range(cur_offset, 4):le_uint())
cur_offset = cur_offset + 4
local flags = buf:range(cur_offset, 1):le_uint()
tree:add(header.mne, flags)
tree:add(header.bse, flags)
tree:add(header.nide, flags)
tree:add(header.ssra, flags)
tree:add(header.lngce, flags)
tree:add(header.imsie, flags)
tree:add(header.imeie, flags)
tree:add(header.hdide, flags)
cur_offset = cur_offset + 1
if bit.band(flags, 0x1) ~= 0 then
tree:add(header.hdid, buf:range(cur_offset, 2):uint())
cur_offset = cur_offset + 2
end
if bit.band(flags, 0x2) ~= 0 then
tree:add(header.imei, buf:range(cur_offset, 15):string())
cur_offset = cur_offset + 15
end
if bit.band(flags, 0x4) ~= 0 then
tree:add(header.imsi, buf:range(cur_offset, 16):string())
cur_offset = cur_offset + 16
end
if bit.band(flags, 0x8) ~= 0 then
tree:add(header.lngc, buf:range(cur_offset, 3):string())
cur_offset = cur_offset + 3
end
if bit.band(flags, 0x20) ~= 0 then
tree:add(header.nid, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(flags, 0x40) ~= 0 then
tree:add(header.bs, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
end
if bit.band(flags, 0x80) ~= 0 then
tree:add(header.msisdn, buf:range(cur_offset, 15):le_uint())
cur_offset = cur_offset + 15
end
return cur_offset
end
local function parse_sr_pos_data(buf, tree)
local cur_offset = 0
local ntm = buf:range(cur_offset, 4):le_uint()
local offset_time = os.time { year = 2010, month = 1, day = 1, hour = 0 }
ntm = ntm + offset_time
tree:add(header.ntm, NSTime.new(ntm))
cur_offset = cur_offset + 4
tree:add(header.lat, buf:range(cur_offset, 4):le_uint() * 90 / 0xFFFFFFFF)
cur_offset = cur_offset + 4
tree:add(header.long, buf:range(cur_offset, 4):le_uint() * 180 / 0xFFFFFFFF)
cur_offset = cur_offset + 4
local flg = buf:range(cur_offset, 1):uint()
tree:add(header.alte, flg)
tree:add(header.lohs, flg)
tree:add(header.lahs, flg)
tree:add(header.mv, flg)
tree:add(header.bb, flg)
tree:add(header.cs, flg)
tree:add(header.fix, flg)
tree:add(header.vld, flg)
cur_offset = cur_offset + 1
local spd = buf:range(cur_offset, 2):le_uint()
tree:add(header.dirh, spd)
tree:add(header.alts, spd)
tree:add(header.spd, spd)
cur_offset = cur_offset + 2
tree:add(header.dir, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
tree:add(header.odm, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
tree:add(header.din, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
tree:add(header.src, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
if bit.band(flg, 0x80) ~= 0 then
tree:add(header.alt, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
-- TODO: разобраться с разбором SourceData
return buf:len()
end
local function parse_sr_ext_pos_data(buf, tree)
local cur_offset = 0
local flags = buf:range(cur_offset, 1):uint()
tree:add(header.nsfe, flags)
tree:add(header.sfe, flags)
tree:add(header.pfe, flags)
tree:add(header.hfe, flags)
tree:add(header.vfe, flags)
cur_offset = cur_offset + 1
if bit.band(flags, 0x1) ~= 0 then
-- если флаг VFE установлен, то есть поле снижение точности в вертикальной плоскости
tree:add(header.vdop, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
end
if bit.band(flags, 0x2) ~= 0 then
-- если флаг HFE установлен, то есть поле снижение точности в горизонтальной плоскости
tree:add(header.hdop, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
end
if bit.band(flags, 0x4) ~= 0 then
-- если флаг HFE установлен, то есть поле снижение точности по местоположению
tree:add(header.pdop, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
end
local sectionLen = buf:len()
if bit.band(flags, 0x8) ~= 0 then
-- если флаг SFE установлен, то есть поле c данными о текущем количестве видимых спутников и типе используемой навигационной спутниковой системы
tree:add(header.sat, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
if cur_offset < sectionLen then
tree:add(header.ns, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
end
end
return sectionLen
end
local function parse_sr_state_data(buf, tree)
local cur_offset = 0
tree:add(header.st, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
tree:add(header.mpsv, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
tree:add(header.bbv, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
tree:add(header.ibv, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
local flags = buf:range(cur_offset, 1):uint()
tree:add(header.nms, flags)
tree:add(header.ibu, flags)
tree:add(header.bbu, flags)
cur_offset = cur_offset + 1
return cur_offset
end
local function parse_sr_liquid_level_sensor(buf, tree)
local cur_offset = 0
local flags = buf:range(cur_offset, 1):uint()
tree:add(header.llsef, flags)
tree:add(header.llsvu, flags)
tree:add(header.rdf, flags)
tree:add(header.llsn, flags)
cur_offset = cur_offset + 1
tree:add(header.maddr, buf:range(cur_offset, 2):le_uint())
cur_offset = cur_offset + 2
if bit.band(flags, 0x8) == 0 then
-- если флаг RDF флаг установлен, то значение имеет длину 4 байта
tree:add(header.llsd, buf:range(cur_offset, 4):le_uint())
cur_offset = cur_offset + 4
else
tree:add(header.llsdraw, buf:bytes():tohex())
end
return cur_offset
end
local function parse_sr_ad_sensors_data(buf, tree)
local cur_offset = 0
local sectionLen = buf:len()
local diflg = buf:range(cur_offset, 1):uint()
tree:add(header.dioe1, diflg)
tree:add(header.dioe2, diflg)
tree:add(header.dioe3, diflg)
tree:add(header.dioe4, diflg)
tree:add(header.dioe5, diflg)
tree:add(header.dioe6, diflg)
tree:add(header.dioe7, diflg)
tree:add(header.dioe8, diflg)
cur_offset = cur_offset + 1
tree:add(header.dout, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
local ansflg = buf:range(cur_offset, 1):uint()
tree:add(header.asfe1, ansflg)
tree:add(header.asfe2, ansflg)
tree:add(header.asfe3, ansflg)
tree:add(header.asfe4, ansflg)
tree:add(header.asfe5, ansflg)
tree:add(header.asfe6, ansflg)
tree:add(header.asfe7, ansflg)
tree:add(header.asfe8, ansflg)
cur_offset = cur_offset + 1
if bit.band(diflg, 0x1) ~= 0 then
tree:add(header.adio1, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(diflg, 0x2) ~= 0 then
tree:add(header.adio2, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(diflg, 0x4) ~= 0 then
tree:add(header.adio3, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(diflg, 0x8) ~= 0 then
tree:add(header.adio4, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(diflg, 0x10) ~= 0 then
tree:add(header.adio5, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(diflg, 0x20) ~= 0 then
tree:add(header.adio6, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(diflg, 0x40) ~= 0 then
tree:add(header.adio7, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(diflg, 0x80) ~= 0 then
tree:add(header.adio8, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
end
if bit.band(ansflg, 0x1) ~= 0 then
tree:add(header.ans1, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(ansflg, 0x2) ~= 0 then
tree:add(header.ans2, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(ansflg, 0x4) ~= 0 then
tree:add(header.ans3, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(ansflg, 0x8) ~= 0 then
tree:add(header.ans4, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(ansflg, 0x10) ~= 0 then
tree:add(header.ans5, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(ansflg, 0x20) ~= 0 then
tree:add(header.ans6, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(ansflg, 0x40) ~= 0 then
tree:add(header.ans7, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
if bit.band(ansflg, 0x80) ~= 0 then
tree:add(header.ans8, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
end
return sectionLen
end
local function parse_sr_abs_cntr_data(buf, tree)
local cur_offset = 0
tree:add(header.cnv, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
tree:add(header.cnv, buf:range(cur_offset, 3):le_uint())
cur_offset = cur_offset + 3
return offset
end
local function parse_sr_result_code(buf, tree)
local cur_offset = 0
tree:add(header.rs, buf:range(cur_offset, 1):uint())
cur_offset = cur_offset + 1
return buf:len()
end
local function parse_subrecord(buf, tree)
local subrecords = tree:add(egts_proto, buf, "Record data")
local current_offset = 0
while current_offset < buf:len() do
local subrecord = subrecords:add(egts_proto, buf, "Subrecord")
local subrecord_type = buf:range(current_offset, 1):uint()
subrecord:add(header.srt, subrecord_type)
current_offset = current_offset + 1
local subrecord_data_len = buf:range(current_offset, 2):le_uint()
subrecord:add(header.srl, subrecord_data_len)
current_offset = current_offset + 2
local sr_data = buf:range(current_offset, subrecord_data_len)
local srd = subrecord:add(egts_proto, sr_data, "Subrecord data")
if subrecord_type == 0 then
parse_sr_response(sr_data, srd)
elseif subrecord_type == 1 then
parse_sr_term_identity(sr_data, srd)
elseif subrecord_type == 9 then
parse_sr_result_code(sr_data, srd)
elseif subrecord_type == 16 then
parse_sr_pos_data(sr_data, srd)
elseif subrecord_type == 17 then
parse_sr_ext_pos_data(sr_data, srd)
elseif subrecord_type == 20 then
parse_sr_state_data(sr_data, srd)
elseif subrecord_type == 27 then
parse_sr_liquid_level_sensor(sr_data, srd)
elseif subrecord_type == 18 then
parse_sr_ad_sensors_data(sr_data, srd)
elseif subrecord_type == 25 then
parse_sr_abs_cntr_data(sr_data, srd)
elseif subrecord_type == 51 then
parse_sr_command_data(sr_data, srd)
else
subrecord:add(header.srd, sr_data:bytes():tohex())
end
current_offset = current_offset + subrecord_data_len
end
return current_offset
end
local function parse_sdr(buf, tree)
local current_offset = 0
local sdr_len = 0
while (current_offset < buf:len()) do
sdr_len = buf:range(current_offset, 2):le_uint()
local service_data_record = tree:add(egts_proto, buf, "Service Data Record")
current_offset = current_offset + 2
service_data_record:add(header.rl, sdr_len)
service_data_record:add(header.rn, buf:range(current_offset, 2):le_uint())
current_offset = current_offset + 2
local rfl = buf:range(current_offset, 1):uint()
service_data_record:add(header.ssod, rfl)
service_data_record:add(header.rsod, rfl)
service_data_record:add(header.grp, rfl)
service_data_record:add(header.rpr, rfl)
service_data_record:add(header.tmfe, rfl)
service_data_record:add(header.evfe, rfl)
service_data_record:add(header.obfe, rfl)
current_offset = current_offset + 1
if bit.band(rfl, 0x1) ~= 0 then
-- если флаг OBFE установлен, то значит есть поле с id объекта и его надо заполнить
service_data_record:add(header.oid, buf:range(current_offset, 4):le_uint())
current_offset = current_offset + 4
end
if bit.band(rfl, 0x2) ~= 0 then
-- если флаг EVFE установлен, то значит присутствует поле с id события
service_data_record:add(header.evid, buf:range(current_offset, 4):le_uint())
current_offset = current_offset + 4
end
if bit.band(rfl, 0x4) ~= 0 then
-- если флаг TMFE установлен, то есть поле со временем, которое нужно разобрать
service_data_record:add(header.tm, buf:range(current_offset, 4):le_uint())
current_offset = current_offset + 4
end
service_data_record:add(header.sst, buf:range(current_offset, 1):uint())
current_offset = current_offset + 1
service_data_record:add(header.rst, buf:range(current_offset, 1):uint())
current_offset = current_offset + 1
local computed_bytes = parse_subrecord(buf:range(current_offset, sdr_len), service_data_record)
current_offset = current_offset + computed_bytes
end
return current_offset
end
local function parse_pt_response (buf, tree)
local current_offset = 0
tree:add(header.rpid, buf:range(current_offset, 2):le_uint())
current_offset = current_offset + 2
tree:add(header.pr, buf:range(current_offset, 1):uint())
current_offset = current_offset + 1
if buf:len() - current_offset > 0 then
local computed_bytes = parse_sdr(buf:range(current_offset), tree)
current_offset = current_offset + computed_bytes
end
return buf:len()
end
local function parse_pt_appdata (buf, tree)
local current_offset = 0
local computed_bytes = 0
while (current_offset < buf:len()) do
computed_bytes = parse_sdr(buf:range(current_offset), tree)
current_offset = current_offset + computed_bytes
end
return current_offset
end
local function parse_pt_signed_appdata (buf, tree)
tree:add(header.sfrd, buf:raw())
return buf:len()
end
local function dissect_egts_pdu(tvbuf, pktinfo, root)
local header_len = tvbuf:range(3, 1):uint()
local data_len = tvbuf:range(5, 2):le_uint()
local msglen = header_len + data_len + 2
pktinfo.cols.protocol:set("EGTS")
-- Начинаем заполнения дерева в отображении
local tree = root:add(egts_proto, tvbuf:range(0, msglen))
tree:add(header.prv, tvbuf:range(0, 1):uint())
tree:add(header.skid, tvbuf:range(1, 1):uint())
local prf_tvbr = tvbuf:range(2, 1):uint()
tree:add(header.prf, prf_tvbr)
tree:add(header.rte, prf_tvbr)
tree:add(header.ena, prf_tvbr)
tree:add(header.cmp, prf_tvbr)
tree:add(header.prt, prf_tvbr)
tree:add(header.hl, header_len)
tree:add(header.he, tvbuf:range(4, 1):uint())
tree:add(header.fdl, data_len)
tree:add(header.pid, tvbuf:range(7, 2):le_uint())
local packet_type_id = tvbuf:range(9, 1):uint()
tree:add(header.pt, packet_type_id)
local field_offset = 10;
if bit.band(prf_tvbr, 0x20) ~= 0 then
-- если RTE флаг присутствует, то заполняем не обязательные поля
tree:add(header.pra, tvbuf:range(field_offset, 2):le_uint())
field_offset = field_offset + 2
tree:add(header.rca, tvbuf:range(field_offset, 2):le_uint())
field_offset = field_offset + 2
tree:add(header.ttl, tvbuf:range(field_offset, 1):uint())
field_offset = field_offset + 1
end
tree:add(header.hcs, tvbuf:range(field_offset, 1):uint())
field_offset = field_offset + 1
local subtree = tree:add(egts_proto, tvbuf, "Services frame data")
if get_packet_type(packet_type_id) == EGTS_PT_RESPONSE then
parse_pt_response(tvbuf:range(field_offset, data_len), subtree)
elseif get_packet_type(packet_type_id) == EGTS_PT_APPDATA then
parse_pt_appdata(tvbuf:range(field_offset, data_len), subtree)
else
parse_pt_signed_appdata(tvbuf:range(field_offset, data_len), subtree)
end
tree:add(header.sfrcs, tvbuf:range(field_offset + data_len, 2):le_uint())
return msglen
end
-- задаем функию обработки, которая получает на вход данные tvbuf (объект Tvb), информацию о пакете
-- pktinfo (объект Pinfo) и root дерево распарсенного объекта.
function egts_proto.dissector(tvbuf, pktinfo, root)
dissect_tcp_pdus(tvbuf, root, MIN_HEADE_LENGHT, get_egts_length, dissect_egts_pdu)
local bytes_consumed = tvbuf:len()
return bytes_consumed
end
-- добавляем парсер в таблицу
DissectorTable.get("tcp.port"):add(default_settings.port, egts_proto)

3
Tst/listner.sh Executable file
View File

@ -0,0 +1,3 @@
while true; do
nc -l 5020;
done

18
Tst/modular.json Normal file
View File

@ -0,0 +1,18 @@
{
"dep": [
{
"type": "local",
"dir": "../"
},
{
"type": "git",
"provider": "Smart_Components_Aurus",
"repo": "ArrayPrint"
},
{
"type": "git",
"provider": "Smart_Components_Aurus",
"repo": "AsciiStringParsingUtils"
}
]
}

253
Tst/test_module.c Normal file
View File

@ -0,0 +1,253 @@
//
// Created by xemon on 8/23/22.
//
#include <stdio.h>
#include <stdbool.h>
#include <egtsWorker.h>
#include <AsciiStringParsingUtils.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "ArrayPrint.h"
void SystemDelayMs() {
}
void parseTest(uint8_t *data, size_t data_size) {
EgtsWorkerEnvironment egtsWorkerEnv;
egtsWorkerEnv.workingBufferLength = data_size;
egtsWorkerEnv.workingBuffer = data;
if (EgtsIsTransportComplete(&egtsWorkerEnv)) {
EgtsParseHeader(&egtsWorkerEnv);
EgtsParseFrameData(&egtsWorkerEnv);
EgtsParseSrvRecord(&egtsWorkerEnv);
if (egtsWorkerEnv.header.type == EGTS_PT_RESPONSE) {
printf(" - EGTS_PT_RESPONSE\n");
} else if (egtsWorkerEnv.header.type == EGTS_PT_APPDATA) {
printf(" - EGTS_PT_APPDATA\n");
} else {
printf(" - unknown %i\n", egtsWorkerEnv.header.type);
}
if (egtsWorkerEnv.srCommand) {
///sms
switch (egtsWorkerEnv.srCommand->cmd) {
case EGTS_ECALL_MSD_REQ:
printf("Запрос МНД");
return;
case EGTS_ECALL_REQ:
printf("Запрос эксренного вызова");
return;
case EGTS_ECALL_TEST_NUMBER:
printf("Запрос на установку номера для тестового вызова");
return;
case EGTS_ECALL_SMS_FALLBACK_NUMBER:
printf("Запрос на установку номера для SMS");
return;
}
}
}
}
uint8_t sendTcp(char *ip, uint16_t port, uint8_t *data, size_t size) {
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
printf("\n Usage: %s <ip of server> \n", ip);
memset(recvBuff, '0', sizeof(recvBuff));
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0) {
printf("\n inet_pton error occured\n");
return 1;
}
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("\n Error : Connect Failed \n");
return 1;
}
// while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
// {
// recvBuff[n] = 0;
// if(fputs(recvBuff, stdout) == EOF)
// {
// printf("\n Error : Fputs error\n");
// }
// }
write(sockfd, data, size);
if (n < 0) {
printf("\n Read error \n");
}
return 0;
}
void testResponse() {
uint8_t data[1024];
size_t len = vEgtsPackEgtsResponse(
111,
data,
0b000,
333,
444,
0
);
///=============================
// uint16_t Address = 1;
// uint8_t Size = 0b0001;
// uint8_t Action = 0b0010;
// uint16_t CommandCode = EGTS_TEST_MODE;
// uint32_t Data = 0;
// size_t len = vEgtsPackSrCmdConfirmation(
// data,
// 2,
// CT_COMCONF,
// CC_OK,
// 44,
// 0,
// 0,
// 0,
// Address,
// Size,
// Action,
// CommandCode,
// Data
// );
///=============================
// uint8_t imei[] = "356133310612543";
// size_t len = vEgtsPackTermIdentityTransport(
// 1,
// data,
// imei,
// sizeof(imei) - 1,
// 1233,
// 0
// );
// size_t len = vEgtsPackMsdTransport(
// 555,
// data,
// imei,
// sizeof(imei) - 1,
// 0
// );
ArrayPrint_Hex(data, len);
sendTcp("127.0.0.1", 5020, data, len);
}
#define BIN(DATA, LEN, HEX_STRING) \
uint8_t DATA[(sizeof(HEX_STRING)-1)/2]; \
size_t LEN = iAsciiStringParseHexBytes(DATA, HEX_STRING, sizeof(HEX_STRING) - 1);
void send_test() {
// char hexData[] = "0100000B001E00080001BD13000800010800000004043310005F08000000A90100000001000012010044C8";
// char hexData[] = "0100010B0018000000012E0D0001000400C5C2B40404330A000101000000A9010000002DB0";
// char hexData[] = "0100010B0018000000012E0D0001000400C5C2B40404330A000105000000A901000000C22C";
// char hexData[] = "0100000B001E000300012513000300010300000004043310005003000000A9010000000100001201003DEF";
/// set sms number
// BIN_FROM_HEX(binData,binDataLen,"0100000B0028000A00013D1D000A00010A0000000404331A00500A000000A9010000000100420D0237393410102010101010101010");
// BIN_FROM_HEX(binData, binDataLen, "0100020B001D004800019916004900000404331300507347061B00000000000C00000000EBAEBAEB1C01");
// BIN_FROM_HEX(binData, binDataLen, "0100020B001D00020001B516000300000404331300507347061B00000000000C00000000EBAEBAEBC589");
// BIN_FROM_HEX(binData, binDataLen, "0100020B001C0007000109150008000004043312005080E5061B00000000000A000000004C44932560");
// BIN_FROM_HEX(binData, binDataLen, "0100010B001400070000DD07000006000100041F16B1830404000300080000020A");
// BIN_FROM_HEX(binData, binDataLen, "0100020B001C00030001201500040000040433120050E2F3061B00000000000A00000000B5EB2DAB72");
// BIN_FROM_HEX(binData, binDataLen, "0100010B00110003000109060001000426732E19040400030004000065C5");
// BIN_FROM_HEX(binData, binDataLen, "0100020B001D00020001B51600030000040433130050C276111B00000000000A0000000074657374DAA0");
// BIN_FROM_HEX(binData, binDataLen, "0100010B001D000200016E120001000400C5C2B40404330F0010C276111B00000000000A000000009198");
//
// 01 00 03 0B 00 1000 3800 00 3C 3800 00 06003900000202000300010000DD22
BIN_FROM_HEX(binData, binDataLen, "0100000B0019000200013812000200800404330F0010020000009F010000000100120100B347");
parseTest(binData, binDataLen);
sendTcp("127.0.0.1", 5020, binData, binDataLen);
// testResponse();
printf("\n");
}
void parse_test() {
//запрос на скорость
// BIN_FROM_HEX(binData, binDataLen, "0100020B001D004800019916004900000404331300507347061B00000000000C00000000EBAEBAEB1C01");
BIN_FROM_HEX(binData, binDataLen,
"0100020B001D00020001B516000300000404331300507347061B00000000000C00000000EBAEBAEBC589");
parseTest(binData, binDataLen);
}
void test_sensors() {
uint8_t data[1024];
tEgtsSensorsDataArgs sensors = {
.analogInPresent = SENSOR_1 | SENSOR_2,
.digitalInPresent = SENSOR_1 | SENSOR_5,
.digitalOutPresent = SENSOR_NO,
.digitalIn = {SENSOR_1 | SENSOR_5, SENSOR_8 | SENSOR_7},
.analogIn = {200,500}
};
size_t len = vEgtsPackSensorsTransport(
111,
data,
0b000,
&sensors
);
sendTcp("127.0.0.1", 5020, data, len);
}
int main() {
// send_test();
// parse_test();
test_sensors();
}

27
modular.json Normal file
View File

@ -0,0 +1,27 @@
{
"dep": [
{
"type": "git",
"provider": "Smart_Components_Aurus",
"repo": "BitBufferOperations"
},
{
"type": "git",
"provider": "Smart_Components_Aurus",
"repo": "SystemDelayInterface"
},
{
"type": "git",
"provider": "Smart_Components_Aurus",
"repo": "BaseTypes"
}
],
"cmake": {
"inc_dirs": [
"Inc"
],
"srcs": [
"Src/**.c"
]
}
}