diff --git a/GPSACollector.cpp b/GPSACollector.cpp index fd539b8..df04ab0 100644 --- a/GPSACollector.cpp +++ b/GPSACollector.cpp @@ -45,7 +45,7 @@ bool CGPSACollector::isValidGPSA(const std::string& gpsa) if(gpsa.length() < 10U || !boost::starts_with(gpsa, "$$CRC")) return false; - auto csum = CAPRSUtils::calcIcomCRC(gpsa); + auto csum = CAPRSUtils::calcGPSAIcomCRC(gpsa); auto csumStr = CStringUtils::string_format("%04X", csum); auto expectedCsum = gpsa.substr(5U, APRS_CSUM_LENGTH); bool res = ::strcasecmp(csumStr.c_str(), expectedCsum.c_str()) == 0; diff --git a/RSMS1AMessageBuilder.cpp b/RSMS1AMessageBuilder.cpp new file mode 100644 index 0000000..53a91ef --- /dev/null +++ b/RSMS1AMessageBuilder.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "RSMS1AMessageBuilder.h" +#include "StringUtils.h" + +std::vector CRSMS1AMessageBuilder::m_charsToEscape = {-17, 0, 17, 19, -2, -25, 26, -3, -1, 36, 13, 44}; + +void CRSMS1AMessageBuilder::buildMessage(std::string& message, const std::string& sender, const std::string& recipient, const std::string body) +{ + + std::string bodyTmp(body); + auto bodyCrc = calculateBodyCRC(body); + bodyTmp.push_back(bodyCrc); + escapeBody(bodyTmp, std::string(bodyTmp)); + + std::string header = CStringUtils::string_format("%s,%s,0011", sender.c_str(), recipient.c_str()); + char c1, c2; + calcMsgIcomCRC(header, c1, c2); + header.push_back(c1); + header.push_back(c2); + message = "$$Msg," + header + bodyTmp + '\n'; +} + +char CRSMS1AMessageBuilder::calculateBodyCRC(const std::string& body) +{ + if(body.length() == 1) + return body[0]; + + int num = 0; + for(auto c : body) { + num += c; + } + + return (char)((num & 255) /*- 128*/); +} + +void CRSMS1AMessageBuilder::escapeBody(std::string output, const std::string& body) +{ + output.clear(); + for(char c : body) { + if(std::find(m_charsToEscape.begin(), m_charsToEscape.end(), c) != m_charsToEscape.end()) { + output.push_back(-17); + } + output.push_back(c); + } +} + +void CRSMS1AMessageBuilder::calcMsgIcomCRC(const std::string& msg, char& c1, char& c2) +{ + int num = 0; + for(unsigned int i = 0U; i < msg.length(); i++) { + num += msg[i]; + } + + c1 = doWhatever((char)((num >> 4) & 15)); + c2 = doWhatever((char)(num & 15)); +} + +char CRSMS1AMessageBuilder::doWhatever(char b2) { + int i; + int i2 = b2 & 255; + if (i2 >= 0 && i2 <= 9) { + i = b2 + 48; + } else if (10 > i2 || i2 > 15) { + return 0; + } else { + i = b2 + 55; + } + return (char) i; +} \ No newline at end of file diff --git a/RSMS1AMessageBuilder.h b/RSMS1AMessageBuilder.h new file mode 100644 index 0000000..d73f748 --- /dev/null +++ b/RSMS1AMessageBuilder.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#pragma once + +#include +#include + +class CRSMS1AMessageBuilder +{ +public: + static void buildMessage(std::string& message, const std::string& sender, const std::string& recipient, const std::string body); + +private: + static void calcMsgIcomCRC(const std::string& msg, char& c1, char& c2); + static void escapeBody(std::string output, const std::string& body); + static void escapeBytes(std::vector output, const std::vector input); + static char calculateBodyCRC(const std::string& body); + static char doWhatever(char b2); + + static std::vector m_charsToEscape; +}; \ No newline at end of file diff --git a/RSMS1AMessageCollector.cpp b/RSMS1AMessageCollector.cpp index f9cafe6..bb30923 100644 --- a/RSMS1AMessageCollector.cpp +++ b/RSMS1AMessageCollector.cpp @@ -57,6 +57,10 @@ bool CRSMS1AMessageCollector::isValidMsg(const std::string& msg) bool ret = splits.size() >= 4 && !splits[1].empty() && !splits[2].empty(); + + CUtils::dump("RS-MS1A:", (unsigned char *)msg.c_str(), msg.length() + 1U); + CLog::logDebug("RS-MS1A: %s", msg.c_str()); + return ret; //TODO 2022-01-01 figure out what the heck it is about thic strange CRCs diff --git a/Tests/RSMS1AMessageBuilder/buildMessage.cpp b/Tests/RSMS1AMessageBuilder/buildMessage.cpp new file mode 100644 index 0000000..8ed29ab --- /dev/null +++ b/Tests/RSMS1AMessageBuilder/buildMessage.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "../../RSMS1AMessageBuilder.h" + +namespace RSMS1AMessageBuilder +{ + + class RSMS1AMessageBuilder_buildMessage : public ::testing::Test { + + }; + + TEST_F(RSMS1AMessageBuilder_buildMessage, testABC) + { + std::string message; + CRSMS1AMessageBuilder::buildMessage(message, "KC3FRA", "F4FXL", "ABC"); + + EXPECT_STREQ(message.c_str(), "$$Msg,KC3FRA,F4FXL,001118ABCF\n"); + } + + TEST_F(RSMS1AMessageBuilder_buildMessage, testA) + { + std::string message; + CRSMS1AMessageBuilder::buildMessage(message, "KC3FRA", "F4FXL", "A"); + + EXPECT_STREQ(message.c_str(), "$$Msg,KC3FRA,F4FXL,001118AA\n"); + } + + TEST_F(RSMS1AMessageBuilder_buildMessage, testAA) + { + std::string message; + CRSMS1AMessageBuilder::buildMessage(message, "KC3FRA", "F4FXL", "AA"); + + EXPECT_STREQ(message.c_str(), "$$Msg,KC3FRA,F4FXL,001118AA\02\n"); + } + + TEST_F(RSMS1AMessageBuilder_buildMessage, testSalutCommentVasTu) + { + std::string message; + CRSMS1AMessageBuilder::buildMessage(message, "KC3FRA", "F4FXL", "Salut, comment vas tu?"); + + EXPECT_STREQ(message.c_str(), "$$Msg,KC3FRA,F4FXL,001118Saluto, comment vas tu?\x7A\n"); + } +}; \ No newline at end of file