diff --git a/Location.cpp b/Location.cpp new file mode 100644 index 0000000..50aee31 --- /dev/null +++ b/Location.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2020 by Thomas Early N7TAE + * + * 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 +#include +#include + +#include "Utilities.h" +#include "Location.h" + +CLocation::CLocation() +{ + crc = std::regex("^.*([0-9]{2})([0-9]{2}\\.[0-9]{2,})([NS])/([0-9]{3})([0-9]{2}\\.[0-9]{1,})([WE])\\[.*$", std::regex::extended); + rmc = std::regex("^.*,([0-9]{2})([0-9]{2}\\.[0-9]{2,}),([NS]),([0-9]{3})([0-9]{2}\\.[0-9]{1,}),([WE]),.*$", std::regex::extended); +} + +// returns true on success +bool CLocation::Parse(const char *instr) +{ + std::string s(instr); + std::cmatch cm; + trim(s); + + if (0 == s.find("$$CRC")) { + std::regex_match(s.c_str(), cm, crc, std::regex_constants::match_default); + } else if ((0 == s.find("$GPGGA")) || (0 == s.find("$GPRMC"))) { + std::regex_match(s.c_str(), cm, rmc, std::regex_constants::match_default); + } else { + if ('$' == s.at(0)) + std::cerr << "can't parse GPS string: " << s << std::endl; + return false; + } + + auto size = cm.size(); + if (size != 7) { + std::cerr << "Bad CRC Match for " << s << ":"; + for (unsigned i=0; i= 0 && mod < 3 && Rptr.mod[mod].defined) { + unsigned char call[CALL_SIZE]; + memcpy(call, sdheader.hdr.rpt1, CALL_SIZE); + memcpy(sdheader.hdr.rpt2, sdheader.hdr.rpt1, CALL_SIZE); + memcpy(sdheader.hdr.rpt1, call, CALL_SIZE); + calcPFCS(sdheader.title, 56); + ToModem[mod].Write(sdheader.title, 56); + toRptr[mod].streamid = sdheader.streamid; + toRptr[mod].addr = fromDstar; + toRptr[mod].sequence = sdheader.ctrl; + time(&toRptr[mod].last_time); + if (LOG_QSO) + printf("SD Header: id=0x%04x flags=%x:%x:%x r1=%8.8s r2=%8.8s ur=%8.8s my=%8.8s nm=%4.4s\n", htons(sdheader.streamid), sdheader.hdr.flag[0], sdheader.hdr.flag[1], sdheader.hdr.flag[2], sdheader.hdr.rpt1, sdheader.hdr.rpt2, sdheader.hdr.urcall, sdheader.hdr.mycall, sdheader.hdr.sfx); + sd.ih = sd.size = 0; + } else { + fprintf(stderr, "Got a valid slow data header but module %d doesn't exist\n", mod); + } + } + } + } else { + //printf("Header overflow, message has %d bytes, trying to add %d more\n", sd.ih, sd.size); sd.ih = sd.size = 0; } - } else { - //printf("Header overflow, message has %d bytes, trying to add %d more\n", sd.ih, sd.size); - sd.ih = sd.size = 0; } sd.first = false; break; @@ -1063,7 +1090,14 @@ void CQnetGateway::ProcessIncomingSD(const SDSVT &dsvt) sd.gps[sd.ig+1] = '\0'; else sd.gps[sd.ig+2] = '\0'; - printf("GPS[%d] string='%s'\n", i, sd.gps); + if (i < 3) { + if (showLastHeard && gps.Parse((const char *)&sd.ig)) { + char call[CALL_SIZE+1]; + memcpy(call, toRptr[i].saved_hdr.hdr.mycall, CALL_SIZE); + call[CALL_SIZE] = '\0'; + qnDB.UpdatePosition(call, gps.MaidenHead(), gps.Longitude(), gps.Longitude()); + } + } sd.ig = 0; } else { sd.ig += sd.size; @@ -1075,12 +1109,17 @@ void CQnetGateway::ProcessIncomingSD(const SDSVT &dsvt) sd.im += 3; if (sd.im >= 20) { sd.message[20] = '\0'; - printf("Message[%d]='%s'\n", i, sd.message); + if (showLastHeard && (i < 3)) { + char call[CALL_SIZE+1]; + memcpy(call, toRptr[i].saved_hdr.hdr.mycall, CALL_SIZE); + call[CALL_SIZE] = '\0'; + qnDB.UpdateMessage(call, (const char *)&(sd.message)); + } sd.im = 0; } break; case 0x50U: // header - if (sd.size) { + if ((3 == i) && sd.size) { memcpy(sd.header+sd.ih, c, 3); sd.ih += 3; } @@ -2594,6 +2633,15 @@ bool CQnetGateway::Init(char *cfgfile) memcpy(end_of_audio.title, "DSVT", 4U); end_of_audio.id = end_of_audio.config = 0x20U; + // and the slow data header + memcpy(sdheader.title, "DSVT", 4); + sdheader.config = 0x10; + memset(sdheader.flaga, 0, 3); + sdheader.id = 0x10U; + sdheader.flagb[0] = 0; + sdheader.flagb[1] = sdheader.flagb[2] = 0x1U; + sdheader.ctrl = 0x80; + /* to remote systems */ for (i = 0; i < 3; i++) { to_remote_g2[i].toDstar.Clear(); diff --git a/QnetGateway.h b/QnetGateway.h index 829967a..7a36dbe 100644 --- a/QnetGateway.h +++ b/QnetGateway.h @@ -29,6 +29,7 @@ #include "QnetDB.h" #include "DStarDecode.h" #include "KRBase.h" +#include "Location.h" #define MAXHOSTNAMELEN 64 #define CALL_SIZE 8 @@ -160,6 +161,8 @@ private: CIRCDDB *ii[2]; // for handling APRS stuff CAPRS *aprs; + // for parsign GPS slow data + CLocation gps; // text coming from local repeater bands SBANDTXT band_txt[3]; // 0=A, 1=B, 2=C