From e35d7b3356c77468deb9b134d99e1854f3015ccb Mon Sep 17 00:00:00 2001 From: cfif Date: Wed, 4 Dec 2024 13:10:49 +0300 Subject: [PATCH] Init --- Inc/NmeaACPParser.h | 63 ++++++++++++ Src/NmeaACPParser.c | 233 ++++++++++++++++++++++++++++++++++++++++++++ modular.json | 10 ++ 3 files changed, 306 insertions(+) create mode 100644 Inc/NmeaACPParser.h create mode 100644 Src/NmeaACPParser.c create mode 100644 modular.json diff --git a/Inc/NmeaACPParser.h b/Inc/NmeaACPParser.h new file mode 100644 index 0000000..1c3566c --- /dev/null +++ b/Inc/NmeaACPParser.h @@ -0,0 +1,63 @@ +// +// Created by xemon on 01.09.22. +// + +#ifndef NMEA_ACP_PARSER_H +#define NMEA_ACP_PARSER_H + +#include "stdint.h" +#include "stddef.h" +#include "stdbool.h" + +typedef struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint16_t millisecond; +} tNmeaTimeAcp; + +typedef struct { + uint8_t day; + uint8_t month; + uint8_t year; +} tNmeaDateAcp; + +typedef struct { + double latitude; + char nsIndicator; + double longitude; + double horizontDiluitPrecis; + double altitude; + char ewIndicator; +} tNmeaLocationAcp; + +typedef struct { + double declination; + double nsat; + double mode; +} tNmeaMagneticAcp; + +typedef struct { + char status; + + tNmeaDateAcp date; + tNmeaTimeAcp time; + tNmeaLocationAcp location; + tNmeaMagneticAcp magnetic; + + double knotVelocity; + double kmhVelocity; + double course; +} tNmeaAcp; + +uint32_t iNmeaTimestampFromAcp(tNmeaAcp *env); + +void vNmeaACPSign(char *str, size_t *strLen); + +bool bNmeaACPParse(char *acprmcString, size_t len, tNmeaAcp *result); + +bool bNmeaACPString(char *nmeaString, size_t len, tNmeaAcp *acp); + +bool bNmeaACPIsValidString(char *nmeaString, size_t len); + +#endif //NMEA_0183_PARSER_NMEA_0183_PARSER_H diff --git a/Src/NmeaACPParser.c b/Src/NmeaACPParser.c new file mode 100644 index 0000000..a6e19ff --- /dev/null +++ b/Src/NmeaACPParser.c @@ -0,0 +1,233 @@ +// +// Created by xemon on 01.09.22. +// +#include "NmeaACPParser.h" +#include "AsciiStringAssmeblingUtils.h" +#include "AsciiStringParsingUtils.h" +#include "time.h" +#include +//#include "printf.h" + +double specifAtCommand; + +//static char *strnstr(const char *haystack, const char *needle, size_t len) +//{ +// int i; +// size_t needle_len; +// +// if (0 == (needle_len = strnlen(needle, len))) +// return (char *)haystack; +// +// for (i=0; i<=(int)(len-needle_len); i++) +// { +// if ((haystack[0] == needle[0]) && +// (0 == strncmp(haystack, needle, needle_len))) +// return (char *)haystack; +// +// haystack++; +// } +// return NULL; +//} + +#define Nmea0183ParseShortCharsDecimalNumber(STR, LEN) (uint16_t) iAsciiStringParseUnsignedLongDecimalNumber(STR,((STR)+(LEN))) + +#define Nmea0183ParseDouble(STR, LEN) dAsciiStringParseDouble(STR,((STR)+(LEN))) + +#define Nmea0183SkipSpace(STR, STR_END) xAsciiStringSkipSpace(STR,STR_END) + +#define Nmea0183SkipToChar(STR, STR_END, SYMBOL) xAsciiStringSeekChar(STR,STR_END,SYMBOL) + +#define Nmea0183ParseNextPortion(BEGIN, DIV, STR_END) iAsciiStringMoveToNextParsingBlock(BEGIN,DIV,STR_END,',') + +#define Nmea0183ParseHexByte(STR) iAsciiStringParseHexByte(STR) + +bool NmeaACPParseTime(char *utcString, char const *utcStringEnd, tNmeaTimeAcp *time) { + + uint32_t len = utcStringEnd - utcString; + uint8_t charsLeft = len - 7; + + if (len > 10 || len < 9) { + return false; + } + + if (utcString[6] != '.') { + return false; + } + + time->hour = Nmea0183ParseShortCharsDecimalNumber(utcString + 0, 2); + time->minute = Nmea0183ParseShortCharsDecimalNumber(utcString + 2, 2); + time->second = Nmea0183ParseShortCharsDecimalNumber(utcString + 4, 2); + + time->millisecond = Nmea0183ParseShortCharsDecimalNumber(utcString + 7, charsLeft); + + charsLeft = 3 - charsLeft; + + while (charsLeft) { + time->millisecond *= 10; + --charsLeft; + } + + return true; +} + +bool NmeaACPParseDate(char *utcString, char const *utcStringEnd, tNmeaDateAcp *date) { + + uint32_t len = utcStringEnd - utcString; + + if (len != 6) { + return false; + } + + date->day = Nmea0183ParseShortCharsDecimalNumber(utcString + 0, 2); + date->month = Nmea0183ParseShortCharsDecimalNumber(utcString + 2, 2); + date->year = Nmea0183ParseShortCharsDecimalNumber(utcString + 4, 2); + + return true; +} + +uint8_t uNmeaACPChecksum(const char *str, size_t len) { + char *end = (char *) (str + len); + + unsigned char result; + result = 0; + str++; + + while ((str != end) && (*str != '*') && (*str != '\0')) + result ^= *str++; + + return result; +} + + +void vNmeaACPSign(char *str, size_t *strLen) { + uint8_t crc = uNmeaACPChecksum(str, *strLen); + vAsciiStringAddChar(str, strLen, '*'); + vAsciiStringAddByteAsHex(str, strLen, crc); +} + +bool bNmeaACPString(char *nmeaString, size_t len, tNmeaAcp *acp) { + if (nmeaString[0] != '$') { + return false; + } + return true; +} + +uint32_t iNmeaTimestampFromAcp(tNmeaAcp *env) { + struct tm time; + time.tm_hour = env->time.hour; + time.tm_min = env->time.minute; + time.tm_sec = env->time.second; + + time.tm_mday = env->date.day; + time.tm_mon = env->date.month - 1; + time.tm_year = (2000 - 1900) + env->date.year; + + return mktime(&time); +} + +bool bNmeaACPIsValidString(char *nmeaString, size_t len) { + if (specifAtCommand == 1) { + char *dataEndPos = strnstr((char *) nmeaString, "*", len); + uint8_t checksumCalculated = uNmeaACPChecksum(nmeaString, dataEndPos - nmeaString); + ++dataEndPos; + uint8_t checksumInString = Nmea0183ParseHexByte(dataEndPos); + return checksumCalculated == checksumInString; + } else { + return 1; + } +} + +bool bNmeaACPParse(char *rmcString, size_t len, tNmeaAcp *result) { + + rmcString = rmcString + 9; + len = len - 9; + + char *end = rmcString + len; + char *front = rmcString; + char *nextDivider = front - 1; + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + if (!NmeaACPParseTime(front, nextDivider, &result->time)) { + return false; + } + } else { + result->time.second = 0; + result->time.minute = 0; + result->time.hour = 0; + result->time.millisecond = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->location.latitude = Nmea0183ParseDouble(front, nextDivider - front); + result->location.nsIndicator = front[9]; + } else { + result->location.latitude = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->location.longitude = Nmea0183ParseDouble(front, nextDivider - front); + result->location.ewIndicator = front[10]; + } else { + result->location.longitude = 0; + } + + // снижение точности + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->location.horizontDiluitPrecis = Nmea0183ParseDouble(front, nextDivider - front); + } else { + result->location.horizontDiluitPrecis = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->location.altitude = Nmea0183ParseDouble(front, nextDivider - front); + } else { + result->location.altitude = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->status = Nmea0183ParseDouble(front, nextDivider - front); + if (result->status > 2) { + result->status = 'A'; + } else { + result->status = 'V'; + } + } else { + result->status = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->course = Nmea0183ParseDouble(front, nextDivider - front); + } else { + result->course = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->kmhVelocity = Nmea0183ParseDouble(front, nextDivider - front); + } else { + result->kmhVelocity = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->knotVelocity = Nmea0183ParseDouble(front, nextDivider - front); + } else { + result->knotVelocity = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + if (!NmeaACPParseDate(front, nextDivider, &result->date)) { + return false; + } + } else { + result->date.year = 0; + result->date.month = 0; + result->date.day = 0; + } + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + result->magnetic.nsat = *front; + } else { + result->magnetic.nsat = 0; + } + + return true; +} diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..71971cd --- /dev/null +++ b/modular.json @@ -0,0 +1,10 @@ +{ + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file