Первый коммит
This commit is contained in:
commit
8567a5bb2a
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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_ */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
|
||||
"cmake": {
|
||||
"inc_dirs": [
|
||||
"./"
|
||||
],
|
||||
"srcs": [
|
||||
"./ert_main.c",
|
||||
"./*.c"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
@ -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")
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"dep": [
|
||||
{
|
||||
"type": "local",
|
||||
"dir": "APP"
|
||||
}
|
||||
],
|
||||
"cmake": {
|
||||
"inc_dirs": [
|
||||
],
|
||||
"srcs": [
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue