Первый коммит

This commit is contained in:
cfif 2025-09-10 17:57:09 +03:00
commit 8567a5bb2a
16 changed files with 5057 additions and 0 deletions

View File

@ -0,0 +1,149 @@
//
// Created by xemon on 06.09.22.
//
#include <memory.h>
#include <math.h>
#include "AsciiStringAssmeblingUtils.h"
static const char ASCII_STRING_HEX_CHAR[] = "0123456789ABCDEF";
static const uint64_t ASCII_STRING_DEC_POW[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000
};
static const uint8_t ASCII_STRING_DEC_POW_LEN = (sizeof(ASCII_STRING_DEC_POW) / sizeof(uint64_t));
uint8_t vAsciiStringDecimalIntToChar(uint8_t number_0_9) {
number_0_9 = number_0_9 % 10; //cutoff digits more 1 (numbers between 0 and 9)
return ('0' + number_0_9); //return char of number('0' is base number in ascii)
}
void vAsciiStringAdd(char *string, size_t *stringLen, char *addString, size_t addStringLen) {
memcpy(string + (*stringLen), addString, addStringLen);
*stringLen += addStringLen;
}
void vAsciiStringAddChar(char *string, size_t *stringLen, uint8_t singleChar) {
string[*stringLen] = singleChar;
++(*stringLen);
}
void vAsciiStringInit(char *string, size_t *stringLen, size_t fullLen) {
memset(string, 0, fullLen);
*stringLen = 0;
}
void vAsciiStringClean(char *string, size_t *stringLen) {
if (*stringLen == 0)return;
memset(string, 0, *stringLen);
*stringLen = 0;
}
void vAsciiStringAddDecimalInt(char *string, size_t *stringLen, uint8_t number, uint8_t digits) {
for (uint8_t reverse_digit = 1; reverse_digit <= digits; ++reverse_digit) {
string[*stringLen + digits - reverse_digit] = vAsciiStringDecimalIntToChar(number);
number /= 10;
}
*stringLen += digits;
}
void vAsciiStringAddDecimalInt64(char *string, size_t *stringLen, uint64_t number, uint8_t digits) {
for (uint8_t reverse_digit = 1; reverse_digit <= digits; ++reverse_digit) {
string[*stringLen + digits - reverse_digit] = vAsciiStringDecimalIntToChar(number % 10);
number /= 10;
}
*stringLen += digits;
}
void vAsciiStringSpitChars(char *one, char *two) {
char tmp;
tmp = *one;
*one = *two;
*two = tmp;
}
void vAsciiStringAddDecimalIntWithLimit(char *string, size_t *stringLen, int64_t number, uint8_t digitsLimit) {
if (number < 0) {
*(string + (*stringLen)) = '-';
++(*stringLen);
number = -number;
}
uint32_t cutoffNumber = 1;
for (uint8_t scale = 0; scale < digitsLimit; ++scale) {
cutoffNumber *= 10;
}
number = number % cutoffNumber;
if (number == 0) {
string[*stringLen] = '0';
(*stringLen) += 1;
}
uint8_t digits = 0;
for (; (digits < digitsLimit) && (number != 0); ++digits) {
string[(*stringLen) + digits] = vAsciiStringDecimalIntToChar(number % 10);
number /= 10;
}
uint8_t reverses = digits / 2;
for (uint8_t reverse_digit = 0; reverse_digit < reverses; ++reverse_digit) {
vAsciiStringSpitChars(string + *stringLen + reverse_digit, string + *stringLen + digits - 1 - reverse_digit);
}
*stringLen += digits;
}
void vAsciiStringAddByteAsHex(char *str, size_t *stringLen, uint8_t number) {
str[*stringLen + 0] = ASCII_STRING_HEX_CHAR[(number >> 4) & 0xF];
str[*stringLen + 1] = ASCII_STRING_HEX_CHAR[(number & 0xF)];
*stringLen += 2;
}
void vAsciiStringAddBytesAsHex(char *str, size_t *stringLen, uint8_t *bytesData, size_t bytesCount) {
uint8_t *end = bytesData + bytesCount;
while (end > bytesData) {
vAsciiStringAddByteAsHex(str, stringLen, *bytesData);
++bytesData;
}
}
static inline uint64_t get_dec_pow(uint8_t value) {
if (value < ASCII_STRING_DEC_POW_LEN) {
return ASCII_STRING_DEC_POW[value];
}
uint64_t mux = ASCII_STRING_DEC_POW[ASCII_STRING_DEC_POW_LEN - 1];
for (uint8_t scale = ASCII_STRING_DEC_POW_LEN; scale < value; ++scale) {
mux *= 10;
}
return mux;
}
void vAsciiStringAddDecimalFloatWithLimit(
char *string,
size_t *stringLen,
double number,
uint8_t intDigits,
uint8_t fractionalDigits
) {
uint64_t dec_mux = get_dec_pow(fractionalDigits);
uint64_t intPart = (uint64_t) number;
double fractional = round(number * dec_mux) / dec_mux - intPart;
uint64_t fractionalPartInInteger = (uint64_t) (fractional * dec_mux);
vAsciiStringAddDecimalIntWithLimit(string, stringLen, intPart, intDigits);
vAsciiStringAddChar(string, stringLen, '.');
vAsciiStringAddDecimalInt64(string, stringLen, fractionalPartInInteger, fractionalDigits);
}

View File

@ -0,0 +1,42 @@
//
// Created by xemon on 06.09.22.
//
#ifndef ASCIISTRINGASSMEBLINGUTILS_ASCIISTRINGASSMEBLINGUTILS_H
#define ASCIISTRINGASSMEBLINGUTILS_ASCIISTRINGASSMEBLINGUTILS_H
#include "stdint.h"
#include "stddef.h"
void vAsciiStringAdd(char *string, size_t *stringLen, char *addString, size_t addStringLen);
uint8_t vAsciiStringDecimalIntToChar(uint8_t number_0_9);
void vAsciiStringAddChar(char *string, size_t *stringLen, uint8_t singleChar);
#define vAsciiStringAddStatic(string, stringLen, staticString)\
vAsciiStringAdd(string, stringLen, staticString, sizeof(staticString)-1)
void vAsciiStringClean(char *string, size_t *stringLen);
void vAsciiStringInit(char *string, size_t *stringLen, size_t fullLen);
void vAsciiStringAddDecimalInt(char *string, size_t *stringLen, uint8_t number, uint8_t digits);
void vAsciiStringAddDecimalInt64(char *string, size_t *stringLen, uint64_t number, uint8_t digits);
void vAsciiStringAddDecimalIntWithLimit(char *string, size_t *stringLen, int64_t number, uint8_t digitsLimit);
void vAsciiStringAddByteAsHex(char *str, size_t *stringLen, uint8_t number);
void vAsciiStringAddBytesAsHex(char *str, size_t *stringLen, uint8_t *bytesData, size_t bytesCount);
void vAsciiStringAddDecimalFloatWithLimit(
char *string,
size_t *stringLen,
double number,
uint8_t intDigits,
uint8_t fractionalDigits
);
#endif //ASCIISTRINGASSMEBLINGUTILS_ASCIISTRINGASSMEBLINGUTILS_H

