// // Created by villuton on 20.03.25. // #include #include #include "Nmea0183Parser_General.h" #include "Nmea0183Parser_Private.h" #define Nmea0183ParserEndDataPos(STR,LEN) strnstr((char *) STR, "*", LEN) /** * Calculates the checksum of an NMEA 0183 XOR string of all bytes in the string * @param str * @param len * @return XOR checksum */ uint8_t uNmea0183CheckSum(const char *str, size_t len) { char *end = (char *) (str + len); unsigned char result; result = 0; while (str != end) result ^= *str++; return result; } /** * Checking string validity NMEA 0183 * @param str * @param len * @return Checksum comparison result */ bool bNmea0183IsValidString(char *str, size_t len) { char *end = str + len; char *front = str; char *nextDivider = front - 1; char *dataStartPos = Nmea0183SkipToStartDelimiter(front,end); char *dataEndPos = Nmea0183SkipToStartCheckSumDelimiter(front,end); uint8_t checksumCalculated = uNmea0183CheckSum(dataStartPos, dataEndPos - dataStartPos); if(Nmea0183ParseCheckSumPosition(&front,&nextDivider,end) > 0){ uint8_t checksumInString = Nmea0183ParseHexByte(nextDivider); return checksumCalculated == checksumInString; } return false; } #define NMEA_HourStrLen 2 #define NMEA_MinuteStrLen 2 #define NMEA_SecondStrLen 2 #define NMEA_HourStrOffset 0 #define NMEA_MinuteStrOffset (NMEA_HourStrOffset + NMEA_HourStrLen) #define NMEA_SecondStrOffset (NMEA_MinuteStrOffset + NMEA_MinuteStrLen) #define NMEA_UTC_PointStrOffset 1 #define NMEA_DecimalSecondStrOffset (NMEA_SecondStrOffset + NMEA_SecondStrLen + NMEA_UTC_PointStrOffset) bool Nmea0183ParseTime(char *utcString, char const *utcStringEnd, tNmeaTime *time) { uint32_t len = utcStringEnd - utcString; uint8_t decimalPortion = len - NMEA_HourStrLen+NMEA_MinuteStrLen+NMEA_SecondStrLen+NMEA_UTC_PointStrOffset; if (len > 10 || len < 9) { return false; } if (utcString[6] != '.') { return false; } time->hour = Nmea0183ParseShortCharsDecimalNumber(utcString + NMEA_HourStrOffset, NMEA_HourStrLen); time->minute = Nmea0183ParseShortCharsDecimalNumber(utcString + NMEA_MinuteStrOffset, NMEA_MinuteStrLen); time->second = Nmea0183ParseShortCharsDecimalNumber(utcString + NMEA_SecondStrOffset, NMEA_SecondStrLen); time->millisecond = Nmea0183ParseShortCharsDecimalNumber(utcString + NMEA_DecimalSecondStrOffset, decimalPortion); while (decimalPortion) { time->millisecond *= 10; --decimalPortion; } return true; } bool Nmea0183ParseDate(char *utcString, char const *utcStringEnd, tNmeaDate *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; }