commit
25a6aefe11
@ -0,0 +1,17 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/bin/g++",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++17",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"args": [
|
||||
"-j3"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Build Tests",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"args": [
|
||||
"-j3",
|
||||
"tests"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 "APRSFrame.h"
|
||||
|
||||
CAPRSFrame::CAPRSFrame() :
|
||||
m_source(),
|
||||
m_destination(),
|
||||
m_path(),
|
||||
m_type(APFT_UNKNOWN)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CAPRSFrame::CAPRSFrame(const std::string& source, const std::string& destination, const std::vector<std::string>& path, APRS_FRAME_TYPE type) :
|
||||
m_source(source),
|
||||
m_destination(destination),
|
||||
m_path(),
|
||||
m_type(type)
|
||||
{
|
||||
m_path.assign(path.begin(), path.end());
|
||||
}
|
||||
|
||||
void CAPRSFrame::clear()
|
||||
{
|
||||
m_source.clear();
|
||||
m_destination.clear();
|
||||
m_path.clear();
|
||||
m_body.clear();
|
||||
m_type = APFT_UNKNOWN;
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 <string>
|
||||
#include <vector>
|
||||
|
||||
// We only support these types for now
|
||||
enum APRS_FRAME_TYPE {
|
||||
APFT_UNKNOWN = 0,
|
||||
APFT_MESSAGE,
|
||||
};
|
||||
|
||||
class CAPRSFrame {
|
||||
public:
|
||||
CAPRSFrame();
|
||||
CAPRSFrame(const std::string& source, const std::string& destination, const std::vector<std::string>& path, APRS_FRAME_TYPE type);
|
||||
|
||||
void clear();
|
||||
std::string& getSource() { return m_source; }
|
||||
std::string& getDestination() { return m_destination; }
|
||||
std::vector<std::string>& getPath() { return m_path; }
|
||||
std::string& getBody() { return m_body; }
|
||||
APRS_FRAME_TYPE& getType() { return m_type; }
|
||||
|
||||
private:
|
||||
std::string m_source;
|
||||
std::string m_destination;
|
||||
std::vector<std::string> m_path;
|
||||
std::string m_body;
|
||||
APRS_FRAME_TYPE m_type;
|
||||
};
|
||||
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 "APRSParser.h"
|
||||
#include "Log.h"
|
||||
|
||||
bool CAPRSParser::parseFrame(const std::string& frameStr, CAPRSFrame& frame)
|
||||
{
|
||||
frame.clear();
|
||||
bool ret = false;
|
||||
|
||||
if(!frameStr.empty()) {
|
||||
auto pos = frameStr.find_first_of(':');
|
||||
if(pos != std::string::npos && pos != frameStr.length() - 1) {
|
||||
auto header = frameStr.substr(0, pos); // contains source, dest and path
|
||||
auto body = frameStr.substr(pos +1);
|
||||
|
||||
std::vector<std::string> headerSplits;
|
||||
boost::split(headerSplits, header, [](char c) { return c == ',' || c == '>';});
|
||||
|
||||
//we need at least source and dest to form a valid frame, also headers shall not contain empty strings
|
||||
if(headerSplits.size() >= 2 && std::none_of(headerSplits.begin(), headerSplits.end(), [](std::string s){ return s.empty(); })) {
|
||||
frame.getSource().assign(headerSplits[0]);
|
||||
frame.getDestination().assign(headerSplits[1]);
|
||||
|
||||
for(unsigned int i = 2; i < headerSplits.size(); i++) {
|
||||
frame.getPath().push_back(headerSplits[i]);
|
||||
}
|
||||
|
||||
frame.getBody().assign(body);
|
||||
|
||||
setFrameType(frame);
|
||||
if(frame.getType() == APFT_UNKNOWN) {
|
||||
CLog::logInfo("Invalid or unsupported APRS frame : %s", frameStr);
|
||||
}
|
||||
else {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CAPRSParser::setFrameType(CAPRSFrame& frame)
|
||||
{
|
||||
APRS_FRAME_TYPE type = APFT_UNKNOWN;
|
||||
std::string body(frame.getBody());
|
||||
|
||||
if(!body.empty()) {
|
||||
switch (body[0])
|
||||
{
|
||||
case ':':
|
||||
if(body[10] == ':' && std::all_of(body.begin() + 1, body.begin() + 10,
|
||||
[](char c){ return c == ' ' || c == '-' || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }))
|
||||
type = APFT_MESSAGE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frame.getType() = type;
|
||||
if(type == APFT_UNKNOWN)
|
||||
frame.clear();
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 <string>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "APRSFrame.h"
|
||||
|
||||
class CAPRSParser
|
||||
{
|
||||
public:
|
||||
static bool parseFrame(const std::string& frameStr, CAPRSFrame& frame);
|
||||
|
||||
private:
|
||||
static void setFrameType(CAPRSFrame& frame);
|
||||
};
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 "APRSReader.h"
|
||||
#include "APRSFrame.h"
|
||||
#include "APRSParser.h"
|
||||
|
||||
CAPRSReader::CAPRSReader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CAPRSReader::readAprsFrame(const std::string& aprsFrame)
|
||||
{
|
||||
auto bla = aprsFrame;
|
||||
return false;
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 "ReadAPRSFrameCallback.h"
|
||||
|
||||
class CAPRSReader : public CReadAPRSFrameCallback
|
||||
{
|
||||
public:
|
||||
CAPRSReader();
|
||||
bool readAprsFrame(const std::string& aprsFrame);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 <boost/algorithm/string.hpp>
|
||||
|
||||
#include "APRSUtils.h"
|
||||
|
||||
void CAPRSUtils::dstarCallsignToAPRS(std::string& dstarCallsign)
|
||||
{
|
||||
if(dstarCallsign[dstarCallsign.length() - 1] == ' ') {
|
||||
boost::trim(dstarCallsign);
|
||||
} else {
|
||||
//loop until got rid of all double blanks
|
||||
while(dstarCallsign.find(" ") != std::string::npos) {
|
||||
boost::replace_all(dstarCallsign, " ", " ");
|
||||
}
|
||||
boost::replace_all(dstarCallsign, " ", "-");//replace remaining blank with a -
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 <string>
|
||||
|
||||
class CAPRSUtils
|
||||
{
|
||||
public:
|
||||
static void dstarCallsignToAPRS(std::string& dstarCallsign);
|
||||
};
|
||||
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <cstring>
|
||||
#include <cassert>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "GPSACollector.h"
|
||||
#include "StringUtils.h"
|
||||
#include "Log.h"
|
||||
|
||||
const unsigned int APRS_CSUM_LENGTH = 4U;
|
||||
|
||||
CGPSACollector::CGPSACollector() :
|
||||
CSentenceCollector(SLOW_DATA_TYPE_GPS, "$$CRC", '\x0D')
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CGPSACollector::isValidSentence(const std::string& sentence)
|
||||
{
|
||||
return isValidGPSA(sentence);
|
||||
}
|
||||
|
||||
bool CGPSACollector::isValidGPSA(const std::string& gpsa)
|
||||
{
|
||||
if(gpsa.length() < 10U || !boost::starts_with(gpsa, "$$CRC"))
|
||||
return false;
|
||||
|
||||
auto csum = calcCRC(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;
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int CGPSACollector::calcCRC(const std::string& gpsa)
|
||||
{
|
||||
unsigned int icomcrc = 0xFFFFU;
|
||||
|
||||
auto length = gpsa.length();
|
||||
for (unsigned int j = 10U; j < length; j++) {
|
||||
unsigned char ch = (unsigned char)gpsa[j];
|
||||
|
||||
for (unsigned int i = 0U; i < 8U; i++) {
|
||||
bool xorflag = (((icomcrc ^ ch) & 0x01U) == 0x01U);
|
||||
|
||||
icomcrc >>= 1;
|
||||
|
||||
if (xorflag)
|
||||
icomcrc ^= 0x8408U;
|
||||
|
||||
ch >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ~icomcrc & 0xFFFFU;
|
||||
}
|
||||
|
||||
unsigned int CGPSACollector::getDataInt(unsigned char * data, unsigned int length)
|
||||
{
|
||||
if(data == nullptr || length == 0U || getSentence().empty())
|
||||
return 0U;
|
||||
|
||||
auto aprsFrame = getSentence();
|
||||
if(aprsFrame.length() < 11U)
|
||||
return 0U;
|
||||
|
||||
aprsFrame = aprsFrame.substr(10).append("\r\n");
|
||||
auto aprsFrameLen = aprsFrame.length();
|
||||
|
||||
if(length < aprsFrameLen) {
|
||||
CLog::logDebug("Not enough space to copy GPS-A APRS frame");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0U; i < aprsFrameLen; i++){
|
||||
data[i] = aprsFrame[i];
|
||||
}
|
||||
|
||||
return aprsFrameLen;
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <string>
|
||||
|
||||
#include "SentenceCollector.h"
|
||||
|
||||
class CGPSACollector : public CSentenceCollector
|
||||
{
|
||||
public:
|
||||
CGPSACollector();
|
||||
|
||||
protected:
|
||||
unsigned int getDataInt(unsigned char * data, unsigned int length);
|
||||
bool isValidSentence(const std::string& sentence);
|
||||
|
||||
private:
|
||||
static unsigned int calcCRC(const std::string& gpsa);
|
||||
static bool isValidGPSA(const std::string& gpsa);
|
||||
|
||||
std::string m_sentence;
|
||||
std::string m_collector;
|
||||
|
||||
};
|
||||
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <string.h>
|
||||
#include <cassert>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "NMEASentenceCollector.h"
|
||||
#include "StringUtils.h"
|
||||
#include "Log.h"
|
||||
#include "APRSUtils.h"
|
||||
|
||||
CNMEASentenceCollector::CNMEASentenceCollector(const std::string& sentence) :
|
||||
CSentenceCollector(SLOW_DATA_TYPE_GPS, sentence, '\x0A')
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CNMEASentenceCollector::isValidSentence(const std::string& sentence)
|
||||
{
|
||||
return isValidNMEA(sentence);
|
||||
}
|
||||
|
||||
bool CNMEASentenceCollector::isValidNMEA(const std::string& nmea)
|
||||
{
|
||||
if(nmea.empty() || nmea[0] != '$')
|
||||
return false;
|
||||
|
||||
auto posStar = nmea.find_last_of('*');
|
||||
if(posStar == 0U || posStar == std::string::npos)
|
||||
return false;
|
||||
|
||||
auto csum = calcXOR(nmea);
|
||||
auto csumStr = CStringUtils::string_format("%02X", csum);
|
||||
auto expctedCSumStr = nmea.substr(posStar + 1, 2U);
|
||||
auto res = ::strcasecmp(expctedCSumStr.c_str(), csumStr.c_str()) == 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned char CNMEASentenceCollector::calcXOR(const std::string& nmea)
|
||||
{
|
||||
unsigned char res = 0U;
|
||||
|
||||
if(!nmea.empty()) {
|
||||
unsigned int i = nmea[0] == '$' ? 1U : 0U; //skip $ it it is there
|
||||
while(i < nmea.length())
|
||||
{
|
||||
if(nmea[i] != '*') {
|
||||
res ^= (unsigned char)nmea[i];
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int CNMEASentenceCollector::getDataInt(unsigned char * data, unsigned int length)
|
||||
{
|
||||
if(data == nullptr || length == 0U || getMyCall().empty() || getSentence().empty())
|
||||
return 0U;
|
||||
|
||||
auto nmea = getSentence();
|
||||
fixUpNMEATimeStamp(nmea);
|
||||
|
||||
std::string fromCall = getMyCall();
|
||||
CAPRSUtils::dstarCallsignToAPRS(fromCall);
|
||||
std::string aprsFrame(fromCall);
|
||||
aprsFrame.append("-5>GPS30,DSTAR*:")
|
||||
.append(nmea)
|
||||
.append("\r\n");
|
||||
|
||||
auto aprsFrameLen = aprsFrame.length();
|
||||
if(length < aprsFrameLen) {
|
||||
CLog::logDebug("Not enough space to copy NMEA APRS frame");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0U; i < aprsFrameLen; i++){
|
||||
data[i] = aprsFrame[i];
|
||||
}
|
||||
|
||||
return aprsFrameLen;
|
||||
}
|
||||
|
||||
// When set on manual position Icom radios send 000000.00 as NMEA timestamps
|
||||
// this is a dirty hack to correct this issue. Actually I am not sure about APRS
|
||||
// software being peeky about this except APRS.fi
|
||||
void CNMEASentenceCollector::fixUpNMEATimeStamp(std::string& nmea)
|
||||
{
|
||||
auto posStar = nmea.find_last_of('*');
|
||||
if(posStar != std::string::npos)
|
||||
nmea = nmea.substr(0, posStar);
|
||||
|
||||
time_t now;
|
||||
::time(&now);
|
||||
struct tm* tm = ::gmtime(&now);
|
||||
auto timeStamp = CStringUtils::string_format(",%02d%02d%02d.00,", tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
boost::replace_all(nmea, ",000000.00,", timeStamp);
|
||||
//recalculate checksum
|
||||
nmea = CStringUtils::string_format("%s*%02x", nmea.c_str(), calcXOR(nmea));
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <string>
|
||||
|
||||
#include "SentenceCollector.h"
|
||||
|
||||
class CNMEASentenceCollector : public CSentenceCollector
|
||||
{
|
||||
public:
|
||||
CNMEASentenceCollector(const std::string& sentence);
|
||||
|
||||
protected:
|
||||
unsigned int getDataInt(unsigned char * data, unsigned int length);
|
||||
bool isValidSentence(const std::string& sentence);
|
||||
|
||||
private:
|
||||
static void dstarCallsignToAPRS(std::string& call);
|
||||
static bool isValidNMEA(const std::string& nmea);
|
||||
static unsigned char calcXOR(const std::string& nmea);
|
||||
static void fixUpNMEATimeStamp(std::string& nmea);
|
||||
};
|
||||
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <cstring>
|
||||
#include <cassert>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "RSMS1AMessageCollector.h"
|
||||
#include "StringUtils.h"
|
||||
#include "Log.h"
|
||||
#include "Utils.h"
|
||||
#include "APRSUtils.h"
|
||||
|
||||
|
||||
const unsigned int APRS_CSUM_LENGTH = 4U;
|
||||
|
||||
CRSMS1AMessageCollector::CRSMS1AMessageCollector() :
|
||||
CSentenceCollector(SLOW_DATA_TYPE_GPS, "$$Msg", '\x0D')
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CRSMS1AMessageCollector::isValidSentence(const std::string& sentence)
|
||||
{
|
||||
return isValidMsg(sentence);
|
||||
}
|
||||
|
||||
bool CRSMS1AMessageCollector::isValidMsg(const std::string& msg)
|
||||
{
|
||||
if(msg.empty() || !boost::starts_with(msg, "$$Msg"))
|
||||
return false;
|
||||
|
||||
// CUtils::dump("RS-MS1A:", (unsigned char *)msg.c_str(), msg.length());
|
||||
std::vector<std::string> splits;
|
||||
boost::split(splits, msg, boost::is_any_of(","));
|
||||
|
||||
bool ret = splits.size() >= 4
|
||||
&& !splits[1].empty()
|
||||
&& !splits[2].empty();
|
||||
return ret;
|
||||
|
||||
//TODO 2022-01-01 figure out what the heck it is about thic strange CRCs
|
||||
|
||||
// CUtils::dump("RS-MS1A:", (unsigned char *)gpsa.c_str(), gpsa.length() + 1U);
|
||||
// CLog::logDebug("RS-MS1A: %s", gpsa.c_str());
|
||||
|
||||
// auto thirdCommaPos = CStringUtils::find_nth(gpsa, 0U, ',', 3);
|
||||
// auto csum = calcCRC(gpsa, thirdCommaPos + 6 + 1, gpsa.length() - thirdCommaPos - 2U - 6U);
|
||||
// auto csumStr = CStringUtils::string_format("%06X", csum);
|
||||
// CLog::logDebug("RS-MS1A CRC: %s", csumStr.c_str());
|
||||
|
||||
// auto expectedCsum = gpsa.substr(5U, APRS_CSUM_LENGTH);
|
||||
// bool res = ::strcasecmp(csumStr.c_str(), expectedCsum.c_str()) == 0;
|
||||
// return res;
|
||||
}
|
||||
|
||||
unsigned int CRSMS1AMessageCollector::calcCRC(const std::string& gpsa, unsigned int start, unsigned int length)
|
||||
{
|
||||
unsigned int icomcrc = 0xFFFFU;
|
||||
auto end = start + length;
|
||||
if(end > gpsa.length()) {
|
||||
end = gpsa.length();
|
||||
}
|
||||
|
||||
for (unsigned int j = start; j < end; j++) {
|
||||
unsigned char ch = (unsigned char)gpsa[j];
|
||||
|
||||
for (unsigned int i = 0U; i < 8U; i++) {
|
||||
bool xorflag = (((icomcrc ^ ch) & 0x01U) == 0x01U);
|
||||
|
||||
icomcrc >>= 1;
|
||||
|
||||
if (xorflag)
|
||||
icomcrc ^= 0x8408U;
|
||||
|
||||
ch >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ~icomcrc & 0xFFFFU;
|
||||
}
|
||||
|
||||
unsigned int CRSMS1AMessageCollector::getDataInt(unsigned char * data, unsigned int length)
|
||||
{
|
||||
if(data == nullptr || length == 0U || getSentence().empty())
|
||||
return 0U;
|
||||
|
||||
auto sentence = getSentence();
|
||||
|
||||
std::vector<std::string> splits;
|
||||
boost::split(splits, sentence, boost::is_any_of(","));
|
||||
|
||||
bool ret = splits.size() >= 4
|
||||
&& !splits[1].empty()
|
||||
&& !splits[2].empty();
|
||||
if(!ret) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
auto sender = splits[1];
|
||||
auto recipient = CUtils::ToUpper(splits[2]);
|
||||
|
||||
for(unsigned int i = 0;i < 3; i++) {
|
||||
splits.erase(splits.begin());
|
||||
}
|
||||
|
||||
auto message = boost::join(splits, ",");
|
||||
if(message.length() > 6)
|
||||
message = message.substr(6);
|
||||
|
||||
auto seqNum = rand() % 0xFFFFFU;
|
||||
|
||||
CAPRSUtils::dstarCallsignToAPRS(sender);
|
||||
CAPRSUtils::dstarCallsignToAPRS(recipient);
|
||||
recipient.resize(9, ' ');
|
||||
message.resize(std::max<int>(0 , ((int)message.length()) - 2));
|
||||
|
||||
//unescape commas in message body
|
||||
boost::replace_all(message, "o,", ",");
|
||||
|
||||
auto aprsFrame = CStringUtils::string_format("%s-5>APDPRS,DSTAR*::%s:%s{%05X\r\n", sender.c_str(), recipient.c_str(), message.c_str(), seqNum);
|
||||
|
||||
auto aprsFrameLen = aprsFrame.length();
|
||||
|
||||
if(length < aprsFrameLen) {
|
||||
CLog::logDebug("Not enough space to copy GPS-A APRS frame");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0U; i < aprsFrameLen; i++){
|
||||
data[i] = aprsFrame[i];
|
||||
}
|
||||
|
||||
return aprsFrameLen;
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <string>
|
||||
|
||||
#include "SentenceCollector.h"
|
||||
|
||||
class CRSMS1AMessageCollector : public CSentenceCollector
|
||||
{
|
||||
public:
|
||||
CRSMS1AMessageCollector();
|
||||
|
||||
protected:
|
||||
unsigned int getDataInt(unsigned char * data, unsigned int length);
|
||||
bool isValidSentence(const std::string& sentence);
|
||||
|
||||
private:
|
||||
static unsigned int calcCRC(const std::string& gpsa, unsigned int start, unsigned int length);
|
||||
static bool isValidMsg(const std::string& gpsa);
|
||||
|
||||
std::string m_sentence;
|
||||
std::string m_collector;
|
||||
};
|
||||
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 <string>
|
||||
|
||||
class CReadAPRSFrameCallback
|
||||
{
|
||||
public:
|
||||
virtual ~CReadAPRSFrameCallback(){ }
|
||||
virtual bool readAprsFrame(const std::string& aprsFrame) = 0;
|
||||
};
|
||||
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <cassert>
|
||||
|
||||
#include "SentenceCollector.h"
|
||||
|
||||
CSentenceCollector::CSentenceCollector(unsigned char slowDataType, const std::string& sentenceIdentifier, unsigned char endMarker) :
|
||||
CSlowDataCollector(slowDataType),
|
||||
m_collector(),
|
||||
m_sentenceIdentifier(sentenceIdentifier),
|
||||
m_sentence(),
|
||||
m_endMarker(endMarker)
|
||||
{
|
||||
assert(!sentenceIdentifier.empty());
|
||||
}
|
||||
|
||||
bool CSentenceCollector::addData(const unsigned char * data)
|
||||
{
|
||||
m_collector.append(std::string((char*)data, 5U));
|
||||
|
||||
std::string::size_type n2 = m_collector.find_last_of(m_endMarker);
|
||||
if (n2 == std::string::npos)
|
||||
return false;
|
||||
|
||||
std::string::size_type n1 = m_collector.find(m_sentenceIdentifier);
|
||||
if (n1 == std::string::npos)
|
||||
return false;
|
||||
|
||||
if(n2 < n1)
|
||||
return false;
|
||||
|
||||
std::string sentence;
|
||||
for(unsigned int i = n1; i <= n2; i++) {
|
||||
sentence.push_back(m_collector[i] & 0x7FU);
|
||||
}
|
||||
|
||||
bool ret = isValidSentence(sentence);
|
||||
if(ret) {
|
||||
m_sentence = sentence;
|
||||
} else {
|
||||
m_sentence.clear();
|
||||
}
|
||||
|
||||
m_collector = m_collector.substr(n2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string CSentenceCollector::getSentence()
|
||||
{
|
||||
return m_sentence;
|
||||
}
|
||||
|
||||
void CSentenceCollector::resetInt()
|
||||
{
|
||||
m_collector.clear();
|
||||
m_sentence.clear();
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <string>
|
||||
|
||||
#include "SlowDataCollector.h"
|
||||
|
||||
class CSentenceCollector : public CSlowDataCollector
|
||||
{
|
||||
public:
|
||||
CSentenceCollector(unsigned char slowDataType, const std::string& sentenceIdentifier, unsigned char endMarker);
|
||||
|
||||
protected:
|
||||
bool addData(const unsigned char * data);
|
||||
|
||||
virtual unsigned int getDataInt(unsigned char * data, unsigned int length) = 0;
|
||||
static void dstarCallsignToAPRS(std::string& call);
|
||||
std::string getSentence();
|
||||
|
||||
private:
|
||||
virtual bool isValidSentence(const std::string& sentence) = 0;
|
||||
virtual void resetInt();
|
||||
|
||||
std::string m_collector;
|
||||
std::string m_sentenceIdentifier;
|
||||
std::string m_sentence;
|
||||
unsigned char m_endMarker;
|
||||
};
|
||||
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "SlowDataCollector.h"
|
||||
#include "Log.h"
|
||||
|
||||
const unsigned int SLOW_DATA_BLOCK_LENGTH = 6U;
|
||||
|
||||
CSlowDataCollector::CSlowDataCollector(unsigned char slowDataType) :
|
||||
m_slowDataType(slowDataType),
|
||||
m_myCall(),
|
||||
m_state(SS_FIRST)
|
||||
{
|
||||
m_buffer = new unsigned char[SLOW_DATA_BLOCK_LENGTH];
|
||||
std::memset(m_buffer, 0, SLOW_DATA_BLOCK_LENGTH);
|
||||
}
|
||||
|
||||
CSlowDataCollector::~CSlowDataCollector()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
std::string CSlowDataCollector::getMyCall() const
|
||||
{
|
||||
return m_myCall;
|
||||
}
|
||||
|
||||
void CSlowDataCollector::setMyCall(const std::string& myCall)
|
||||
{
|
||||
m_myCall = myCall;
|
||||
}
|
||||
|
||||
bool CSlowDataCollector::writeData(const unsigned char* data)
|
||||
{
|
||||
assert(data != nullptr);
|
||||
|
||||
switch (m_state) {
|
||||
case SS_FIRST:
|
||||
m_buffer[0U] = data[0U] ^ SCRAMBLER_BYTE1;
|
||||
m_buffer[1U] = data[1U] ^ SCRAMBLER_BYTE2;
|
||||
m_buffer[2U] = data[2U] ^ SCRAMBLER_BYTE3;
|
||||
m_state = SS_SECOND;
|
||||
return false;
|
||||
|
||||
case SS_SECOND:
|
||||
m_buffer[3U] = data[0U] ^ SCRAMBLER_BYTE1;
|
||||
m_buffer[4U] = data[1U] ^ SCRAMBLER_BYTE2;
|
||||
m_buffer[5U] = data[2U] ^ SCRAMBLER_BYTE3;
|
||||
m_state = SS_FIRST;
|
||||
break;
|
||||
}
|
||||
|
||||
// unsigned char rxDataType = (m_buffer[0] & SLOW_DATA_TYPE_MASK);
|
||||
|
||||
// switch (rxDataType)
|
||||
// {
|
||||
// case SLOW_DATA_TYPE_MASK: CLog::logDebug("SLOW_DATA_TYPE_MASK "); break;
|
||||
// case SLOW_DATA_TYPE_GPS: CLog::logDebug("SLOW_DATA_TYPE_GPS "); break;
|
||||
// case SLOW_DATA_TYPE_TEXT: CLog::logDebug("SLOW_DATA_TYPE_TEXT "); break;
|
||||
// case SLOW_DATA_TYPE_HEADER: CLog::logDebug("SLOW_DATA_TYPE_HEADER "); break;
|
||||
// case SLOW_DATA_TYPE_MESSAGE: CLog::logDebug("SLOW_DATA_TYPE_MESSAGE "); break;
|
||||
// case SLOW_DATA_TYPE_FAST_DATA1: CLog::logDebug("SLOW_DATA_TYPE_FAST_DATA1 "); break;
|
||||
// case SLOW_DATA_TYPE_FAST_DATA2: CLog::logDebug("SLOW_DATA_TYPE_FAST_DATA2 "); break;
|
||||
// case SLOW_DATA_TYPE_SQUELCH: CLog::logDebug("SLOW_DATA_TYPE_SQUELCH "); break;
|
||||
// case SLOW_DATA_LENGTH_MASK: CLog::logDebug("SLOW_DATA_LENGTH_MASK "); break;
|
||||
// default:
|
||||
// CLog::logDebug("!!!!!!!!!!!!!!! %X", rxDataType);
|
||||
// break;
|
||||
// };
|
||||
|
||||
if((m_buffer[0] & SLOW_DATA_TYPE_MASK) == m_slowDataType)
|
||||
return addData(m_buffer + 1U);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSlowDataCollector::sync()
|
||||
{
|
||||
m_state = SS_FIRST;
|
||||
}
|
||||
|
||||
unsigned int CSlowDataCollector::getData(unsigned char * data, unsigned int length)
|
||||
{
|
||||
return getDataInt(data, length);
|
||||
}
|
||||
|
||||
void CSlowDataCollector::reset()
|
||||
{
|
||||
m_state = SS_FIRST;
|
||||
m_myCall.clear();
|
||||
resetInt();
|
||||
}
|
||||
|
||||
unsigned char CSlowDataCollector::getDataType()
|
||||
{
|
||||
return m_slowDataType;
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2010,2012,2018 by Jonathan Naylor G4KLX
|
||||
* 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 <string>
|
||||
|
||||
#include "DStarDefines.h"
|
||||
#include "Defs.h"
|
||||
|
||||
class CSlowDataCollector
|
||||
{
|
||||
public:
|
||||
CSlowDataCollector(unsigned char slowDataType);
|
||||
virtual ~CSlowDataCollector();
|
||||
|
||||
std::string getMyCall() const;
|
||||
void setMyCall(const std::string& mycall);
|
||||
bool writeData(const unsigned char* data);
|
||||
void sync();
|
||||
unsigned int getData(unsigned char* data, unsigned int length);
|
||||
void reset();
|
||||
unsigned char getDataType();
|
||||
|
||||
protected:
|
||||
virtual bool addData(const unsigned char* data) = 0;
|
||||
virtual unsigned int getDataInt(unsigned char* data, unsigned int length) = 0;
|
||||
virtual void resetInt() { }
|
||||
|
||||
private:
|
||||
unsigned char m_slowDataType;
|
||||
std::string m_myCall;
|
||||
SLOWDATA_STATE m_state;
|
||||
unsigned char * m_buffer;
|
||||
};
|
||||
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "StringUtils.h"
|
||||
|
||||
size_t CStringUtils::find_nth(const std::string& haystack, char needle, size_t nth)
|
||||
{
|
||||
size_t matches = 0U;
|
||||
auto haystackLength = haystack.length();
|
||||
|
||||
for(size_t i = 0; i < haystackLength; i++) {
|
||||
if(haystack[i] == needle) {
|
||||
matches++;
|
||||
if(matches == nth)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return std::string::npos;
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
|
||||
#include "../../APRSParser.h"
|
||||
|
||||
class APRSParser_parseAPRSFrame : public ::testing::Test {
|
||||
|
||||
};
|
||||
|
||||
TEST_F(APRSParser_parseAPRSFrame, EmpyString) {
|
||||
|
||||
CAPRSFrame aprsFrame;
|
||||
bool retVal = CAPRSParser::parseFrame("", aprsFrame);
|
||||
|
||||
EXPECT_FALSE(retVal);
|
||||
EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "");
|
||||
EXPECT_EQ(aprsFrame.getType(), APFT_UNKNOWN);
|
||||
EXPECT_EQ(aprsFrame.getPath().size(), 0U);
|
||||
}
|
||||
|
||||
TEST_F(APRSParser_parseAPRSFrame, NoSourceCallsign) {
|
||||
|
||||
CAPRSFrame aprsFrame;
|
||||
bool retVal = CAPRSParser::parseFrame(">APRS::F4ABC Test Message", aprsFrame);
|
||||
|
||||
EXPECT_FALSE(retVal);
|
||||
EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "");
|
||||
EXPECT_EQ(aprsFrame.getType(), APFT_UNKNOWN);
|
||||
EXPECT_EQ(aprsFrame.getPath().size(), 0U);
|
||||
}
|
||||
|
||||
TEST_F(APRSParser_parseAPRSFrame, NoDestCallsign) {
|
||||
|
||||
CAPRSFrame aprsFrame;
|
||||
bool retVal = CAPRSParser::parseFrame("N0CALL>::F4ABC Test Message", aprsFrame);
|
||||
|
||||
EXPECT_FALSE(retVal);
|
||||
EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "");
|
||||
EXPECT_EQ(aprsFrame.getType(), APFT_UNKNOWN);
|
||||
EXPECT_EQ(aprsFrame.getPath().size(), 0U);
|
||||
}
|
||||
|
||||
TEST_F(APRSParser_parseAPRSFrame, CorrectMessageFrameWithDigipeater) {
|
||||
|
||||
CAPRSFrame aprsFrame;
|
||||
bool retVal = CAPRSParser::parseFrame("N0CALL>APRS,WIDE1-1,WIDE2-2::F4ABC :Test Message", aprsFrame);
|
||||
|
||||
EXPECT_TRUE(retVal);
|
||||
EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), ":F4ABC :Test Message");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "APRS");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "N0CALL");
|
||||
EXPECT_EQ(aprsFrame.getType(), APFT_MESSAGE);
|
||||
EXPECT_EQ(aprsFrame.getPath().size(), 2);
|
||||
EXPECT_STREQ(aprsFrame.getPath()[0].c_str(), "WIDE1-1");
|
||||
EXPECT_STREQ(aprsFrame.getPath()[1].c_str(), "WIDE2-2");
|
||||
}
|
||||
|
||||
TEST_F(APRSParser_parseAPRSFrame, CorrectMessageFrameWithoutDigipeater) {
|
||||
|
||||
CAPRSFrame aprsFrame;
|
||||
bool retVal = CAPRSParser::parseFrame("N0CALL>APRS::F4ABC :Test Message", aprsFrame);
|
||||
|
||||
EXPECT_TRUE(retVal);
|
||||
EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), ":F4ABC :Test Message");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "APRS");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "N0CALL");
|
||||
EXPECT_EQ(aprsFrame.getType(), APFT_MESSAGE);
|
||||
EXPECT_EQ(aprsFrame.getPath().size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(APRSParser_parseAPRSFrame, InvalideMessageFrame) {
|
||||
|
||||
CAPRSFrame aprsFrame;
|
||||
bool retVal = CAPRSParser::parseFrame("N0CALL>APRS::F4ABC&@#$:Test Message", aprsFrame);
|
||||
|
||||
EXPECT_FALSE(retVal);
|
||||
EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "");
|
||||
EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "");
|
||||
EXPECT_EQ(aprsFrame.getType(), APFT_UNKNOWN);
|
||||
EXPECT_EQ(aprsFrame.getPath().size(), 0U);
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
|
||||
SRCS = $(wildcard *.cpp) $(wildcard ../*.cpp) $(wildcard */*.cpp)
|
||||
OBJS = $(SRCS:.cpp=.o)
|
||||
DEPS = $(SRCS:.cpp=.d)
|
||||
|
||||
dstargateway_tests: $(OBJS)
|
||||
$(CC) $(CPPFLAGS) -o dstargateway_tests $(OBJS) $(LDFLAGS) -lgtest -lgtest_main
|
||||
|
||||
%.o : %.cpp
|
||||
$(CC) $(CPPFLAGS) -DUNIT_TESTS -I../ -MMD -MD -c $< -o $@
|
||||
|
||||
-include $(DEPS)
|
||||
|
||||
.PHONY run-tests: dstargateway_tests
|
||||
./dstargateway_tests
|
||||
|
||||
.PHONY clean :
|
||||
clean :
|
||||
@$(RM) $(OBJS) $(DEPS) dstargateway_tests
|
||||
Loading…
Reference in new issue