128
APP/BitBuffer.c Normal file
View File

@ -0,0 +1,128 @@
/*
* BitOps.c
*
* Created on: Apr 13, 2021
* Author: zemon
*/
#include "BitBuffer.h"
void vBitBufferAppendDataByteBitsCountWithBitsOffset(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t appendableByte,
uint8_t countOfAppendableBits
) {
uint16_t fullBytesOffset = offsetOfFirstBit / 8;
uint8_t bitsOffsetInFirstByte = offsetOfFirstBit % 8;
uint8_t bitsWritedToSecondByte = bitsOffsetInFirstByte + countOfAppendableBits - 8;
uint8_t firstByteCut = appendableByte << (8 - countOfAppendableBits);
destinationBitSequence[fullBytesOffset] |= firstByteCut >> bitsOffsetInFirstByte;
if (bitsWritedToSecondByte > 0) {
destinationBitSequence[fullBytesOffset + 1] |= appendableByte << (8 - bitsWritedToSecondByte);
}
}
uint8_t vBitBufferAppendByte(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t appendableByte,
uint8_t countOfAppendableBits
) {
vBitBufferAppendDataByteBitsCountWithBitsOffset(
destinationBitSequence,
offsetOfFirstBit,
appendableByte,
countOfAppendableBits
);
return countOfAppendableBits;
}
uint8_t vBitBufferAppendBits(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t *appendableData,
uint8_t countOfAppendableBits
) {
uint16_t fullBytes = countOfAppendableBits / 8;
uint16_t notFullByteBits = countOfAppendableBits % 8;
uint16_t i = 0;
for (; i < fullBytes; ++i) {
vBitBufferAppendDataByteBitsCountWithBitsOffset(
destinationBitSequence,
offsetOfFirstBit,
appendableData[i], 8
);
offsetOfFirstBit += 8;
}
if (notFullByteBits > 0) {
vBitBufferAppendDataByteBitsCountWithBitsOffset(
destinationBitSequence,
offsetOfFirstBit,
appendableData[i],
notFullByteBits
);
}
return countOfAppendableBits;
}
uint8_t vBitBufferAppendBitsReverseBytes(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t *appendableData,
uint8_t countOfAppendableBits
) {
uint16_t fullBytes = countOfAppendableBits / 8;
uint16_t notFullByteBits = countOfAppendableBits % 8;
uint16_t totalBytes = fullBytes + (notFullByteBits > 0 ? 1 : 0);
uint16_t i = 0;
for (; i < fullBytes; ++i) {
vBitBufferAppendDataByteBitsCountWithBitsOffset(
destinationBitSequence,
offsetOfFirstBit,
appendableData[(totalBytes - 1) - i],
8
);
offsetOfFirstBit += 8;
}
if (notFullByteBits > 0) {
vBitBufferAppendDataByteBitsCountWithBitsOffset(
destinationBitSequence,
offsetOfFirstBit,
appendableData[(totalBytes - 1) - i],
notFullByteBits
);
}
return countOfAppendableBits;
}
uint8_t vBitBufferAppendBytesReverse(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t *appendableData,
uint8_t countOfAppendableBytes
) {
for (int i = countOfAppendableBytes - 1; i > -1; --i) {
vBitBufferAppendDataByteBitsCountWithBitsOffset(
destinationBitSequence,
offsetOfFirstBit,
appendableData[i], 8
);
offsetOfFirstBit += 8;
}
return countOfAppendableBytes * 8;
}

50
APP/BitBuffer.h Normal file
View File

@ -0,0 +1,50 @@
/*
* BitOps.h
*
* Created on: Apr 13, 2021
* Author: zemon
*/
#ifndef BITOPS_INC_BITOPS_H_
#define BITOPS_INC_BITOPS_H_
#include "stdint.h"
void vBitBufferAppendDataByteBitsCountWithBitsOffset(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t appendableByte,
uint8_t countOfAppendableBits
);
uint8_t vBitBufferAppendByte(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t appendableByte,
uint8_t countOfAppendableBits
);
uint8_t vBitBufferAppendBits(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t *appendableData,
uint8_t countOfAppendableBits
);
uint8_t vBitBufferAppendBitsReverseBytes(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t *appendableData,
uint8_t countOfAppendableBits
);
uint8_t vBitBufferAppendBytesReverse(
uint8_t *destinationBitSequence,
uint16_t offsetOfFirstBit,
uint8_t *appendableData,
uint8_t countOfAppendableBytes
);
#endif /* BITOPS_INC_BITOPS_H_ */

24
APP/EcallTypes.h Normal file
View File

@ -0,0 +1,24 @@
//
// Created by xemon on 8/23/22.
//
#ifndef MODULE_ECALLTYPES_H
#define MODULE_ECALLTYPES_H
typedef enum {
AUTOMATIC_ACTIVATION = 1,
MANUAL_ACTIVATION = 0
} eEcallActivationType;
typedef enum {
TEST_CALL = 1,
EMERGENCY_CALL = 0
} eEcallTestMode;
typedef enum {
NOT_CHANGE_TIME = 2,
GNSS_TIME_SOURSE = 1,
RTC_TIME_SOURSE = 0
} eEcallTimeSourse;
#endif //MODULE_ECALLTYPES_H

534
APP/EraGlonassMsd.c Normal file
View File

