270 lines
8.1 KiB
C
270 lines
8.1 KiB
C
//
|
|
// 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");
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
FILE *input_file = fopen(argv[1], "r");
|
|
if (input_file == NULL) {
|
|
printf("Error: Failed to open file %s\n", argv[1]);
|
|
fflush(stdout);
|
|
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 from file: \"%s\", %zu bytes:\n", argv[1], 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");
|
|
fflush(stdout);
|
|
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");
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
EraGlonassMsdSetTimeStamp(&msd, timestamp);
|
|
|
|
printf("timestamp: %u\n", msd.MSD_Data.timestamp);
|
|
|
|
} else {
|
|
printf("Parsing timestamp error");
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
} else {
|
|
printf("Parsing JSON timestamp error");
|
|
fflush(stdout);
|
|
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 (size_t i = 0; i < strlen(coordinateJS->valuestring); ++i) {
|
|
|
|
tmp[len] = coordinateJS->valuestring[i];
|
|
++len;
|
|
|
|
if ((coordinateJS->valuestring[i + 1] == 'N') || (coordinateJS->valuestring[i + 1] == 'S') ||
|
|
(coordinateJS->valuestring[i + 1] == 'W') || (coordinateJS->valuestring[i + 1] == 'E')) {
|
|
tmp[len] = ' ';
|
|
++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");
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
} else {
|
|
printf("Parsing JSON coordinate error");
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
if (cJSON_IsString(phoneJS) && (phoneJS->valuestring != NULL)) {
|
|
printf("phone (JSON): %s\n", phoneJS->valuestring);
|
|
} else {
|
|
printf("Parsing JSON phone error");
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
if (cJSON_IsString(idJS) && (idJS->valuestring != NULL)) {
|
|
printf("id (JSON): %s\n", idJS->valuestring);
|
|
|
|
char VIN[18] = {0};
|
|
|
|
memset(VIN, '0', 17);
|
|
|
|
memcpy(&VIN[17 - 5], 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");
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
|
|
uint8_t msdEncoded[512] = {0};
|
|
|
|
msdEncoded[0] = 0;
|
|
msdEncoded[1] = 15;
|
|
memcpy(&msdEncoded[2], "000000000000000", 15);
|
|
msdEncoded[17] = strlen(phoneJS->valuestring);
|
|
memcpy(&msdEncoded[18], phoneJS->valuestring, strlen(phoneJS->valuestring));
|
|
|
|
msdEncoded[18 + strlen(phoneJS->valuestring)] = 0;
|
|
size_t msdEncodedSize = EraGlonassMsdEncode(&msd, MSD_V_2, &msdEncoded[20 + strlen(phoneJS->valuestring)]);
|
|
msdEncoded[19 + strlen(phoneJS->valuestring)] = msdEncodedSize;
|
|
|
|
char egtsHexStr[1024] = {0};
|
|
size_t egtsHexStrLen = 0;
|
|
vAsciiStringAddBytesAsHex(egtsHexStr, &egtsHexStrLen, msdEncoded, 20 + strlen(phoneJS->valuestring) + msdEncodedSize);
|
|
|
|
|
|
FILE *output_file = fopen(argv[2], "w");
|
|
if (output_file == NULL) {
|
|
printf("Error: Failed to open file %s\n", argv[2]);
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
size_t bytes_written = fwrite(egtsHexStr, 1, egtsHexStrLen, output_file);
|
|
|
|
if (bytes_written != egtsHexStrLen) {
|
|
printf("Error: Failed to write file %s\n", argv[2]);
|
|
fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
printf("Write to file: \"%s\" %zu bytes: %.*s\n", argv[2], bytes_written, (int) bytes_written, egtsHexStr);
|
|
|
|
fclose(output_file);
|
|
|
|
fflush(stdout);
|
|
|
|
cJSON_Delete(json);
|
|
|
|
return 0;
|
|
|
|
|
|
} |