@ -0,0 +1,534 @@
/*
* msd.c
*
* Created on: OCT 21, 2020
* Author: FICOM-IT LTD
*/
#include "EraGlonassMsd.h"
#include "BitBuffer.h"
#include <memory.h>
void EraGlonassMsdInit(tEraGlonassMsd *env) {
// env->lastPos = (tEraGlonassMsd_GpsPos) {512, 512};
//init not changeable fields
env->MSD_Data.msgId = 0;
env->MSD_Data.msdId = MSD_V_2; // MSD format version
env->MSD_Data.MSD_Control.extraData = 0x00; // Additional information not included
// aGpsStatus
env->MSD_Data.MSD_Control.recentPos1 = 0x01; // Recent vehicle position 1 available
env->MSD_Data.MSD_Control.recentPos2 = 0x01; // Recent vehicle position 2 available
env->MSD_Data.additionalData.coordSystem = ERA_GLONASS_MSD_COORDINATE_SYSTEM_TYPE_WGS84;
env->MSD_Data.additionalData.diagnosticResult = NULL;
}
void EraGlonassMsd_ClearDiagnostic(tMSD_DiagnosticResult *env) {
memset(env, 0, sizeof(tMSD_DiagnosticResult));
}
// In case we don't have valid GPS data set defaults as described in EN15722
void EraGlonassMsdNoGnssSetDefaults(tEraGlonassMsd *env) {
env->MSD_Data.timestamp = 0x00;
env->MSD_Data.pos.lat = 0xFFFFFFFF;
env->MSD_Data.pos.lon = 0xFFFFFFFF;
// env->MSD_Data.pos.lat = 0xFFFFFFF;
// env->MSD_Data.pos.lon = 0xFFFFFFF;
env->MSD_Data.direction = 0xFF;
env->MSD_Data.MSD_PosDelta[0].lat = 512;
env->MSD_Data.MSD_PosDelta[0].lon = 512;
env->MSD_Data.MSD_PosDelta[1].lat = 512;
env->MSD_Data.MSD_PosDelta[1].lon = 512;
// aGpsStatus
env->MSD_Data.MSD_Control.recentPos1 = 0x00; // Recent vehicle position 1 available
env->MSD_Data.MSD_Control.recentPos2 = 0x00; // Recent vehicle position 2 available
}
void EraGlonassMsdSetDataEmergencySituationFlags(
tEraGlonassMsd *env,
int MSD_MSG_ID,
eEcallActivationType eCallType,
eEcallTestMode eCallTestMode
) {
// Message ID
env->MSD_Data.msgId = MSD_MSG_ID;
// Automatic or manual eCall activation
if (eCallType == AUTOMATIC_ACTIVATION) {
env->MSD_Data.MSD_Control.activation = 1;
}
if (eCallType == MANUAL_ACTIVATION) {
env->MSD_Data.MSD_Control.activation = 0;
}
// Test eCall
if (eCallTestMode == TEST_CALL) {
env->MSD_Data.MSD_Control.testCall = 1;
}
if (eCallTestMode == EMERGENCY_CALL) {
env->MSD_Data.MSD_Control.testCall = 0;
}
}
void EraGlonassMsdCalcPosDelta(tEraGlonassMsd *env, tEraGlonassMsd_GpsPos lastPos) {
int16_t deltaLat = 0, deltaLon = 0;
deltaLat = (lastPos.lat - env->MSD_Data.pos.lat) / 100;
deltaLon = (lastPos.lon - env->MSD_Data.pos.lon) / 100;
if (deltaLat <= -512) {
deltaLat = -512;
} else if (deltaLat >= 511) {
deltaLat = 511;
}
deltaLat += 512; // Make offset
if (deltaLon <= -512) {
deltaLon = -512;
} else if (deltaLon >= 511) {
deltaLon = 511;
}
deltaLon += 512;
env->MSD_Data.MSD_PosDelta[1].lat = env->MSD_Data.MSD_PosDelta[0].lat;
env->MSD_Data.MSD_PosDelta[1].lon = env->MSD_Data.MSD_PosDelta[0].lon;
env->MSD_Data.MSD_Control.recentPos2 = env->MSD_Data.MSD_Control.recentPos1;
env->MSD_Data.MSD_PosDelta[0].lat = deltaLat;
env->MSD_Data.MSD_PosDelta[0].lon = deltaLon;
env->MSD_Data.MSD_Control.recentPos1 = 0x01;
//Update to the latest position in order to calculate
//correctly the deltas on the next iteration
// env->lastPos.lat = env->MSD_Data.pos.lat;
// env->lastPos.lon = env->MSD_Data.pos.lon;
}
void EraGlonassMsdSetTimeStamp(tEraGlonassMsd *env, uint32_t timestamp) {
env->MSD_Data.timestamp = timestamp;
}
void EraGlonassMsdSetPositionValue(
tEraGlonassMsd *env,
int32_t lonArc,
int32_t latArc,
uint16_t track,
uint8_t valid
) {
tEraGlonassMsd_GpsPos lastPos = env->MSD_Data.pos;
env->MSD_Data.pos.lat = latArc;
env->MSD_Data.pos.lon = lonArc;
if (valid == 0) {
env->MSD_Data.MSD_Control.posStatus = 0x00; // False if position is not valid
env->MSD_Data.direction = 0xFF;
} else if (valid == 1){
EraGlonassMsdCalcPosDelta(env, lastPos);
env->MSD_Data.MSD_Control.posStatus = 0x00;
env->MSD_Data.direction = 0xFF;
} else if (valid == 2){
EraGlonassMsdCalcPosDelta(env, lastPos);
env->MSD_Data.MSD_Control.posStatus = 0x01;
// env->MSD_Data.direction = (track / 2); //(*255)/2
env->MSD_Data.direction = track; //(*255)/2
}
env->MSD_Data.pos.lat += 0x80000000; // Make offset
env->MSD_Data.pos.lon += 0x80000000;
}
void EraGlonassMsdSetPassengersNumber(tEraGlonassMsd *env, uint16_t value) {
// Check passengers number
if (value >= 1) {
env->MSD_Data.MSD_Control.passengers = value; // Passengers number available
} else {
env->MSD_Data.MSD_Control.passengers = 0x00; // Passengers number not available
}
}
void EraGlonassMsdSetVehicleType(tEraGlonassMsd *env, eUveosGostVehicleType value) {
env->MSD_Data.MSD_Control.vehicleType = value;
}
void EraGlonassMsdSetVIN(tEraGlonassMsd *env, char *vin, uint8_t vinLen) {
unsigned char ch = 0, i = 0;
// Set VIN
for (i = 0; i < 17; i++) {
if (i < vinLen) {
ch = vin[i];
} else {
ch = '0';
}
if (ch >= '0' && ch <= '9') {
ch -= 0x30; // Numbers are encoded with valuese 0x00 to 0x09
} else if (ch >= 'A' && ch <= 'H') {
ch -= 0x37;
} else if (ch >= 'J' && ch <= 'N') {
ch -= 0x38;
} else if (ch == 'P') {
ch = 0x17;
} else if (ch >= 'R' && ch <= 'Z') {
ch -= 0x3A;
} else {
ch = '0' - 0x30;
}
env->MSD_Data.vin[i] = ch;
}
}
void EraGlonassMsdSetPropulsionStorageType(
tEraGlonassMsd *env,
eUveosGostVehiclePropulsionStorageType value
) {
env->MSD_Data.MSD_Control.includedTanks = 0b01111111; // Enable all tank type to be transmitted
// Set propulsion system storage
env->MSD_Data.propulsion = value;
}
uint16_t sEraGlonassMsdEncodeOfControl(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
lastBit += vBitBufferAppendByte(raw, lastBit, data->msgId, 8);
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.activation ? 0x01 : 0x00, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.testCall ? 0x01 : 0x00, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.posStatus ? 0x01 : 0x00, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.vehicleType, 5);
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfVin(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
for (int i = 0; i < 17; ++i) {
lastBit += vBitBufferAppendByte(raw, lastBit, ((uint8_t) data->vin[i]), 6);
}
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfPropulsion(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
uint8_t maxCountOfTanks;
if (data->msdId == MSD_V_1) {
maxCountOfTanks = 6;
} else if (data->msdId == MSD_V_2) {
maxCountOfTanks = 7;
}
uint8_t tanksInfoIncluded = !(data->MSD_Control.includedTanks >> maxCountOfTanks) && 0x1;
if (tanksInfoIncluded) {
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.includedTanks, maxCountOfTanks + 1);
for (int i = 0; i < maxCountOfTanks; ++i) {
if ((data->MSD_Control.includedTanks >> i) && 0x1) {
lastBit += vBitBufferAppendByte(raw, lastBit, (data->propulsion >> i), 1);
}
}
} else {
lastBit += vBitBufferAppendByte(raw, lastBit, 0x1, 1);
}
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfTimestamp(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
lastBit += vBitBufferAppendBitsReverseBytes(raw, lastBit, (uint8_t *) &data->timestamp, 32);
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfLocation(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
lastBit += vBitBufferAppendBitsReverseBytes(raw, lastBit, (uint8_t *) &data->pos.lat, 32);
lastBit += vBitBufferAppendBitsReverseBytes(raw, lastBit, (uint8_t *) &data->pos.lon, 32);
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfDirection(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
\
lastBit += vBitBufferAppendByte(raw, lastBit, data->direction, 8);
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfRecentPositions(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
\
if (data->MSD_Control.recentPos1) {
lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[0].lat, 10);
lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[0].lon, 10);
}
if (data->MSD_Control.recentPos2) {
lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[1].lat, 10);
lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[1].lon, 10);
}
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfPassengersCount(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
if (data->MSD_Control.passengers) {
lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_Control.passengers, 8);
}
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfV1FreeSpaceFix(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
if (data->msdId == MSD_V_1) {
lastBit += vBitBufferAppendByte(raw, lastBit, 0x00, 8);
}
return lastBit;
}
uint16_t
sEraGlonassMsdEncodeOfAdditionalDataOID(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
lastBit += vBitBufferAppendByte(raw, lastBit, 0x03, 8);//lent of OID
lastBit += vBitBufferAppendByte(raw, lastBit, 0x01, 8);//OID 1
lastBit += vBitBufferAppendByte(raw, lastBit, 0x04, 8);//OID 2
if (data->msdId == MSD_V_1) {
lastBit += vBitBufferAppendByte(raw, lastBit, 0x01, 8);//OID 3
} else if (data->msdId == MSD_V_2) {
lastBit += vBitBufferAppendByte(raw, lastBit, 0x02, 8);//OID 3
}
return lastBit;
}
#define MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(FLAG) lastBit += vBitBufferAppendByte(raw, lastBit, (FLAG) == ERA_GLONASS_MSD_OPTIONAL_FLAG_ABSENT ? 0b0 : 0b1, 1);
#define MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(FLAG) \
if((FLAG) == ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_TRUE) { lastBit += vBitBufferAppendByte(raw, lastBit, 0b1 , 1);} \
else if((FLAG) == ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_FALSE) { lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1);}
uint16_t sEraGlonassMsdEncodeOfAdditionalDataPayload(
tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit
) {
lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1); // enable extendable
//enable what present
lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.asi15Present ? 0b1 : 0b0, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.diagnosticResult ? 0b1 : 0b0, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.crashInfoPresent ? 0b1 : 0b0, 1);
if (data->msdId == MSD_V_2) {
lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.coordSystem ? 0b1 : 0b0,
1); // enable extendable
}
if (data->additionalData.asi15Present) {
lastBit += vBitBufferAppendByte(raw, lastBit, ((uint8_t *) &data->additionalData.asi15)[1], 3);
lastBit += vBitBufferAppendByte(raw, lastBit, ((uint8_t *) &data->additionalData.asi15)[0], 8);
}
if (data->additionalData.diagnosticResult) {
tMSD_DiagnosticResult *diagRes = data->additionalData.diagnosticResult;
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->micConnectionFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->micFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->rightSpeakerFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->leftSpeakerFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->speakersFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->ignitionLineFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->uimFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->statusIndicatorFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->batteryFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->batteryVoltageLow);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->crashSensorFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->firmwareImageCorruption);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->commModuleInterfaceFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->gnssReceiverFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->raimProblem);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->gnssAntennaFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->commModuleFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->eventsMemoryOverflow);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->crashProfileMemoryOverflow);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->otherCriticalFailures);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->otherNotCriticalFailures);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->micConnectionFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->micFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->rightSpeakerFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->leftSpeakerFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->speakersFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->ignitionLineFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->uimFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->statusIndicatorFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->batteryFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->batteryVoltageLow);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->crashSensorFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->firmwareImageCorruption);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->commModuleInterfaceFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->gnssReceiverFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->raimProblem);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->gnssAntennaFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->commModuleFailure);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->eventsMemoryOverflow);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->crashProfileMemoryOverflow);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->otherCriticalFailures);
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->otherNotCriticalFailures);
}
if (data->additionalData.crashInfoPresent) {
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashFront)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashLeftSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashRightSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashRear)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashWithRollover)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashFrontOrSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashOtherType)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashFront)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashLeftSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashRightSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashRear)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashWithRollover)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashFrontOrSide)
MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashOtherType)
}
if (data->msdId == MSD_V_2) {
lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.coordSystem, 2);
}
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfAdditionalDataOctetString(
tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit
) {
uint16_t octetStringOffset = lastBit + 8;
uint16_t octetStringBitsLength =
sEraGlonassMsdEncodeOfAdditionalDataPayload(data, raw, octetStringOffset) - (octetStringOffset);
uint8_t octetsCount = octetStringBitsLength / 8 + (octetStringBitsLength % 8 ? 1 : 0);
lastBit += vBitBufferAppendByte(raw, lastBit, octetsCount, 8);
lastBit += octetsCount * 8;
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfAdditionalData(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
lastBit = sEraGlonassMsdEncodeOfAdditionalDataOID(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfAdditionalDataOctetString(data, raw, lastBit);
return lastBit;
}
uint16_t sEraGlonassMsdEncodeOfMsdMainBody(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalDataPresent ? 0b1 : 0b0, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1);
// lastBit+= vBitBufferAppendByte(raw,lastBit,data->MSD_Control.extraData,3);
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.recentPos1 ? 0x01 : 0x00, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.recentPos2 ? 0x01 : 0x00, 1);
lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.passengers ? 0x01 : 0x00, 1);
lastBit = sEraGlonassMsdEncodeOfControl(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfVin(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfPropulsion(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfV1FreeSpaceFix(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfTimestamp(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfLocation(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfDirection(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfRecentPositions(data, raw, lastBit);
lastBit = sEraGlonassMsdEncodeOfPassengersCount(data, raw, lastBit);
if (data->additionalDataPresent) {
lastBit = sEraGlonassMsdEncodeOfAdditionalData(data, raw, lastBit);
}
return lastBit;
}
uint16_t sEraGlonassMsdEncodeV2BodyOctetString(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) {
//length of msd block
uint16_t octetStringOffset = lastBit + 8;
uint16_t octetStringBitsLength =
sEraGlonassMsdEncodeOfMsdMainBody(data, raw, octetStringOffset) - (octetStringOffset);
uint8_t octetsCount = octetStringBitsLength / 8 + (octetStringBitsLength % 8 ? 1 : 0);
lastBit += vBitBufferAppendByte(raw, lastBit, octetsCount, 8);
lastBit += octetsCount * 8;
return lastBit;
}
uint16_t EraGlonassMsdEncode(tEraGlonassMsd *env, eEraGlonassMsd_Version msdVersion, uint8_t *encoded) {
env->MSD_Data.msdId = msdVersion;
memset(encoded, '\0', ERA_GLONASS_MSD_ENCODED_BUFFER_LENGTH); // Clear
uint16_t lastBit = 0;
lastBit += vBitBufferAppendByte(encoded, lastBit, env->MSD_Data.msdId, 8);
if (env->MSD_Data.msdId == MSD_V_1) {
lastBit = sEraGlonassMsdEncodeOfMsdMainBody(&env->MSD_Data, encoded, lastBit);
} else if (env->MSD_Data.msdId == MSD_V_2) {
lastBit = sEraGlonassMsdEncodeV2BodyOctetString(&env->MSD_Data, encoded, lastBit);
}
size_t byteLength = lastBit / 8 + (lastBit % 8 ? 1 : 0);
return byteLength;
}

177
APP/EraGlonassMsd.h Normal file
View File

@ -0,0 +1,177 @@
/*
* msd.h
*
* Created on: Oct 20, 2020
* Author: FICOM-IT LTD
*/
#ifndef INC_MSD_H_
#define INC_MSD_H_
#include <stdint.h>
#include <stdbool.h>
#include <UveosGostSettingsTypes.h>
#include "EcallTypes.h"
#define ERA_GLONASS_MSD_ENCODED_BUFFER_LENGTH 128
typedef enum {
MSD_V_1 = 1,
MSD_V_2 = 2,
} eEraGlonassMsd_Version;
// @brief Control and status data
typedef struct {
uint16_t extraData; // 000 - additional data excluded, 010 - additional data included
uint16_t recentPos1; // True if previous location is available
uint16_t recentPos2; // True if previous location is available
uint16_t passengers; // True if passangers' number is available
uint16_t activation; // True if Automatic, False if manual eCall activation
uint16_t testCall; // True if test eCall, Flase if not test eCall
uint16_t posStatus; // True if GPS position can be trusted
uint16_t vehicleType; // Vehicle identification according to 2007/46/EC, 2002/24/EC
uint16_t includedTanks; // if True include status data (present/not present) for the relevant tank
} tEraGlonassMsd_Control;
// @brief Vehicle location stored in milli-arc-second
typedef struct {
int32_t lat; // Position latitude
int32_t lon; // Position longitude
} tEraGlonassMsd_GpsPos;
// @brief Vehicle location difference with the previous location stored in milli-arc-second
typedef struct {
uint16_t lat;
uint16_t lon;
} tEraGlonassMsd_PosDelta;
typedef enum {
ERA_GLONASS_MSD_OPTIONAL_FLAG_ABSENT = 0,
ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_TRUE = 1,
ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_FALSE = 2,
} tEraGlonassMsd_OptionalFlagState;
typedef uint8_t tEraGlonassMsd_OptionalFlag;
#define EraGlonassMsd_OptionalFlagClear(FLAG) (GLAG) = ERA_GLONASS_MSD_OPTIONAL_FLAG_ABSENT
#define EraGlonassMsd_OptionalFlagSet(FLAG, VALUE) (FLAG) = (VALUE) ? ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_TRUE : ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_FALSE
typedef struct {
tEraGlonassMsd_OptionalFlag CrashFront;
tEraGlonassMsd_OptionalFlag CrashLeftSide;
tEraGlonassMsd_OptionalFlag CrashRightSide;
tEraGlonassMsd_OptionalFlag CrashRear;
tEraGlonassMsd_OptionalFlag CrashWithRollover;
tEraGlonassMsd_OptionalFlag CrashSide;
tEraGlonassMsd_OptionalFlag CrashFrontOrSide;
tEraGlonassMsd_OptionalFlag CrashOtherType;
} tMSD_CrashInfo;
#define EraGlonassMsd_CrashInfoClear(ENV) memset(ENV, 0, sizeof(tMSD_CrashInfo))
typedef struct {
tEraGlonassMsd_OptionalFlag micConnectionFailure;
tEraGlonassMsd_OptionalFlag micFailure;
tEraGlonassMsd_OptionalFlag rightSpeakerFailure;
tEraGlonassMsd_OptionalFlag leftSpeakerFailure;
tEraGlonassMsd_OptionalFlag speakersFailure;
tEraGlonassMsd_OptionalFlag ignitionLineFailure;
tEraGlonassMsd_OptionalFlag uimFailure;
tEraGlonassMsd_OptionalFlag statusIndicatorFailure;
tEraGlonassMsd_OptionalFlag batteryFailure;
tEraGlonassMsd_OptionalFlag batteryVoltageLow;
tEraGlonassMsd_OptionalFlag crashSensorFailure;
tEraGlonassMsd_OptionalFlag firmwareImageCorruption;
tEraGlonassMsd_OptionalFlag commModuleInterfaceFailure;
tEraGlonassMsd_OptionalFlag gnssReceiverFailure;
tEraGlonassMsd_OptionalFlag raimProblem;
tEraGlonassMsd_OptionalFlag gnssAntennaFailure;
tEraGlonassMsd_OptionalFlag commModuleFailure;
tEraGlonassMsd_OptionalFlag eventsMemoryOverflow;
tEraGlonassMsd_OptionalFlag crashProfileMemoryOverflow;
tEraGlonassMsd_OptionalFlag otherCriticalFailures;
tEraGlonassMsd_OptionalFlag otherNotCriticalFailures;
} tMSD_DiagnosticResult;
typedef enum {
ERA_GLONASS_MSD_COORDINATE_SYSTEM_TYPE_WGS84 = 0x01,
ERA_GLONASS_MSD_COORDINATE_SYSTEM_TYPE_PZ90 = 0x02,
} eEraGlonassMsd_CoordinateSystemType;
typedef struct {
bool asi15Present;
bool crashInfoPresent;
uint16_t asi15;
tMSD_CrashInfo crashInfo;
eEraGlonassMsd_CoordinateSystemType coordSystem;
tMSD_DiagnosticResult *diagnosticResult;
} tEraGlonassMsd_AdditionalData;
// @brief MSD data structure
typedef struct {
uint16_t msdId; // MSD format version set to 1
uint16_t msgId; // Message identifier, starting with 1 for each new eCall session
tEraGlonassMsd_Control MSD_Control; // Control flags and data
uint16_t vin[18]; // VIN
uint16_t propulsion; // Vehicle propulsion storage type
uint32_t timestamp; // Timestamp
tEraGlonassMsd_GpsPos pos; // Vehicle position
uint8_t direction; // Vehicle heading, course over ground, course over north
tEraGlonassMsd_PosDelta MSD_PosDelta[2]; // Previous position delta
bool additionalDataPresent;
tEraGlonassMsd_AdditionalData additionalData; // Additional data
} tEraGlonassMsd_DataTypedef;
typedef struct {
tEraGlonassMsd_DataTypedef MSD_Data;
// tEraGlonassMsd_GpsPos lastPos;
} tEraGlonassMsd;
//Must be called on create
void EraGlonassMsdInit(tEraGlonassMsd *env);
void EraGlonassMsd_ClearDiagnostic(tMSD_DiagnosticResult *env);
//Must be called when settings changed
void EraGlonassMsdSetPassengersNumber(tEraGlonassMsd *env, uint16_t value);
void EraGlonassMsdSetVehicleType(tEraGlonassMsd *env, eUveosGostVehicleType value);
void EraGlonassMsdSetVIN(tEraGlonassMsd *env, char *vin, uint8_t vinLen);
void EraGlonassMsdSetPropulsionStorageType(tEraGlonassMsd *env, eUveosGostVehiclePropulsionStorageType value);
//Must be called when gnss data changed
void EraGlonassMsdSetTimeStamp(tEraGlonassMsd *env, uint32_t timestamp);
void EraGlonassMsdSetPositionValue(
tEraGlonassMsd *env,
int32_t lonArc,
int32_t latArc,
uint16_t track,
uint8_t valid
);
void EraGlonassMsdNoGnssSetDefaults(tEraGlonassMsd *env);
//Called on emergency situation
void EraGlonassMsdSetDataEmergencySituationFlags(
tEraGlonassMsd *env,
int MSD_MSG_ID,
eEcallActivationType eCallType,
eEcallTestMode eCallTestMode
);
uint16_t EraGlonassMsdEncode(tEraGlonassMsd *env, eEraGlonassMsd_Version msdVersion, uint8_t *encoded);
#endif /* INC_MSD_H_ */

104
APP/UveosGostSettings.h Normal file
View File

@ -0,0 +1,104 @@
/*
* UVEOS_GOST_Settings.h
*
* Created on: Apr 12, 2021
* Author: zemon
*/
#ifndef INC_UVEOS_GOST_SETTINGS_H_
#define INC_UVEOS_GOST_SETTINGS_H_
#include "stdint.h"
#include "stdbool.h"
#include "BaseTypes.h"
#include <UveosGostSettingsTypes.h>
typedef struct {
bool ECALL_TEST_MODE; //совершать все вызовы на тестовый номер
uint8_t FULL_POWER_OFF_TIME;
uint16_t BIP_BACKLIGHT_MODE;
uint16_t BIP_GREEN_LED_POWER_MODE;
uint16_t BIP_RED_LED_POWER_MODE;
} tUveosNotGostSettings;
typedef struct {
//Radio settings
uint16_t RADIO_MUTE_DELAY; //*(МС) Задержка между установкой сигнала «радио mute» и началом проигрывания звука
uint16_t RADIO_UNMUTE_DELAY; //*(МС) Задержка между снятием сигнала «радио mute» и окончанием проигрывания звукае
//настройки сробатывания
uint8_t CRASH_SIGNAL_INTERNAL; //* Только транспортные средства категорий М1 и N1 — для определения события аварии используется встроенный измеритель ускорения
uint8_t CRASH_SIGNAL_EXTERNAL; //* Только транспортные средства категорий М1 и N1 — для определения факта ДТП используется внешний датчик в транспортном средстве
float ASI15_TRESHOLD; //* Только транспортные средства категорий М1 и N1 — порог срабатывания датчика автоматической идентификации события ДТП
uint16_t SOS_BUTTON_TIME; //* (МС) Время нажатия на кнопку «Экстренный вызов» для активации режима «Экстренный вызов»
uint8_t ECALL_NO_AUTOMATIC_TRIGGERING; //Параметр используется для отмены функции автоматической инициации экстренного вызова
//Параметры дозвона
tString16 ECALL_TEST_NUMBER; //номер для тестового вызова
uint16_t CCFT; //(МИН) Длительность счетчика автоматического прекращения звонка (60 м)
uint16_t ECALL_DIAL_DURATION; //(МИН) Общая продолжительность дозвона при инициации экстренного вызова
uint64_t MSD_MAX_TRANSMISSION_TIME; //(CEK) Максимальная длительность передачи MSD (20 с)
uint8_t ECALL_MANUAL_CAN_CANCEL; //TRUE — экстренный вызов, инициированный вручную, может быть прекращен со стороны пользователя
//Ожидание
uint64_t CALL_AUTO_ANSWER_TIME; //(МИН)Промежуток времени после завершения экстренного вызова, в течение которого УСВ автоматически отвечает на входящие звонки
//Веремя регестрации в сети
uint64_t NAD_DEREGISTRATION_TIME; //(МИН) Время, после которого коммуникационный модуль GSM и UMTS прекращает регистрацию в сети
uint64_t POST_TEST_REGISTRATION_TIME; //Промежуток времени, в течение которого УСВ остается зарегистрированной в сети после передачи результатов тестирования оператору системы
//Оптравка экстренных ситуаций из памяти
tString16 ECALL_SMS_FALLBACK_NUMBER; //Номер, по которому УСВ посылает SMS с МНД при ошибке передачи МНД посредством in-band модема и по запросу от оператора системы. Определяется оператором национальной системы реагирования на аварии
uint64_t INT_MEM_TRANSMIT_INTERVAL; //интервал времени между повторными попытками отправки мнд из памяти
uint16_t INT_MEM_TRANSMIT_ATTEMPTS; //количество попыток отпкравки мнд из памяти
//Попытки дозвона
uint16_t ECALL_AUTO_DIAL_ATTEMPTS; //Только транспортные средства категорий М1 и N1 — число попыток дозвона при автоматически инициированном экстренном вызове. Не может быть установлено в «0»
uint16_t ECALL_MANUAL_DIAL_ATTEMPTS; //Число попыток дозвона при экстренном вызове, инициированном вручную. Значение не может устанавливаться в «0»
//Testing settings - тестирование и гараж
// Если УСВ была зарегистрирована в сети посредством нажатия на кнопку «Дополнительные функции»,
// то последующая регистрация УСВ в сети при нажатии на кнопку «Дополнительные функции» возможна
// не ранее чем через данный промежуток времени. Если значение установлено в «0»,
// то ограничений на последующую регистрацию УСВ в сети не накладывается
uint16_t TEST_REGISTRATION_PERIOD;
uint16_t TEST_MODE_END_DISTANCE; //(Метры)Дистанция, на которой режим тестирования выключается автоматически
uint16_t GARAGE_MODE_END_DISTANCE; //*(Метры) Дистанция, на которой режим «Автосервис» выключается автоматически
//Emergence acceleration profile - полностью используеться в коплектации доп оборудования
uint16_t IGNITION_OFF_FOLLOW_UP_TIME1; //* Промежуток времени, в течение которого осуществляется запись профиля ускорения при ДТП при выключенном зажигании
uint16_t IGNITION_OFF_FOLLOW_UP_TIME2; //* Промежуток времени, в течение которого осуществляется определение события аварии при выключенном зажигании
uint16_t CRASH_RECORD_TIME; //* Время записи информации о профиле ускорения при ДТП
uint16_t CRASH_RECORD_RESOLUTION; //* Дискретность записи профиля ускорения при ДТП
uint16_t CRASH_PRE_RECORD_TIME; //* Время записи информации о профиле ускорения до того, как событие ДТП наступило
uint16_t CRASH_PRE_RECORD_RESOLUTION; //* Продолжительность одного отсчета при записи профиля ускорения до того, как событие ДТП наступило
//Other settings - параметры навигацонного приемника - используються при инициализации приемника, а так же записываются в него после их изменения (все без участия УВЕОС,платформозависомо)
uint16_t GNSS_POWER_OFF_TIME; //* Промежуток времени, через который отключается питание приемника ГНСС после выключения зажигания
uint16_t GNSS_DATA_RATE; //Темп выдачи данных приемником ГНСС
uint16_t GNSS_MIN_ELEVATION; //* Минимальное значение угла возвышения (угла отсечки) навигационных космических аппаратов
//Vehicle parameters - Параметры транспортного средства, записываються в МНД
tString32 VIN; //18
uint16_t VEHICLE_TYPE; //Категория транспортного средства
uint8_t VEHICLE_PROPULSION_STORAGE_TYPE; //Тип энергоносителя
uint8_t VEHICLE_PASSENGERS_NUMBER; //Количество пасажиров
//неиспользуються, у нас пины определены заранее
uint16_t GARAGE_MODE_PIN; //*номер пина на котором поднимаеться сигнал в случае прехода в режим гараж
uint16_t ECALL_MODE_PIN; //*номер пина на котором поднимаеться сигнал в случае прехода в режим ecall
tUveosNotGostSettings notGost;
} tUveosGostSettings;
void vUveosGostSettingsInitDefaults(tUveosGostSettings *gostSettings);
#endif /* INC_UVEOS_GOST_SETTINGS_H_ */

View File

@ -0,0 +1,50 @@
/*
* UVEOS_GOST_SettingsEnums.h
*
* Created on: Apr 12, 2021
* Author: zemon
*/
#ifndef INC_UVEOS_GOST_SETTINGSENUMS_H_
#define INC_UVEOS_GOST_SETTINGSENUMS_H_
typedef enum {
UVEOS_GOST_NONE,
UVEOS_GOST_PIN_1,
UVEOS_GOST_PIN_2,
UVEOS_GOST_PIN_3,
UVEOS_GOST_PIN_4,
UVEOS_GOST_PIN_5,
UVEOS_GOST_PIN_6,
UVEOS_GOST_PIN_7,
UVEOS_GOST_PIN_8
} eUveosGostPin;
typedef enum {
UVEOS_GOST_PASSENGER_VEHICLE_CLASS_M1 = 1,
UVEOS_GOST_BUSES_AND_COACHES_CLASS_M2 = 2,
UVEOS_GOST_BUSES_AND_COACHES_CLASS_M3 = 3,
UVEOS_GOST_LIGHT_COMMERCIAL_VEHICLES_CLASS_N1 = 4,
UVEOS_GOST_HEAVY_DUTY_VEHICLES_CLASS_N2 = 5,
UVEOS_GOST_HEAVY_DUTY_VEHICLES_CLASS_N3 = 6,
UVEOS_GOST_MOTORCYCLE_CLASS_L1E = 7,
UVEOS_GOST_MOTORCYCLE_CLASS_L2E = 8,
UVEOS_GOST_MOTORCYCLE_CLASS_L3E = 9,
UVEOS_GOST_MOTORCYCLE_CLASS_L4E = 10,
UVEOS_GOST_MOTORCYCLE_CLASS_L5E = 11,
UVEOS_GOST_MOTORCYCLE_CLASS_L6E = 12,
UVEOS_GOST_MOTORCYCLE_CLASS_L7E = 13
} eUveosGostVehicleType;
typedef enum {
UVEOS_GOST_GASOLINE_TANK_PRESENT = 32,
UVEOS_GOST_DIESEL_TANK_PRESENT = 16,
UVEOS_GOST_COMPRESSED_NATURAL_GAS = 8,
UVEOS_GOST_LIQUID_PROPANE_GAS = 4,
UVEOS_GOST_ELECTRIC_ENERGY_STORAGE = 2,
UVEOS_GOST_HYDROGEN_STORAGE = 1
} eUveosGostVehiclePropulsionStorageType;
#endif /* INC_UVEOS_GOST_SETTINGSENUMS_H_ */

3191
APP/cJSON.c Normal file

File diff suppressed because it is too large Load Diff

306
APP/cJSON.h Normal file
View File

@ -0,0 +1,306 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 18
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* Limits the length of circular references can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

243
APP/main.c Normal file
View File

@ -0,0 +1,243 @@
//
// Created by cfif on 09.09.2025.
//
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "cJSON.h"
#include "EraGlonassMsd.h"
#include "AsciiStringAssmeblingUtils.h"
char cConvertDecToMilliArcSec(double dec, int32_t *mArcs, double *gradus) {
int deg = 0, min = 0;
double sec = 0.0;
double _dec = dec;
deg = (int) (_dec / 100);
min = (int) (_dec) - (deg * 100);
sec = (double) (_dec - min - 100 * deg) * 60.0;
if (gradus != NULL) *gradus = deg + min / 60.0 + sec / 3600.0;
if (mArcs != NULL) *mArcs = (int) (deg * 3600 + min * 60) * 1000 + (int) (sec * 1000); // mArcseconds
return 0;
}
char cConvertDecToMilliArcSecFromDegMin(double deg, double min, int32_t *mArcs, double *gradus) {
double sec = 0.0;
if (gradus != NULL) *gradus = deg + min / 60.0 + sec / 3600.0;
if (mArcs != NULL) *mArcs = (int) (deg * 3600 + min * 60) * 1000 + (int) (sec * 1000); // mArcseconds
return 0;
}
int main(int argc, char *argv[]) {
// const char *json_string = "{\"timestamp\": \"2024-06-26T09:36:42+05:06\", \"coordinate\": \"56 33.13N 060 54.13E\", \"phone\": \"88312622039\", \"id\": \"00182\" }";
if (argc != 3) {
printf("Usage: conv fileIn fileOut\n");
return 1;
}
FILE *input_file = fopen(argv[1], "r");
if (input_file == NULL) {
printf("Error: Failed to open file %s\n", argv[1]);
return 1;
}
#define BUFFER_SIZE 4096
char json_string[BUFFER_SIZE] = {0};
size_t bytes_read = fread(json_string, 1, BUFFER_SIZE, input_file);
printf("Read %zu bytes:\n", bytes_read);
printf("%.*s\n", (int)bytes_read, json_string);
fclose(input_file);
tEraGlonassMsd msd;
EraGlonassMsdInit(&msd);
EraGlonassMsdSetDataEmergencySituationFlags(&msd, 1, MANUAL_ACTIVATION, EMERGENCY_CALL);
EraGlonassMsdSetVehicleType(&msd, 0);
EraGlonassMsdSetPassengersNumber(&msd, 1);
EraGlonassMsdSetPropulsionStorageType(&msd, 0);
cJSON *json = cJSON_Parse(json_string);
if (json == NULL) {
printf("Error parsing JSON\n");
return 1;
}
cJSON *timestampJS = cJSON_GetObjectItemCaseSensitive(json, "timestamp");
cJSON *coordinateJS = cJSON_GetObjectItemCaseSensitive(json, "coordinate");
cJSON *phoneJS = cJSON_GetObjectItemCaseSensitive(json, "phone");
cJSON *idJS = cJSON_GetObjectItemCaseSensitive(json, "id");
if (cJSON_IsString(timestampJS) && (timestampJS->valuestring != NULL)) {
printf("timestamp (JSON): %s\n", timestampJS->valuestring);
struct tm timeinfo = {0};
int timezone_hour_offset;
int timezone_min_offset;
char timezone_sign;
int result = sscanf(timestampJS->valuestring, "%d-%d-%dT%d:%d:%d%c%d:%d",
&timeinfo.tm_year, &timeinfo.tm_mon, &timeinfo.tm_mday,
&timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec,
&timezone_sign, &timezone_hour_offset, &timezone_min_offset);
if (result >= 6) {
timeinfo.tm_year -= 1900;
timeinfo.tm_mon -= 1;
time_t timestamp = mktime(&timeinfo);
if (result >= 9) {
int offset_seconds = timezone_hour_offset * 3600 + timezone_min_offset * 60;
if (timezone_sign == '-') {
timestamp += offset_seconds;
} else if (timezone_sign == '+') {
timestamp -= offset_seconds;
}
} else {
printf("Parsing timestamp (UTC) error");
return 1;
}
EraGlonassMsdSetTimeStamp(&msd, timestamp);
printf("timestamp: %u\n", msd.MSD_Data.timestamp);
} else {
printf("Parsing timestamp error");
return 1;
}
} else {
printf("Parsing JSON timestamp error");
return 1;
}
if (cJSON_IsString(coordinateJS) && (coordinateJS->valuestring != NULL)) {
printf("coordinate (JSON): %s\n", coordinateJS->valuestring);
int lat_deg, lon_deg;
double lat_min, lon_min;
char lat_dir, lon_dir;
char tmp[1024] = {0};
int len = 0;
for (int i = 0; i < strlen(coordinateJS->valuestring); ++i) {
if ((coordinateJS->valuestring[i + 1] == 'N') || (coordinateJS->valuestring[i + 1] == 'S') ||
(coordinateJS->valuestring[i + 1] == 'W') || (coordinateJS->valuestring[i + 1] == 'E')) {
tmp[len] = coordinateJS->valuestring[i];
++len;
tmp[len] = ' ';
++len;
} else {
tmp[len] = coordinateJS->valuestring[i];
++len;
}
}
int result = sscanf(tmp,
"%d %lf %c %d %lf %c",
&lat_deg, &lat_min, &lat_dir,
&lon_deg, &lon_min, &lon_dir);
if (result == 6) {
double lat_decimal = 0;
double lon_decimal = 0;
cConvertDecToMilliArcSecFromDegMin(lat_deg, lat_min, &msd.MSD_Data.pos.lat, &lat_decimal);
cConvertDecToMilliArcSecFromDegMin(lon_deg, lon_min, &msd.MSD_Data.pos.lon, &lon_decimal);
if (lat_dir == 'S') {
lat_decimal = -lat_decimal;
msd.MSD_Data.pos.lat = -msd.MSD_Data.pos.lat;
}
if (lon_dir == 'W') {
lon_decimal = -lon_decimal;
msd.MSD_Data.pos.lon = -msd.MSD_Data.pos.lon;
}
printf("Latitude (degrees): %lf; dir: %c\n", lat_decimal, lat_dir);
printf("Longitude (degrees): %lf; dir: %c\n", lon_decimal, lon_dir);
printf("Latitude (mArcs): %d\n", msd.MSD_Data.pos.lat);
printf("Longitude (mArcs): %d\n", msd.MSD_Data.pos.lon);
EraGlonassMsdSetPositionValue(&msd, msd.MSD_Data.pos.lon, msd.MSD_Data.pos.lat, 0, 2);
} else {
printf("Parsing coordinate error (1)");
return 1;
}
} else {
printf("Parsing JSON coordinate error");
return 1;
}
if (cJSON_IsString(phoneJS) && (phoneJS->valuestring != NULL)) {
printf("phone (JSON): %s\n", phoneJS->valuestring);
} else {
printf("Parsing JSON phone error");
return 1;
}
if (cJSON_IsString(idJS) && (idJS->valuestring != NULL)) {
printf("id (JSON): %s\n", idJS->valuestring);
char VIN[17] = {0};
memcpy(VIN, idJS->valuestring, 5);
memcpy(&VIN[5], "1111111111", 10);
EraGlonassMsdSetVIN(&msd, VIN, sizeof(VIN));
printf("id (VIN): %s\n", VIN);
} else {
printf("Parsing JSON id error");
return 1;
}
cJSON_Delete(json);
uint8_t msdEncoded[512] = {0};
size_t msdEncodedSize = EraGlonassMsdEncode(&msd, MSD_V_2, msdEncoded);
char egtsHexStr[1024] = {0};
size_t egtsHexStrLen = 0;
vAsciiStringAddBytesAsHex(egtsHexStr, &egtsHexStrLen, msdEncoded, msdEncodedSize);
FILE *output_file = fopen(argv[2], "w");
if (output_file == NULL) {
printf("Error: Failed to open file %s\n", argv[1]);
return 1;
}
size_t bytes_written = fwrite(egtsHexStr, 1, egtsHexStrLen, output_file);
printf("Write %zu bytes:\n", bytes_written);
printf("%.*s\n", (int)bytes_written, egtsHexStr);
fclose(output_file);
return 0;
}

12
APP/modular.json Normal file
View File

@ -0,0 +1,12 @@
{
"cmake": {
"inc_dirs": [
"./"
],
"srcs": [
"./ert_main.c",
"./*.c"
]
}
}

22
CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.17)
project(simulink)
set(CMAKE_CXX_STANDARD 17)
include(modular.cmake)
#link_directories(/usr/local/opt/libpq/lib/)
#include_directories(/usr/local/opt/libpq/include)
#link_directories(/usr/lib/x86_64-linux-gnu/)
#include_directories(/usr/include/postgresql)
#link_libraries(pq)
#link_libraries(tcp)
#link_libraries(pthread)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -funsigned-char -pipe -Wl,-O0 -std=gnu++2a -Wall -Wextra")
add_executable(conv ${SOURCES})
target_link_libraries(conv PRIVATE m)

11
modular.cmake Normal file
View File

@ -0,0 +1,11 @@
function(add_sources FILE_LIST FILES_PATH)
file(GLOB_RECURSE ADD_FILES_LIST ${FILES_PATH})
list(APPEND ${FILE_LIST} ${ADD_FILES_LIST})
set(${FILE_LIST} ${${FILE_LIST}} PARENT_SCOPE)
endfunction()
include_directories("APP/")
add_sources(SOURCES "APP/ert_main.c")
add_sources(SOURCES "APP/*.c")

14
modular.json Normal file
View File

@ -0,0 +1,14 @@
{
"dep": [
{
"type": "local",
"dir": "APP"
}
],
"cmake": {
"inc_dirs": [
],
"srcs": [
]
}
}