From f834c505ca3608e1d05e2835d2cb3ee4693cb086 Mon Sep 17 00:00:00 2001 From: Cort Buffington Date: Mon, 9 Jan 2023 07:21:57 -0600 Subject: [PATCH 01/29] Adding high speed UART support for Armbian + AllWinnder H2/H3 SBCs (ie. NanoPi NEO, OrangePi Zero, etc.) --- UARTController.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/UARTController.cpp b/UARTController.cpp index 27aeed2..0d636d8 100644 --- a/UARTController.cpp +++ b/UARTController.cpp @@ -357,6 +357,12 @@ bool CUARTController::setRaw() ::cfsetispeed(&termios, B460800); break; #endif /*B460800*/ +#if defined(B500000) + case 500000U: + ::cfsetospeed(&termios, B500000); + ::cfsetispeed(&termios, B500000); + break; +#endif /*B500000*/ default: LogError("Unsupported serial port speed - %u", m_speed); ::close(m_fd); From f75ad66a3388584d35f02deb73149616ef9de57e Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 11 Jan 2023 19:35:23 +0000 Subject: [PATCH 02/29] Handle the case where the D-Star RF timeout timer is not stopped at the end of a transmission. --- DStarControl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DStarControl.cpp b/DStarControl.cpp index 768006f..be07f08 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019,2021 Jonathan Naylor, G4KLX + * Copyright (C) 2015-2019,2021,2023 Jonathan Naylor, G4KLX * * 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 @@ -640,6 +640,8 @@ void CDStarControl::writeEndRF() { m_rfState = RS_RF_LISTENING; + m_rfTimeoutTimer.stop(); + if (m_netState == RS_NET_IDLE) { m_display->clearDStar(); @@ -647,8 +649,6 @@ void CDStarControl::writeEndRF() if (m_network != NULL) m_network->reset(); - } else { - m_rfTimeoutTimer.stop(); } } From e10454c2d5d0c38c2b1ce19d3c020fac86d25b5b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 6 Jun 2023 19:41:17 +0100 Subject: [PATCH 03/29] Fix the signal handling. --- MMDVMHost.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 6f41f10..fbe0218 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021,2023 by Jonathan Naylor G4KLX * * 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 @@ -75,7 +75,7 @@ static void sigHandler2(int signum) const char* HEADER1 = "This software is for use on amateur radio networks only,"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER3 = "commercial networks is strictly prohibited."; -const char* HEADER4 = "Copyright(C) 2015-2021 by Jonathan Naylor, G4KLX and others"; +const char* HEADER4 = "Copyright(C) 2015-2023 by Jonathan Naylor, G4KLX and others"; int main(int argc, char** argv) { @@ -112,15 +112,24 @@ int main(int argc, char** argv) delete host; - if (m_signal == 2) - ::LogInfo("MMDVMHost-%s exited on receipt of SIGINT", VERSION); - - if (m_signal == 15) - ::LogInfo("MMDVMHost-%s exited on receipt of SIGTERM", VERSION); - - if (m_signal == 1) - ::LogInfo("MMDVMHost-%s is restarting on receipt of SIGHUP", VERSION); - } while (m_signal == 1); + switch (m_signal) { + case 2: + ::LogInfo("MMDVMHost-%s exited on receipt of SIGINT", VERSION); + break; + case 15: + ::LogInfo("MMDVMHost-%s exited on receipt of SIGTERM", VERSION); + break; + case 1: + ::LogInfo("MMDVMHost-%s exited on receipt of SIGHUP", VERSION); + break; + case 10: + ::LogInfo("MMDVMHost-%s is restarting on receipt of SIGUSR1", VERSION); + break; + default: + ::LogInfo("MMDVMHost-%s exited on receipt of an unknown signal", VERSION); + break; + } + } while (m_signal == 10); ::LogFinalise(); From d709c2bc60b19c4ea2021cbd650c0b7b692e6f15 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 6 Jun 2023 20:33:25 +0100 Subject: [PATCH 04/29] Clean up the DMR Talker Alias code and logging. --- DMRSlot.cpp | 65 +++++++++++++------------- DMRSlot.h | 5 +- DMRTA.cpp | 128 ++++++++++++++++++++++++++++------------------------ DMRTA.h | 21 +++++---- Display.cpp | 15 ++++-- Display.h | 6 +-- Nextion.cpp | 4 +- Nextion.h | 5 +- 8 files changed, 134 insertions(+), 115 deletions(-) diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 825e80b..f341e1e 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 Jonathan Naylor, G4KLX + * Copyright (C) 2015-2021,2023 Jonathan Naylor, G4KLX * * 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 @@ -81,12 +81,13 @@ m_rfEmbeddedData(NULL), m_rfEmbeddedReadN(0U), m_rfEmbeddedWriteN(1U), m_rfTalkerId(TALKER_ID_NONE), -m_rfTalkerAlias(), +m_rfTalkerAlias(slotNo), m_netEmbeddedLC(), m_netEmbeddedData(NULL), m_netEmbeddedReadN(0U), m_netEmbeddedWriteN(1U), m_netTalkerId(TALKER_ID_NONE), +m_netTalkerAlias(slotNo), m_rfLC(NULL), m_netLC(NULL), m_rfSeqNo(0U), @@ -661,7 +662,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) case FLCO_GPS_INFO: if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); logGPSPosition(data); } if (m_network != NULL) @@ -675,12 +676,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_HEADER)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(0, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); + m_rfTalkerAlias.add(0U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_rfTalkerId |= TALKER_ID_HEADER; @@ -694,12 +695,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(1, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); + m_rfTalkerAlias.add(1U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_rfTalkerId |= TALKER_ID_BLOCK1; @@ -713,12 +714,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(2, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); + m_rfTalkerAlias.add(2U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_rfTalkerId |= TALKER_ID_BLOCK2; @@ -732,12 +733,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(3, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R"); + m_rfTalkerAlias.add(3U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_rfTalkerId |= TALKER_ID_BLOCK3; @@ -1494,20 +1495,20 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) case FLCO_GPS_INFO: if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); logGPSPosition(data); } break; case FLCO_TALKER_ALIAS_HEADER: if (!(m_netTalkerId & TALKER_ID_HEADER)) { if (!m_netTalkerId) - m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(0, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "N"); + m_netTalkerAlias.reset(); + m_netTalkerAlias.add(0U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_netTalkerId |= TALKER_ID_HEADER; @@ -1516,13 +1517,13 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) case FLCO_TALKER_ALIAS_BLOCK1: if (!(m_netTalkerId & TALKER_ID_BLOCK1)) { if (!m_netTalkerId) - m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(1, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "N"); + m_netTalkerAlias.reset(); + m_netTalkerAlias.add(1U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_netTalkerId |= TALKER_ID_BLOCK1; @@ -1531,13 +1532,13 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) case FLCO_TALKER_ALIAS_BLOCK2: if (!(m_netTalkerId & TALKER_ID_BLOCK2)) { if (!m_netTalkerId) - m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(2, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "N"); + m_netTalkerAlias.reset(); + m_netTalkerAlias.add(2U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_netTalkerId |= TALKER_ID_BLOCK2; @@ -1546,13 +1547,13 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) case FLCO_TALKER_ALIAS_BLOCK3: if (!(m_netTalkerId & TALKER_ID_BLOCK3)) { if (!m_netTalkerId) - m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(3, data+2U, 7U); - m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "N"); + m_netTalkerAlias.reset(); + m_netTalkerAlias.add(3U, data + 2U, 7U); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); - CUtils::dump(2U, text, data, 9U); + CUtils::dump(1U, text, data, 9U); } m_netTalkerId |= TALKER_ID_BLOCK3; diff --git a/DMRSlot.h b/DMRSlot.h index 62bcc91..d3d58a2 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021,2023 by Jonathan Naylor G4KLX * * 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 @@ -80,6 +80,7 @@ private: unsigned int m_netEmbeddedReadN; unsigned int m_netEmbeddedWriteN; unsigned char m_netTalkerId; + CDMRTA m_netTalkerAlias; CDMRLC* m_rfLC; CDMRLC* m_netLC; unsigned char m_rfSeqNo; @@ -132,7 +133,7 @@ private: static unsigned char* m_idle; - static FLCO m_flco1; + static FLCO m_flco1; static unsigned char m_id1; static ACTIVITY_TYPE m_activity1; static FLCO m_flco2; diff --git a/DMRTA.cpp b/DMRTA.cpp index 9e60673..055116e 100644 --- a/DMRTA.cpp +++ b/DMRTA.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX +* Copyright (C) 2015,2016,2017,2018,2023 Jonathan Naylor, G4KLX * Copyright (C) 2018 by Shawn Chain, BG5HHP * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,9 @@ #include #include -CDMRTA::CDMRTA() : -m_TA(), +CDMRTA::CDMRTA(unsigned int slotNo) : +m_slotNo(slotNo), +m_ta(), m_buf() { } @@ -31,13 +32,14 @@ CDMRTA::~CDMRTA() bool CDMRTA::add(unsigned int blockId, const unsigned char* data, unsigned int len) { assert(data != NULL); - if (blockId > 3) { + + if (blockId > 3U) { // invalid block id reset(); return false; } - unsigned int offset = blockId * 7; + unsigned int offset = blockId * 7U; if (offset + len >= sizeof(m_buf)) { // buffer overflow @@ -52,75 +54,83 @@ bool CDMRTA::add(unsigned int blockId, const unsigned char* data, unsigned int l const unsigned char* CDMRTA::get() { - return (unsigned char*)m_TA; + return (unsigned char*)m_ta; } void CDMRTA::reset() { - ::memset(m_TA, 0, sizeof(m_TA)); - ::memset(m_buf, 0, sizeof(m_buf)); + ::memset(m_ta, 0x00U, sizeof(m_ta)); + ::memset(m_buf, 0x00U, sizeof(m_buf)); } bool CDMRTA::decodeTA() { - unsigned char *b; - unsigned char c; - int j; - unsigned int i, t1, t2; + unsigned int taFormat = (m_buf[0] >> 6U) & 0x03U; + unsigned int taSize = (m_buf[0] >> 1U) & 0x1FU; + ::strcpy(m_ta, "(could not decode)"); - unsigned char* talkerAlias = m_buf; + switch (taFormat) { + case 0U: { // 7 bit + ::memset(m_ta, 0x00U, sizeof(m_ta)); - unsigned int TAformat = (talkerAlias[0] >> 6U) & 0x03U; - unsigned int TAsize = (talkerAlias[0] >> 1U) & 0x1FU; - ::strcpy(m_TA, "(could not decode)"); + unsigned char* b = m_buf; + unsigned int t1 = 0U; + unsigned int t2 = 0U; + unsigned char c = 0U; - switch (TAformat) { - case 0U: // 7 bit - ::memset(m_TA, 0, sizeof(m_TA)); - b = &talkerAlias[0]; - t1 = 0U; t2 = 0U; c = 0U; - for (i = 0U; (i < 32U) && (t2 < TAsize); i++) { - for (j = 7; j >= 0; j--) { - c = (c << 1U) | (b[i] >> j); - if (++t1 == 7U) { - if (i > 0U) - m_TA[t2++] = c & 0x7FU; + for (unsigned int i = 0U; (i < 32U) && (t2 < taSize); i++) { + for (int j = 7; j >= 0; j--) { + c = (c << 1U) | (b[i] >> j); - t1 = 0U; - c = 0U; - } - } - } - m_TA[TAsize] = 0; - break; + if (++t1 == 7U) { + if (i > 0U) + m_ta[t2++] = c & 0x7FU; - case 1U: // ISO 8 bit - case 2U: // UTF8 - ::memcpy(m_TA, talkerAlias + 1U, sizeof(m_TA)); - break; + t1 = 0U; + c = 0U; + } + } + } - case 3U: // UTF16 poor man's conversion - t2=0; - ::memset(&m_TA, 0, sizeof(m_TA)); - for (i = 0U; (i < 15U) && (t2 < TAsize); i++) { - if (talkerAlias[2U * i + 1U] == 0) - m_TA[t2++] = talkerAlias[2U * i + 2U]; - else - m_TA[t2++] = '?'; - } - m_TA[TAsize] = 0; - break; - } + m_ta[taSize] = 0; + } + break; - size_t TAlen = ::strlen(m_TA); - LogMessage("DMR Talker Alias (Data Format %u, Received %u/%u char): '%s'", TAformat, TAlen, TAsize, m_TA); + case 1U: // ISO 8 bit + case 2U: // UTF8 + ::memcpy(m_ta, m_buf + 1U, sizeof(m_ta)); + break; - if (TAlen > TAsize) { - if (TAlen < 29U) - strcat(m_TA, " ?"); - else - strcpy(m_TA + 28U, " ?"); - } + case 3U: { // UTF16 poor man's conversion + unsigned int t2 = 0U; + ::memset(&m_ta, 0x00U, sizeof(m_ta)); - return TAlen >= TAsize; + for (unsigned int i = 0U; (i < 15U) && (t2 < taSize); i++) { + if (m_buf[2U * i + 1U] == 0) + m_ta[t2++] = m_buf[2U * i + 2U]; + else + m_ta[t2++] = '?'; + } + + m_ta[taSize] = 0; + } + break; + } + + size_t taLen = ::strlen(m_ta); + + if (taLen == taSize) + LogMessage("DMR Slot %u, Talker Alias \"%s\"", m_slotNo, m_ta); + + LogDebug("DMR Slot %u, Talker Alias (Data Format %u, Received %u/%u char): '%s'", m_slotNo, taFormat, taLen, taSize, m_ta); + + if (taLen > taSize) { + if (taLen < 29U) + ::strcat(m_ta, " ?"); + else + ::strcpy(m_ta + 28U, " ?"); + } + + return taLen >= taSize; } + diff --git a/DMRTA.h b/DMRTA.h index d53f93f..ccf48d9 100644 --- a/DMRTA.h +++ b/DMRTA.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX +* Copyright (C) 2015,2016,2017,2018,2023 Jonathan Naylor, G4KLX * Copyright (C) 2018 by Shawn Chain, BG5HHP * * This program is free software; you can redistribute it and/or modify @@ -17,19 +17,22 @@ class CDMRTA { public: - CDMRTA(); - ~CDMRTA(); + CDMRTA(unsigned int slotNo); + ~CDMRTA(); - bool add(unsigned int blockId, const unsigned char* data, unsigned int len); - const unsigned char* get(); - void reset(); + bool add(unsigned int blockId, const unsigned char* data, unsigned int len); + + const unsigned char* get(); + + void reset(); protected: - bool decodeTA(); + bool decodeTA(); private: - char m_TA[32]; - unsigned char m_buf[32]; + unsigned int m_slotNo; + char m_ta[32]; + unsigned char m_buf[32]; }; #endif diff --git a/Display.cpp b/Display.cpp index ebb1864..718ed84 100644 --- a/Display.cpp +++ b/Display.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2021,2023 by Jonathan Naylor G4KLX * * 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 @@ -189,10 +189,15 @@ void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi) writeDMRRSSIInt(slotNo, rssi); } -void CDisplay::writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type) +void CDisplay::writeDMRTA(unsigned int slotNo, const unsigned char* talkerAlias, const char* type) { - if (strcmp(type," ")==0) { writeDMRTAInt(slotNo, (unsigned char*)"", type); return; } - if (strlen((char*)talkerAlias)>=4U) writeDMRTAInt(slotNo, (unsigned char*)talkerAlias, type); + if (::strcmp(type, " ") == 0) { + writeDMRTAInt(slotNo, (unsigned char*)"", type); + return; + } + + if (::strlen((char*)talkerAlias) >= 4U) + writeDMRTAInt(slotNo, (unsigned char*)talkerAlias, type); } void CDisplay::writeDMRBER(unsigned int slotNo, float ber) @@ -487,7 +492,7 @@ void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) { } -void CDisplay::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type) +void CDisplay::writeDMRTAInt(unsigned int slotNo, const unsigned char* talkerAlias, const char* type) { } diff --git a/Display.h b/Display.h index fae929b..109b0ca 100644 --- a/Display.h +++ b/Display.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2021,2023 by Jonathan Naylor G4KLX * * 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 @@ -53,7 +53,7 @@ public: void writeDMR(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type); void writeDMRRSSI(unsigned int slotNo, unsigned char rssi); void writeDMRBER(unsigned int slotNo, float ber); - void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type); + void writeDMRTA(unsigned int slotNo, const unsigned char* talkerAlias, const char* type); void clearDMR(unsigned int slotNo); void writeFusion(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin); @@ -103,7 +103,7 @@ protected: virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0; virtual int writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type); virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi); - virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type); + virtual void writeDMRTAInt(unsigned int slotNo, const unsigned char* talkerAlias, const char* type); virtual void writeDMRBERInt(unsigned int slotNo, float ber); virtual void clearDMRInt(unsigned int slotNo) = 0; diff --git a/Nextion.cpp b/Nextion.cpp index 4875fe5..6df9a6d 100644 --- a/Nextion.cpp +++ b/Nextion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2023 by Jonathan Naylor G4KLX * * 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 @@ -477,7 +477,7 @@ void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) } } -void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type) +void CNextion::writeDMRTAInt(unsigned int slotNo, const unsigned char* talkerAlias, const char* type) { if (!(m_screenLayout & LAYOUT_TA_ENABLE)) return; diff --git a/Nextion.h b/Nextion.h index 713fc90..d440526 100644 --- a/Nextion.h +++ b/Nextion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2023 by Jonathan Naylor G4KLX * * 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 @@ -50,8 +50,7 @@ protected: virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi); - virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type); - + virtual void writeDMRTAInt(unsigned int slotNo, const unsigned char* talkerAlias, const char* type); virtual void writeDMRBERInt(unsigned int slotNo, float ber); virtual void clearDMRInt(unsigned int slotNo); From 9085112b4d2e55f1f843db9cbbbad30fbadd6190 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 7 Jun 2023 11:28:41 +0100 Subject: [PATCH 05/29] Add extra logging when starting and stopping the MMDVM. --- M17Control.cpp | 1 - MMDVMHost.cpp | 28 +++++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index 79def48..5d7f7e6 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -362,7 +362,6 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) // Remove any erronous EOF from the FN netData[M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES + 0U] &= 0x7FU; - // The CRC is added in the networking code m_network->write(netData); diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index fbe0218..ef8f9d2 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -297,8 +297,8 @@ int CMMDVMHost::run() LogInfo(HEADER3); LogInfo(HEADER4); - LogMessage("MMDVMHost-%s is starting", VERSION); - LogMessage("Built %s %s (GitID #%.7s)", __TIME__, __DATE__, gitversion); + LogInfo("MMDVMHost-%s is starting", VERSION); + LogInfo("Built %s %s (GitID #%.7s)", __TIME__, __DATE__, gitversion); readParams(); @@ -353,6 +353,8 @@ int CMMDVMHost::run() m_display = CDisplay::createDisplay(m_conf, m_modem); + LogInfo("Opening network connections"); + if (m_dstarEnabled && m_conf.getDStarNetworkEnabled()) { ret = createDStarNetwork(); if (!ret) @@ -488,6 +490,8 @@ int CMMDVMHost::run() m_dmrLookup->read(); } + LogInfo("Starting protocol handlers"); + CStopWatch stopWatch; stopWatch.start(); @@ -765,7 +769,7 @@ int CMMDVMHost::run() setMode(MODE_IDLE); - LogMessage("MMDVMHost-%s is running", VERSION); + LogInfo("MMDVMHost-%s is running", VERSION); while (!m_killed) { bool lockout = m_modem->hasLockout(); @@ -1307,18 +1311,14 @@ int CMMDVMHost::run() setMode(MODE_QUIT); - m_modem->close(); - delete m_modem; - - m_display->close(); - delete m_display; - if (m_dmrLookup != NULL) m_dmrLookup->stop(); if (m_nxdnLookup != NULL) m_nxdnLookup->stop(); + LogInfo("Closing network connections"); + if (m_dstarNetwork != NULL) { m_dstarNetwork->close(); delete m_dstarNetwork; @@ -1374,6 +1374,8 @@ int CMMDVMHost::run() delete m_remoteControl; } + LogInfo("Stopping protocol handlers"); + delete m_dstar; delete m_dmr; delete m_ysf; @@ -1384,6 +1386,14 @@ int CMMDVMHost::run() delete m_fm; delete m_ax25; + LogInfo("MMDVMHost-%s has stopped", VERSION); + + m_modem->close(); + delete m_modem; + + m_display->close(); + delete m_display; + return 0; } From da147031c98fbf176e745c17f0bc001a132541d8 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 7 Jun 2023 12:27:44 +0100 Subject: [PATCH 06/29] Add host startup and closedown messages to JSON/MQTT. --- MMDVMHost.cpp | 40 ++++++++++++++++++++++++++++------------ MMDVMHost.h | 3 ++- schema.json | 3 ++- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 30f1b77..7bdf8b7 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -369,6 +369,7 @@ int CMMDVMHost::run() m_display = CDisplay::createDisplay(m_conf, m_modem); LogInfo("Opening network connections"); + writeJSONMessage("Opening network connections"); if (m_dstarEnabled && m_conf.getDStarNetworkEnabled()) { ret = createDStarNetwork(); @@ -506,6 +507,7 @@ int CMMDVMHost::run() } LogInfo("Starting protocol handlers"); + writeJSONMessage("Starting protocol handlers"); CStopWatch stopWatch; stopWatch.start(); @@ -785,6 +787,7 @@ int CMMDVMHost::run() setMode(MODE_IDLE); LogInfo("MMDVMHost-%s is running", VERSION); + writeJSONMessage("MMDVMHost is running"); while (!m_killed) { bool lockout = m_modem->hasLockout(); @@ -1333,6 +1336,7 @@ int CMMDVMHost::run() m_nxdnLookup->stop(); LogInfo("Closing network connections"); + writeJSONMessage("Closing network connections"); if (m_dstarNetwork != NULL) { m_dstarNetwork->close(); @@ -1390,6 +1394,7 @@ int CMMDVMHost::run() } LogInfo("Stopping protocol handlers"); + writeJSONMessage("Stopping protocol handlers"); delete m_dstar; delete m_dmr; @@ -1402,6 +1407,7 @@ int CMMDVMHost::run() delete m_ax25; LogInfo("MMDVMHost-%s has stopped", VERSION); + writeJSONMessage("MMDVMHost has stopped"); m_modem->close(); delete m_modem; @@ -2047,7 +2053,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("D-Star"); - writeJSON("D-Star"); + writeJSONMode("D-Star"); break; case MODE_DMR: @@ -2096,7 +2102,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("DMR"); - writeJSON("DMR"); + writeJSONMode("DMR"); break; case MODE_YSF: @@ -2141,7 +2147,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("System Fusion"); - writeJSON("YSF"); + writeJSONMode("YSF"); break; case MODE_P25: @@ -2186,7 +2192,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("P25"); - writeJSON("P25"); + writeJSONMode("P25"); break; case MODE_NXDN: @@ -2231,7 +2237,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("NXDN"); - writeJSON("NXDN"); + writeJSONMode("NXDN"); break; case MODE_M17: @@ -2276,7 +2282,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("M17"); - writeJSON("M17"); + writeJSONMode("M17"); break; case MODE_POCSAG: @@ -2321,7 +2327,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("POCSAG"); - writeJSON("POCSAG"); + writeJSONMode("POCSAG"); break; case MODE_FM: @@ -2371,7 +2377,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.start(); m_cwIdTimer.stop(); createLockFile("FM"); - writeJSON("FM"); + writeJSONMode("FM"); break; case MODE_LOCKOUT: @@ -2421,7 +2427,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.stop(); m_cwIdTimer.stop(); removeLockFile(); - writeJSON("lockout"); + writeJSONMode("lockout"); break; case MODE_ERROR: @@ -2471,7 +2477,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_modeTimer.stop(); m_cwIdTimer.stop(); removeLockFile(); - writeJSON("error"); + writeJSONMode("error"); break; default: @@ -2530,7 +2536,7 @@ void CMMDVMHost::setMode(unsigned char mode) m_mode = MODE_IDLE; m_modeTimer.stop(); removeLockFile(); - writeJSON("idle"); + writeJSONMode("idle"); break; } } @@ -2821,7 +2827,7 @@ void CMMDVMHost::buildNetworkHostsString(std::string &str) str += std::string(" fm:\"") + ((m_fmEnabled && (m_fmNetwork != NULL)) ? m_conf.getFMGatewayAddress() : "NONE") + "\""; } -void CMMDVMHost::writeJSON(const std::string& mode) +void CMMDVMHost::writeJSONMode(const std::string& mode) { nlohmann::json json; @@ -2831,3 +2837,13 @@ void CMMDVMHost::writeJSON(const std::string& mode) WriteJSON("MMDVM", json); } +void CMMDVMHost::writeJSONMessage(const std::string& message) +{ + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["message"] = message; + + WriteJSON("MMDVM", json); +} + diff --git a/MMDVMHost.h b/MMDVMHost.h index a6cb437..6d3cb3e 100644 --- a/MMDVMHost.h +++ b/MMDVMHost.h @@ -142,7 +142,8 @@ private: void createLockFile(const char* mode) const; void removeLockFile() const; - void writeJSON(const std::string& mode); + void writeJSONMode(const std::string& mode); + void writeJSONMessage(const std::string& message); }; #endif diff --git a/schema.json b/schema.json index 5ffd1f7..4dd9a15 100644 --- a/schema.json +++ b/schema.json @@ -35,7 +35,8 @@ "type": "object", "timestamp": {"$ref": "#/$defs/timestamp"}, "mode": {"$ref": "#/$defs/mmdvm_mode"}, - "required": ["timestamp", "mode"] + "message": {"type": "string"}, + "required": ["timestamp"] }, "D-Star": { From 8d941db7b1f7ea1f8b8d1ef4cc6773f8fdedced1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 9 Jun 2023 15:46:29 +0100 Subject: [PATCH 07/29] Simplify the end of transmission JSON for all DV modes. --- DMRSlot.cpp | 98 ++++++++++++++++++++++++-------------------- DMRSlot.h | 9 ++-- DStarControl.cpp | 92 +++++++++++++++-------------------------- DStarControl.h | 10 ++--- M17Control.cpp | 48 +++++++++++++++------- M17Control.h | 10 +++-- NXDNControl.cpp | 54 +++++++++++++++--------- NXDNControl.h | 8 ++-- P25Control.cpp | 38 +++++++++-------- P25Control.h | 7 ++-- YSFControl.cpp | 104 ++++++++++++++--------------------------------- YSFControl.h | 12 +++--- schema.json | 12 +++--- 13 files changed, 243 insertions(+), 259 deletions(-) diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 1f5e627..eed76ac 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -151,10 +151,10 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (m_rssi != 0U) { LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", srcId, src, flco == FLCO_GROUP, dstId, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("lost", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("lost", srcId, src, flco == FLCO_GROUP, dstId, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("lost", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); } if (m_rfTimeout) { @@ -174,7 +174,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) FLCO flco = m_rfLC->getFLCO(); LogMessage("DMR Slot %u, RF data transmission lost from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str()); - writeJSONRF("lost", srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("lost"); writeEndRF(); return false; } @@ -371,10 +371,10 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (m_rssi != 0U) { LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", srcId, src, flco == FLCO_GROUP, dstId, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", srcId, src, flco == FLCO_GROUP, dstId, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("end", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); } m_display->writeDMRTA(m_slotNo, NULL, " "); @@ -449,7 +449,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (m_rfFrames == 0U) { LogMessage("DMR Slot %u, ended RF data transmission from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONRF("end", srcId, src, gi, dstId); + writeJSONRF("end"); writeEndRF(); } @@ -559,11 +559,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (m_rfState != RS_RF_DATA || m_rfFrames == 0U) return false; - unsigned int srcId = m_rfLC->getSrcId(); - unsigned int dstId = m_rfLC->getDstId(); - std::string src = m_lookup->find(srcId); - FLCO flco = m_rfLC->getFLCO(); - // Regenerate the rate 1/2 payload if (dataType == DT_RATE_12_DATA) { CBPTC19696 bptc; @@ -600,7 +595,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (m_rfFrames == 0U) { LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo); - writeJSONRF("end", srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("end"); writeEndRF(); } @@ -1324,7 +1319,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) // We've received the voice header and terminator haven't we? m_netFrames += 2U; LogMessage("DMR Slot %u, received network end of voice transmission from %s to %s%s, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); - writeJSONNet("end", srcId, src, flco == FLCO_GROUP, dstId, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); + writeJSONNet("end", float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); m_display->writeDMRTA(m_slotNo, NULL, " "); writeEndNet(); } else if (dataType == DT_DATA_HEADER) { @@ -1379,7 +1374,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) if (m_netFrames == 0U) { LogMessage("DMR Slot %u, ended network data transmission from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONNet("end", srcId, src, gi, dstId); + writeJSONNet("end"); writeEndNet(); } } else if (dataType == DT_VOICE_SYNC) { @@ -1805,12 +1800,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) writeQueueNet(data); if (m_netFrames == 0U) { - unsigned int srcId = m_netLC->getSrcId(); - unsigned int dstId = m_netLC->getDstId(); - std::string src = m_lookup->find(srcId); - LogMessage("DMR Slot %u, ended network data transmission", m_slotNo); - writeJSONNet("end", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("end"); writeEndNet(); } } else { @@ -1874,12 +1865,8 @@ void CDMRSlot::clock() m_rfTimeoutTimer.clock(ms); if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired()) { if (!m_rfTimeout) { - unsigned int srcId = m_rfLC->getSrcId(); - unsigned int dstId = m_rfLC->getDstId(); - std::string src = m_lookup->find(srcId); - LogMessage("DMR Slot %u, RF user has timed out", m_slotNo); - writeJSONRF("timeout", srcId, src, m_rfLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONRF("timeout"); m_rfTimeout = true; } } @@ -1887,12 +1874,8 @@ void CDMRSlot::clock() m_netTimeoutTimer.clock(ms); if (m_netTimeoutTimer.isRunning() && m_netTimeoutTimer.hasExpired()) { if (!m_netTimeout) { - unsigned int srcId = m_netLC->getSrcId(); - unsigned int dstId = m_netLC->getDstId(); - std::string src = m_lookup->find(srcId); - LogMessage("DMR Slot %u, network user has timed out", m_slotNo); - writeJSONNet("timeout", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("timeout"); m_netTimeout = true; } } @@ -1902,25 +1885,17 @@ void CDMRSlot::clock() if (m_networkWatchdog.hasExpired()) { if (m_netState == RS_NET_AUDIO) { - unsigned int srcId = m_netLC->getSrcId(); - unsigned int dstId = m_netLC->getDstId(); - std::string src = m_lookup->find(srcId); - // We've received the voice header haven't we? m_netFrames += 1U; LogMessage("DMR Slot %u, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); - writeJSONNet("lost", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); + writeJSONNet("lost", float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits)); writeEndNet(true); #if defined(DUMP_DMR) closeFile(); #endif } else { - unsigned int srcId = m_netLC->getSrcId(); - unsigned int dstId = m_netLC->getDstId(); - std::string src = m_lookup->find(srcId); - LogMessage("DMR Slot %u, network watchdog has expired", m_slotNo); - writeJSONNet("lost", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("lost"); writeEndNet(); #if defined(DUMP_DMR) closeFile(); @@ -2314,6 +2289,17 @@ void CDMRSlot::enable(bool enabled) m_enabled = enabled; } +void CDMRSlot::writeJSONRF(const char* action) +{ + assert(action != NULL); + + nlohmann::json json; + + writeJSON(json, "rf", action); + + WriteJSON("DMR", json); +} + void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); @@ -2352,13 +2338,13 @@ void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::st WriteJSON("DMR", json); } -void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber) +void CDMRSlot::writeJSONRF(const char* action, float duration, float ber) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action); json["duration"] = duration; json["ber"] = ber; @@ -2366,13 +2352,13 @@ void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::st WriteJSON("DMR", json); } -void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) +void CDMRSlot::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action); json["duration"] = duration; json["ber"] = ber; @@ -2387,6 +2373,17 @@ void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::st WriteJSON("DMR", json); } +void CDMRSlot::writeJSONNet(const char* action) +{ + assert(action != NULL); + + nlohmann::json json; + + writeJSON(json, "network", action); + + WriteJSON("DMR", json); +} + void CDMRSlot::writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); @@ -2425,13 +2422,13 @@ void CDMRSlot::writeJSONNet(const char* action, unsigned int srcId, const std::s WriteJSON("DMR", json); } -void CDMRSlot::writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float loss, float ber) +void CDMRSlot::writeJSONNet(const char* action, float duration, float loss, float ber) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "network", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "network", action); json["duration"] = duration; json["loss"] = loss; @@ -2440,6 +2437,17 @@ void CDMRSlot::writeJSONNet(const char* action, unsigned int srcId, const std::s WriteJSON("DMR", json); } +void CDMRSlot::writeJSON(nlohmann::json& json, const char* source, const char* action) +{ + assert(source != NULL); + assert(action != NULL); + + json["timestamp"] = CUtils::createTimestamp(); + json["source"] = source; + json["action"] = action; + json["slot"] = int(m_slotNo); +} + void CDMRSlot::writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(source != NULL); diff --git a/DMRSlot.h b/DMRSlot.h index 18fadd2..42888e0 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -161,17 +161,20 @@ private: static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP, ACTIVITY_TYPE type = ACTIVITY_NONE); + void writeJSONRF(const char* action); void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames); void writeJSONRF(const char* action, const char* desc, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); - void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber); - void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); + void writeJSONRF(const char* action, float duration, float ber); + void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); + void writeJSONNet(const char* action); void writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); void writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames); - void writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float loss, float ber); + void writeJSONNet(const char* action, float duration, float loss, float ber); void writeJSONNet(const char* action, const char* desc, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); + void writeJSON(nlohmann::json& json, const char* source, const char* action); void writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); }; diff --git a/DStarControl.cpp b/DStarControl.cpp index b44375c..c1577ab 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -227,10 +227,10 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (m_rssi != 0U) { LogMessage("D-Star, transmission lost from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("lost", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("D-Star, transmission lost from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("lost", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("lost", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); return false; @@ -433,10 +433,10 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (m_rssi != 0U) { LogMessage("D-Star, received RF end of transmission from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("D-Star, received RF end of transmission from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("end", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); @@ -795,7 +795,7 @@ void CDStarControl::writeNetwork() // We've received the header and EOT haven't we? m_netFrames += 2U; LogMessage("D-Star, received network end of transmission from %8.8s/%4.4s to %8.8s, %.1f seconds, %u%% packet loss", my1, my2, your, float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); - writeJSONNet("end", my1, my2, your, float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); + writeJSONNet("end", float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); writeEndNet(); } else if (type == TAG_DATA) { @@ -877,7 +877,7 @@ void CDStarControl::clock() m_netFrames += 1U; LogMessage("D-Star, network watchdog has expired, %.1f seconds, %u%% packet loss", float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); - writeJSONNet("lost", my1, my2, your, float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); + writeJSONNet("lost", float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); writeEndNet(); #if defined(DUMP_DSTAR) closeFile(); @@ -1347,35 +1347,36 @@ void CDStarControl::writeJSONRF(const char* action, const unsigned char* my1, co nlohmann::json json; - writeJSONRF(json, action, my1, my2, your); + json["timestamp"] = CUtils::createTimestamp(); + + json["source_cs"] = convertBuffer(my1, DSTAR_LONG_CALLSIGN_LENGTH); + json["source_ext"] = convertBuffer(my2, DSTAR_SHORT_CALLSIGN_LENGTH); + json["destination_cs"] = convertBuffer(your, DSTAR_LONG_CALLSIGN_LENGTH); + + json["source"] = "rf"; + json["action"] = action; WriteJSON("D-Star", json); } -void CDStarControl::writeJSONRF(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float ber) +void CDStarControl::writeJSONRF(const char* action, float duration, float ber) { assert(action != NULL); - assert(my1 != NULL); - assert(my2 != NULL); - assert(your != NULL); nlohmann::json json; - writeJSONRF(json, action, my1, my2, your, duration, ber); + writeJSONRF(json, action, duration, ber); WriteJSON("D-Star", json); } -void CDStarControl::writeJSONRF(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) +void CDStarControl::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); - assert(my1 != NULL); - assert(my2 != NULL); - assert(your != NULL); nlohmann::json json; - writeJSONRF(json, action, my1, my2, your, duration, ber); + writeJSONRF(json, action, duration, ber); nlohmann::json rssi; rssi["min"] = -int(minRSSI); @@ -1396,7 +1397,14 @@ void CDStarControl::writeJSONNet(const char* action, const unsigned char* my1, c nlohmann::json json; - writeJSONNet(json, action, my1, my2, your); + json["timestamp"] = CUtils::createTimestamp(); + + json["source_cs"] = convertBuffer(my1, DSTAR_LONG_CALLSIGN_LENGTH); + json["source_ext"] = convertBuffer(my2, DSTAR_SHORT_CALLSIGN_LENGTH); + json["destination_cs"] = convertBuffer(your, DSTAR_LONG_CALLSIGN_LENGTH); + + json["source"] = "network"; + json["action"] = action; if (reflector != NULL) json["reflector"] = convertBuffer(reflector, DSTAR_LONG_CALLSIGN_LENGTH); @@ -1404,67 +1412,33 @@ void CDStarControl::writeJSONNet(const char* action, const unsigned char* my1, c WriteJSON("D-Star", json); } -void CDStarControl::writeJSONNet(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float loss) +void CDStarControl::writeJSONNet(const char* action, float duration, float loss) { assert(action != NULL); - assert(my1 != NULL); - assert(my2 != NULL); - assert(your != NULL); nlohmann::json json; - writeJSONNet(json, action, my1, my2, your); + json["timestamp"] = CUtils::createTimestamp(); json["duration"] = duration; json["loss"] = loss; + json["source"] = "network"; + json["action"] = action; + WriteJSON("D-Star", json); } -void CDStarControl::writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your) +void CDStarControl::writeJSONRF(nlohmann::json& json, const char* action, float duration, float ber) { assert(action != NULL); - assert(my1 != NULL); - assert(my2 != NULL); - assert(your != NULL); json["timestamp"] = CUtils::createTimestamp(); - json["source_cs"] = convertBuffer(my1, DSTAR_LONG_CALLSIGN_LENGTH); - json["source_ext"] = convertBuffer(my2, DSTAR_SHORT_CALLSIGN_LENGTH); - json["destination_cs"] = convertBuffer(your, DSTAR_LONG_CALLSIGN_LENGTH); - - json["source"] = "rf"; - json["action"] = action; -} - -void CDStarControl::writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float ber) -{ - assert(action != NULL); - assert(my1 != NULL); - assert(my2 != NULL); - assert(your != NULL); - - writeJSONRF(json, action, my1, my2, your); - json["duration"] = duration; json["ber"] = ber; -} -void CDStarControl::writeJSONNet(nlohmann::json& json, const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your) -{ - assert(action != NULL); - assert(my1 != NULL); - assert(my2 != NULL); - assert(your != NULL); - - json["timestamp"] = CUtils::createTimestamp(); - - json["source_cs"] = convertBuffer(my1, DSTAR_LONG_CALLSIGN_LENGTH); - json["source_ext"] = convertBuffer(my2, DSTAR_SHORT_CALLSIGN_LENGTH); - json["destination_cs"] = convertBuffer(your, DSTAR_LONG_CALLSIGN_LENGTH); - - json["source"] = "network"; + json["source"] = "rf"; json["action"] = action; } diff --git a/DStarControl.h b/DStarControl.h index f7e6bec..dc6202f 100644 --- a/DStarControl.h +++ b/DStarControl.h @@ -136,14 +136,12 @@ private: void writeEndNet(); void writeJSONRF(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your); - void writeJSONRF(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float ber); - void writeJSONRF(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); + void writeJSONRF(const char* action, float duration, float ber); + void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); void writeJSONNet(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, const unsigned char* reflector = NULL); - void writeJSONNet(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float loss); + void writeJSONNet(const char* action, float duration, float loss); - void writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your); - void writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your, float duration, float ber); - void writeJSONNet(nlohmann::json& json, const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your); + void writeJSONRF(nlohmann::json& json, const char* action, float duration, float ber); std::string convertBuffer(const unsigned char* buffer, unsigned int length) const; diff --git a/M17Control.cpp b/M17Control.cpp index a2f2bc8..7909b52 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -115,10 +115,10 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (type == TAG_LOST && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA_AUDIO)) { if (m_rssi != 0U) { LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", m_rfState, m_source, m_dest, float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("lost", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("lost", m_rfState, m_source, m_dest, float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("lost", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); return false; @@ -423,10 +423,10 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_rssi != 0U) { LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", m_rfState, m_source, m_dest, float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("end", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } else { LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", m_rfState, m_source, m_dest, float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } writeEndRF(); @@ -646,7 +646,7 @@ void CM17Control::writeNetwork() uint16_t fn = (netData[28U] << 8) + (netData[29U] << 0); if ((fn & 0x8000U) == 0x8000U) { LogMessage("M17, received network end of transmission from %s to %s, %.1f seconds", m_source.c_str(), m_dest.c_str(), float(m_netFrames) / 25.0F); - writeJSONNet("end", m_netState, m_source, m_dest, float(m_netFrames) / 25.0F); + writeJSONNet("end", float(m_netFrames) / 25.0F); unsigned char data[M17_FRAME_LENGTH_BYTES + 2U]; @@ -781,7 +781,7 @@ void CM17Control::clock(unsigned int ms) if (m_networkWatchdog.hasExpired()) { LogMessage("M17, network watchdog has expired, %.1f seconds", float(m_netFrames) / 25.0F); - writeJSONNet("lost", m_netState, m_source, m_dest, float(m_netFrames) / 25.0F); + writeJSONNet("lost", float(m_netFrames) / 25.0F); writeEndNet(); } } @@ -936,24 +936,24 @@ void CM17Control::writeJSONRF(const char* action, RPT_RF_STATE state, const std: WriteJSON("M17", json); } -void CM17Control::writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest, float duration, float ber) +void CM17Control::writeJSONRF(const char* action, float duration, float ber) { assert(action != NULL); nlohmann::json json; - writeJSONRF(json, action, state, source, dest, duration, ber); + writeJSONRF(json, action, duration, ber); WriteJSON("M17", json); } -void CM17Control::writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) +void CM17Control::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); nlohmann::json json; - writeJSONRF(json, action, state, source, dest, duration, ber); + writeJSONRF(json, action, duration, ber); nlohmann::json rssi; rssi["min"] = -int(minRSSI); @@ -976,19 +976,29 @@ void CM17Control::writeJSONNet(const char* action, RPT_NET_STATE state, const st WriteJSON("M17", json); } -void CM17Control::writeJSONNet(const char* action, RPT_NET_STATE state, const std::string& source, const std::string& dest, float duration) +void CM17Control::writeJSONNet(const char* action, float duration) { assert(action != NULL); nlohmann::json json; - writeJSONNet(json, action, state, source, dest); + writeJSONNet(json, action); json["duration"] = duration; WriteJSON("M17", json); } +void CM17Control::writeJSONRF(nlohmann::json& json, const char* action) +{ + assert(action != NULL); + + json["timestamp"] = CUtils::createTimestamp(); + + json["source"] = "rf"; + json["action"] = action; +} + void CM17Control::writeJSONRF(nlohmann::json& json, const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest) { assert(action != NULL); @@ -1017,16 +1027,26 @@ void CM17Control::writeJSONRF(nlohmann::json& json, const char* action, RPT_RF_S } } -void CM17Control::writeJSONRF(nlohmann::json& json, const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest, float duration, float ber) +void CM17Control::writeJSONRF(nlohmann::json& json, const char* action, float duration, float ber) { assert(action != NULL); - writeJSONRF(json, action, state, source, dest); + writeJSONRF(json, action); json["duration"] = duration; json["ber"] = ber; } +void CM17Control::writeJSONNet(nlohmann::json& json, const char* action) +{ + assert(action != NULL); + + json["timestamp"] = CUtils::createTimestamp(); + + json["source"] = "network"; + json["action"] = action; +} + void CM17Control::writeJSONNet(nlohmann::json& json, const char* action, RPT_NET_STATE state, const std::string& source, const std::string& dest) { assert(action != NULL); diff --git a/M17Control.h b/M17Control.h index ae505c2..731f987 100644 --- a/M17Control.h +++ b/M17Control.h @@ -106,14 +106,16 @@ private: void writeEndNet(); void writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest); - void writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest, float duration, float ber); - void writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); + void writeJSONRF(const char* action, float duration, float ber); + void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); void writeJSONNet(const char* action, RPT_NET_STATE state, const std::string& source, const std::string& dest); - void writeJSONNet(const char* action, RPT_NET_STATE state, const std::string& source, const std::string& dest, float duration); + void writeJSONNet(const char* action, float duration); void writeJSONRF(nlohmann::json& json, const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest); - void writeJSONRF(nlohmann::json& json, const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest, float duration, float ber); + void writeJSONRF(nlohmann::json& json, const char* action); + void writeJSONRF(nlohmann::json& json, const char* action, float duration, float ber); + void writeJSONNet(nlohmann::json& json, const char* action); void writeJSONNet(nlohmann::json& json, const char* action, RPT_NET_STATE state, const std::string& source, const std::string& dest); bool openFile(); diff --git a/NXDNControl.cpp b/NXDNControl.cpp index b904b24..22b159f 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -100,10 +100,10 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) if (m_rssi != 0U) { LogMessage("NXDN, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", srcId, source, grp, dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("lost", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("NXDN, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("lost", srcId, source, grp, dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("lost", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); return false; @@ -275,10 +275,10 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne m_rfFrames++; if (m_rssi != 0U) { LogMessage("NXDN, received RF end of transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", srcId, source, grp, dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("NXDN, received RF end of transmission from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", srcId, source, grp, dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("end", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); } else { @@ -688,7 +688,7 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data) std::string source = m_lookup->find(srcId); LogMessage("NXDN, ended RF data transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); - writeJSONNet("end", srcId, source, grp, dstId); + writeJSONNet("end"); writeEndRF(); } @@ -858,7 +858,7 @@ void CNXDNControl::writeNetwork() if (type == NXDN_MESSAGE_TYPE_TX_REL) { m_netFrames++; LogMessage("NXDN, received network end of transmission from %s to %s%u, %.1f seconds", source.get(keyCALLSIGN).c_str(), grp ? "TG " : "", dstId, float(m_netFrames) / 12.5F); - writeJSONNet("end", srcId, source.get(keyCALLSIGN), grp, dstId, float(m_netFrames) / 12.5F); + writeJSONNet("end", float(m_netFrames) / 12.5F); writeEndNet(); } else if (type == NXDN_MESSAGE_TYPE_VCALL) { LogMessage("NXDN, received network transmission from %s to %s%u", source.get(keyCALLSIGN).c_str(), grp ? "TG " : "", dstId); @@ -1016,15 +1016,8 @@ void CNXDNControl::clock(unsigned int ms) m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { - unsigned short srcId = m_netLayer3.getSourceUnitId(); - unsigned short dstId = m_netLayer3.getDestinationGroupId(); - bool grp = m_netLayer3.getIsGroup(); - - class CUserDBentry source; - m_lookup->findWithName(srcId, &source); - LogMessage("NXDN, network watchdog has expired, %.1f seconds", float(m_netFrames) / 12.5F); - writeJSONNet("lost", srcId, source.get(keyCALLSIGN), grp, dstId, float(m_netFrames) / 12.5F); + writeJSONNet("lost", float(m_netFrames) / 12.5F); writeEndNet(); } } @@ -1177,13 +1170,13 @@ void CNXDNControl::writeJSONRF(const char* action, unsigned short srcId, const s WriteJSON("NXDN", json); } -void CNXDNControl::writeJSONRF(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId, float duration, float ber) +void CNXDNControl::writeJSONRF(const char* action, float duration, float ber) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action); json["duration"] = duration; json["ber"] = ber; @@ -1191,13 +1184,13 @@ void CNXDNControl::writeJSONRF(const char* action, unsigned short srcId, const s WriteJSON("NXDN", json); } -void CNXDNControl::writeJSONRF(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) +void CNXDNControl::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action); json["duration"] = duration; json["ber"] = ber; @@ -1212,6 +1205,17 @@ void CNXDNControl::writeJSONRF(const char* action, unsigned short srcId, const s WriteJSON("NXDN", json); } +void CNXDNControl::writeJSONNet(const char* action) +{ + assert(action != NULL); + + nlohmann::json json; + + writeJSON(json, "network", action); + + WriteJSON("NXDN", json); +} + void CNXDNControl::writeJSONNet(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId) { assert(action != NULL); @@ -1236,19 +1240,29 @@ void CNXDNControl::writeJSONNet(const char* action, unsigned short srcId, const WriteJSON("NXDN", json); } -void CNXDNControl::writeJSONNet(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId, float duration) +void CNXDNControl::writeJSONNet(const char* action, float duration) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "network", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "network", action); json["duration"] = duration; WriteJSON("NXDN", json); } +void CNXDNControl::writeJSON(nlohmann::json& json, const char* source, const char* action) +{ + assert(source != NULL); + assert(action != NULL); + + json["timestamp"] = CUtils::createTimestamp(); + json["source"] = source; + json["action"] = action; +} + void CNXDNControl::writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId) { assert(source != NULL); diff --git a/NXDNControl.h b/NXDNControl.h index 7fdbb66..efdabf8 100644 --- a/NXDNControl.h +++ b/NXDNControl.h @@ -104,13 +104,15 @@ private: void closeFile(); void writeJSONRF(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId); - void writeJSONRF(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId, float duration, float ber); - void writeJSONRF(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); + void writeJSONRF(const char* action, float duration, float ber); + void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); void writeJSONNet(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId); void writeJSONNet(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId, unsigned char frames); - void writeJSONNet(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId, float duration); + void writeJSONNet(const char* action); + void writeJSONNet(const char* action, float duration); + void writeJSON(nlohmann::json& json, const char* source, const char* action); void writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId); }; diff --git a/P25Control.cpp b/P25Control.cpp index 0c45e60..a208021 100644 --- a/P25Control.cpp +++ b/P25Control.cpp @@ -129,10 +129,10 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) if (m_rssi != 0U) { LogMessage("P25, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", srcId, source, grp, dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("lost", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("P25, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("lost", srcId, source, grp, dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("lost", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); } if (m_netState == RS_NET_IDLE) @@ -470,10 +470,10 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) if (m_rssi != 0U) { LogMessage("P25, received RF end of voice transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", srcId, source, grp, dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("P25, received RF end of voice transmission from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", srcId, source, grp, dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("end", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); } m_display->clearP25(); @@ -734,12 +734,8 @@ void CP25Control::clock(unsigned int ms) m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { - unsigned int dstId = m_netData.getDstId(); - unsigned int srcId = m_netData.getSrcId(); - std::string source = m_lookup->find(srcId); - LogMessage("P25, network watchdog has expired, %.1f seconds, %u%% packet loss", float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); - writeJSONNet("lost", srcId, source, m_netData.getLCF() == P25_LCF_GROUP, dstId, float(m_netFrames) / 50.0F, float(m_netLost * 100U) / float(m_netFrames)); + writeJSONNet("lost", float(m_netFrames) / 50.0F, float(m_netLost * 100U) / float(m_netFrames)); m_display->clearP25(); m_networkWatchdog.stop(); @@ -1141,7 +1137,7 @@ void CP25Control::createNetTerminator() std::string source = m_lookup->find(srcId); LogMessage("P25, network end of transmission from %s to %s%u, %.1f seconds, %u%% packet loss", source.c_str(), m_netData.getLCF() == P25_LCF_GROUP ? "TG " : "", dstId, float(m_netFrames) / 50.0F, (m_netLost * 100U) / m_netFrames); - writeJSONNet("end", srcId, source, m_netData.getLCF() == P25_LCF_GROUP, dstId, float(m_netFrames) / 50.0F, float(m_netLost * 100U) / float(m_netFrames)); + writeJSONNet("end", float(m_netFrames) / 50.0F, float(m_netLost * 100U) / float(m_netFrames)); m_display->clearP25(); m_netTimeout.stop(); @@ -1228,13 +1224,13 @@ void CP25Control::writeJSONRF(const char* action, unsigned int srcId, const std: WriteJSON("P25", json); } -void CP25Control::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber) +void CP25Control::writeJSONRF(const char* action, float duration, float ber) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action); json["duration"] = duration; json["ber"] = ber; @@ -1242,13 +1238,13 @@ void CP25Control::writeJSONRF(const char* action, unsigned int srcId, const std: WriteJSON("P25", json); } -void CP25Control::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) +void CP25Control::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action); json["duration"] = duration; json["ber"] = ber; @@ -1274,13 +1270,13 @@ void CP25Control::writeJSONNet(const char* action, unsigned int srcId, const std WriteJSON("P25", json); } -void CP25Control::writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float loss) +void CP25Control::writeJSONNet(const char* action, float duration, float loss) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "network", action, srcId, srcInfo, grp, dstId); + writeJSON(json, "network", action); json["duration"] = duration; json["loss"] = loss; @@ -1288,6 +1284,16 @@ void CP25Control::writeJSONNet(const char* action, unsigned int srcId, const std WriteJSON("P25", json); } +void CP25Control::writeJSON(nlohmann::json& json, const char* source, const char* action) +{ + assert(source != NULL); + assert(action != NULL); + + json["timestamp"] = CUtils::createTimestamp(); + json["source"] = source; + json["action"] = action; +} + void CP25Control::writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(source != NULL); diff --git a/P25Control.h b/P25Control.h index 4e7dfb8..d927da3 100644 --- a/P25Control.h +++ b/P25Control.h @@ -122,12 +122,13 @@ private: void closeFile(); void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); - void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber); - void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); + void writeJSONRF(const char* action, float duration, float ber); + void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); void writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); - void writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float loss); + void writeJSONNet(const char* action, float duration, float loss); + void writeJSON(nlohmann::json& json, const char* source, const char* action); void writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); }; diff --git a/YSFControl.cpp b/YSFControl.cpp index 874a602..a11b690 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -105,15 +105,14 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) return false; unsigned char type = data[0U]; - unsigned char dgid = m_lastFICH.getDGId(); if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) { if (m_rssi != 0U) { LogMessage("YSF, transmission lost from %10.10s to %10.10s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, m_rfDest, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("lost", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("YSF, transmission lost from %10.10s to %10.10s, %.1f seconds, BER: %.1f%%", m_rfSource, m_rfDest, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("lost", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("lost", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); return false; @@ -324,10 +323,10 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) if (m_rssi != 0U) { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", "voice_vw", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", "voice_vw", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); @@ -498,10 +497,10 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) if (m_rssi != 0U) { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", "voice_dn", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", "voice_dn", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } writeEndRF(); @@ -803,10 +802,10 @@ bool CYSFControl::processFRData(bool valid, unsigned char *data) if (m_rssi != 0U) { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", "data_fr", m_rfSource, dgid, float(m_rfFrames) / 10.0F, 0.0F, m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 10.0F, 0.0F, m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); } else { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds", m_rfSource, dgid, float(m_rfFrames) / 10.0F); - writeJSONRF("end", "data_fr", m_rfSource, dgid, float(m_rfFrames) / 10.0F, 0.0F); + writeJSONRF("end", float(m_rfFrames) / 10.0F, 0.0F); } writeEndRF(); @@ -1064,7 +1063,7 @@ void CYSFControl::writeNetwork() if (end) { LogMessage("YSF, received network end of transmission from %10.10s to DG-ID %u at %10.10s, %.1f seconds, %u%% packet loss", m_netSource, dgid, data + 4U, float(m_netFrames) / 10.0F, (m_netLost * 100U) / m_netFrames); - writeJSONNet("end", m_netSource, dgid, data + 4U, float(m_netFrames) / 10.0F, (m_netLost * 100U) / m_netFrames); + writeJSONNet("end", float(m_netFrames) / 10.0F, (m_netLost * 100U) / m_netFrames); writeEndNet(); } } @@ -1081,9 +1080,8 @@ void CYSFControl::clock(unsigned int ms) m_networkWatchdog.clock(ms); if (m_networkWatchdog.hasExpired()) { - unsigned char dgid = m_lastFICH.getDGId(); LogMessage("YSF, network watchdog has expired, %.1f seconds, %u%% packet loss", float(m_netFrames) / 10.0F, (m_netLost * 100U) / m_netFrames); - writeJSONNet("lost", m_netSource, dgid, float(m_netFrames) / 10.0F, (m_netLost * 100U) / m_netFrames); + writeJSONNet("lost", float(m_netFrames) / 10.0F, (m_netLost * 100U) / m_netFrames); writeEndNet(); } } @@ -1263,14 +1261,13 @@ void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsign WriteJSON("YSF", json); } -void CYSFControl::writeJSONRF(const char* action, const unsigned char* source, unsigned char dgid, float duration, float ber) +void CYSFControl::writeJSONRF(const char* action, float duration, float ber) { assert(action != NULL); - assert(source != NULL); nlohmann::json json; - writeJSONRF(json, action, source, dgid); + writeJSONRF(json, action); json["duration"] = duration; json["ber"] = ber; @@ -1278,56 +1275,14 @@ void CYSFControl::writeJSONRF(const char* action, const unsigned char* source, u WriteJSON("YSF", json); } -void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, float duration, float ber) +void CYSFControl::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); - assert(mode != NULL); - assert(source != NULL); nlohmann::json json; - writeJSONRF(json, action, source, dgid); + writeJSONRF(json, action); - json["mode"] = mode; - json["duration"] = duration; - json["ber"] = ber; - - WriteJSON("YSF", json); -} - -void CYSFControl::writeJSONRF(const char* action, const unsigned char* source, unsigned char dgid, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) -{ - assert(action != NULL); - assert(source != NULL); - - nlohmann::json json; - - writeJSONRF(json, action, source, dgid); - - json["duration"] = duration; - json["ber"] = ber; - - nlohmann::json rssi; - rssi["min"] = -int(minRSSI); - rssi["max"] = -int(maxRSSI); - rssi["ave"] = -int(aveRSSI); - - json["rssi"] = rssi; - - WriteJSON("YSF", json); -} - -void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) -{ - assert(action != NULL); - assert(mode != NULL); - assert(source != NULL); - - nlohmann::json json; - - writeJSONRF(json, action, source, dgid); - - json["mode"] = mode; json["duration"] = duration; json["ber"] = ber; @@ -1356,14 +1311,13 @@ void CYSFControl::writeJSONNet(const char* action, const unsigned char* source, WriteJSON("YSF", json); } -void CYSFControl::writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, float duration, unsigned int loss) +void CYSFControl::writeJSONNet(const char* action, float duration, unsigned int loss) { assert(action != NULL); - assert(source != NULL); nlohmann::json json; - writeJSONNet(json, action, source, dgid); + writeJSONNet(json, action); json["duration"] = duration; json["loss"] = loss; @@ -1371,22 +1325,14 @@ void CYSFControl::writeJSONNet(const char* action, const unsigned char* source, WriteJSON("YSF", json); } -void CYSFControl::writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, const unsigned char* reflector, float duration, unsigned int loss) +void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action) { assert(action != NULL); - assert(source != NULL); - assert(reflector != NULL); - nlohmann::json json; + json["timestamp"] = CUtils::createTimestamp(); - writeJSONNet(json, action, source, dgid); - - json["reflector"] = convertBuffer(reflector); - - json["duration"] = duration; - json["loss"] = loss; - - WriteJSON("YSF", json); + json["source"] = "rf"; + json["action"] = action; } void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid) @@ -1403,6 +1349,16 @@ void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action, const un json["dg-id"] = int(dgid); } +void CYSFControl::writeJSONNet(nlohmann::json& json, const char* action) +{ + assert(action != NULL); + + json["timestamp"] = CUtils::createTimestamp(); + + json["source"] = "network"; + json["action"] = action; +} + void CYSFControl::writeJSONNet(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid) { assert(action != NULL); diff --git a/YSFControl.h b/YSFControl.h index 1fe92ad..fba0378 100644 --- a/YSFControl.h +++ b/YSFControl.h @@ -103,16 +103,16 @@ private: void writeEndNet(); void writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid); - void writeJSONRF(const char* action, const unsigned char* source, unsigned char dgid, float duration, float ber); - void writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, float duration, float ber); - void writeJSONRF(const char* action, const unsigned char* source, unsigned char dgid, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); - void writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); + void writeJSONRF(const char* action, float duration, float ber); + void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); void writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, const unsigned char* reflector); - void writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, float duration, unsigned int loss); - void writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, const unsigned char* reflector, float duration, unsigned int loss); + void writeJSONNet(const char* action, float duration, unsigned int loss); + void writeJSONRF(nlohmann::json& json, const char* action); void writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid); + + void writeJSONNet(nlohmann::json& json, const char* action); void writeJSONNet(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid); std::string convertBuffer(const unsigned char* buffer) const; diff --git a/schema.json b/schema.json index 4dd9a15..2d10c0a 100644 --- a/schema.json +++ b/schema.json @@ -56,7 +56,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source_cs", "source_ext", "destination_cs", "source", "action"] + "required": ["timestamp", "source", "action"] }, "DMR": { @@ -79,7 +79,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source_id", "destination_id", "destination_type", "slot", "source", "action"] + "required": ["timestamp", "slot", "source", "action"] }, "YSF": { @@ -99,7 +99,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source_cs", "dg-id", "source", "action"] + "required": ["timestamp", "source", "action"] }, "P25": { @@ -119,7 +119,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source_id", "destination_id", "destination_type", "source", "action"] + "required": ["timestamp", "source", "action"] }, "NXDN": { @@ -138,7 +138,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source_id", "destination_id", "destination_type", "source", "action"] + "required": ["timestamp", "source", "action"] }, "POCSAG": { @@ -190,6 +190,6 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source_cs", "destination_cs", "source", "action", "traffic_type"] + "required": ["timestamp", "source", "action"] } } From cf161dbd3d12a324916d5bdc47b3bc0b5cd819db Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 9 Jun 2023 17:24:07 +0100 Subject: [PATCH 08/29] Remove the unneeded source from the JSON except for the start of the transmission. --- DMRSlot.cpp | 14 ++++++-------- DMRSlot.h | 2 +- DStarControl.cpp | 2 -- M17Control.cpp | 2 -- NXDNControl.cpp | 16 +++++++--------- NXDNControl.h | 2 +- P25Control.cpp | 10 ++++------ P25Control.h | 2 +- YSFControl.cpp | 8 ++------ schema.json | 39 +++++++++++++++++++++++++++++++++------ 10 files changed, 55 insertions(+), 42 deletions(-) diff --git a/DMRSlot.cpp b/DMRSlot.cpp index eed76ac..962fbe3 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -2295,7 +2295,7 @@ void CDMRSlot::writeJSONRF(const char* action) nlohmann::json json; - writeJSON(json, "rf", action); + writeJSON(json, action); WriteJSON("DMR", json); } @@ -2344,7 +2344,7 @@ void CDMRSlot::writeJSONRF(const char* action, float duration, float ber) nlohmann::json json; - writeJSON(json, "rf", action); + writeJSON(json, action); json["duration"] = duration; json["ber"] = ber; @@ -2358,7 +2358,7 @@ void CDMRSlot::writeJSONRF(const char* action, float duration, float ber, unsign nlohmann::json json; - writeJSON(json, "rf", action); + writeJSON(json, action); json["duration"] = duration; json["ber"] = ber; @@ -2379,7 +2379,7 @@ void CDMRSlot::writeJSONNet(const char* action) nlohmann::json json; - writeJSON(json, "network", action); + writeJSON(json, action); WriteJSON("DMR", json); } @@ -2428,7 +2428,7 @@ void CDMRSlot::writeJSONNet(const char* action, float duration, float loss, floa nlohmann::json json; - writeJSON(json, "network", action); + writeJSON(json, action); json["duration"] = duration; json["loss"] = loss; @@ -2437,13 +2437,11 @@ void CDMRSlot::writeJSONNet(const char* action, float duration, float loss, floa WriteJSON("DMR", json); } -void CDMRSlot::writeJSON(nlohmann::json& json, const char* source, const char* action) +void CDMRSlot::writeJSON(nlohmann::json& json, const char* action) { - assert(source != NULL); assert(action != NULL); json["timestamp"] = CUtils::createTimestamp(); - json["source"] = source; json["action"] = action; json["slot"] = int(m_slotNo); } diff --git a/DMRSlot.h b/DMRSlot.h index 42888e0..2e940c2 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -174,7 +174,7 @@ private: void writeJSONNet(const char* action, float duration, float loss, float ber); void writeJSONNet(const char* action, const char* desc, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); - void writeJSON(nlohmann::json& json, const char* source, const char* action); + void writeJSON(nlohmann::json& json, const char* action); void writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); }; diff --git a/DStarControl.cpp b/DStarControl.cpp index c1577ab..4f13e4d 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -1423,7 +1423,6 @@ void CDStarControl::writeJSONNet(const char* action, float duration, float loss) json["duration"] = duration; json["loss"] = loss; - json["source"] = "network"; json["action"] = action; WriteJSON("D-Star", json); @@ -1438,7 +1437,6 @@ void CDStarControl::writeJSONRF(nlohmann::json& json, const char* action, float json["duration"] = duration; json["ber"] = ber; - json["source"] = "rf"; json["action"] = action; } diff --git a/M17Control.cpp b/M17Control.cpp index 7909b52..fa2e3a8 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -995,7 +995,6 @@ void CM17Control::writeJSONRF(nlohmann::json& json, const char* action) json["timestamp"] = CUtils::createTimestamp(); - json["source"] = "rf"; json["action"] = action; } @@ -1043,7 +1042,6 @@ void CM17Control::writeJSONNet(nlohmann::json& json, const char* action) json["timestamp"] = CUtils::createTimestamp(); - json["source"] = "network"; json["action"] = action; } diff --git a/NXDNControl.cpp b/NXDNControl.cpp index 22b159f..7417571 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -1176,7 +1176,7 @@ void CNXDNControl::writeJSONRF(const char* action, float duration, float ber) nlohmann::json json; - writeJSON(json, "rf", action); + writeJSON(json, action); json["duration"] = duration; json["ber"] = ber; @@ -1190,7 +1190,7 @@ void CNXDNControl::writeJSONRF(const char* action, float duration, float ber, un nlohmann::json json; - writeJSON(json, "rf", action); + writeJSON(json, action); json["duration"] = duration; json["ber"] = ber; @@ -1211,7 +1211,7 @@ void CNXDNControl::writeJSONNet(const char* action) nlohmann::json json; - writeJSON(json, "network", action); + writeJSON(json, action); WriteJSON("NXDN", json); } @@ -1246,21 +1246,19 @@ void CNXDNControl::writeJSONNet(const char* action, float duration) nlohmann::json json; - writeJSON(json, "network", action); + writeJSON(json, action); json["duration"] = duration; WriteJSON("NXDN", json); } -void CNXDNControl::writeJSON(nlohmann::json& json, const char* source, const char* action) +void CNXDNControl::writeJSON(nlohmann::json& json, const char* action) { - assert(source != NULL); assert(action != NULL); - json["timestamp"] = CUtils::createTimestamp(); - json["source"] = source; - json["action"] = action; + json["timestamp"] = CUtils::createTimestamp(); + json["action"] = action; } void CNXDNControl::writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId) diff --git a/NXDNControl.h b/NXDNControl.h index efdabf8..9925000 100644 --- a/NXDNControl.h +++ b/NXDNControl.h @@ -112,7 +112,7 @@ private: void writeJSONNet(const char* action); void writeJSONNet(const char* action, float duration); - void writeJSON(nlohmann::json& json, const char* source, const char* action); + void writeJSON(nlohmann::json& json, const char* action); void writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId); }; diff --git a/P25Control.cpp b/P25Control.cpp index a208021..0e69298 100644 --- a/P25Control.cpp +++ b/P25Control.cpp @@ -1230,7 +1230,7 @@ void CP25Control::writeJSONRF(const char* action, float duration, float ber) nlohmann::json json; - writeJSON(json, "rf", action); + writeJSON(json, action); json["duration"] = duration; json["ber"] = ber; @@ -1244,7 +1244,7 @@ void CP25Control::writeJSONRF(const char* action, float duration, float ber, uns nlohmann::json json; - writeJSON(json, "rf", action); + writeJSON(json, action); json["duration"] = duration; json["ber"] = ber; @@ -1276,7 +1276,7 @@ void CP25Control::writeJSONNet(const char* action, float duration, float loss) nlohmann::json json; - writeJSON(json, "network", action); + writeJSON(json, action); json["duration"] = duration; json["loss"] = loss; @@ -1284,13 +1284,11 @@ void CP25Control::writeJSONNet(const char* action, float duration, float loss) WriteJSON("P25", json); } -void CP25Control::writeJSON(nlohmann::json& json, const char* source, const char* action) +void CP25Control::writeJSON(nlohmann::json& json, const char* action) { - assert(source != NULL); assert(action != NULL); json["timestamp"] = CUtils::createTimestamp(); - json["source"] = source; json["action"] = action; } diff --git a/P25Control.h b/P25Control.h index d927da3..de4d917 100644 --- a/P25Control.h +++ b/P25Control.h @@ -128,7 +128,7 @@ private: void writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); void writeJSONNet(const char* action, float duration, float loss); - void writeJSON(nlohmann::json& json, const char* source, const char* action); + void writeJSON(nlohmann::json& json, const char* action); void writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); }; diff --git a/YSFControl.cpp b/YSFControl.cpp index a11b690..7492707 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -1330,9 +1330,7 @@ void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action) assert(action != NULL); json["timestamp"] = CUtils::createTimestamp(); - - json["source"] = "rf"; - json["action"] = action; + json["action"] = action; } void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid) @@ -1354,9 +1352,7 @@ void CYSFControl::writeJSONNet(nlohmann::json& json, const char* action) assert(action != NULL); json["timestamp"] = CUtils::createTimestamp(); - - json["source"] = "network"; - json["action"] = action; + json["action"] = action; } void CYSFControl::writeJSONNet(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid) diff --git a/schema.json b/schema.json index 2d10c0a..4ab3e94 100644 --- a/schema.json +++ b/schema.json @@ -39,6 +39,33 @@ "required": ["timestamp"] }, + "RSSI" : { + "type": "object", + "timestamp": {"$ref": "#/$defs/timestamp"}, + "mode": {"$ref": "#/$defs/mmdvm_mode"}, + "slot": {"$ref": "#/$defs/dmr_slot"}, + "value": {"$ref": "#/$defs/rssi"}, + "required": ["timestamp", "mode", "value"] + }, + + "BER" : { + "type": "object", + "timestamp": {"$ref": "#/$defs/timestamp"}, + "mode": {"$ref": "#/$defs/mmdvm_mode"}, + "slot": {"$ref": "#/$defs/dmr_slot"}, + "value": {"$ref": "#/$defs/ber"}, + "required": ["timestamp", "mode", "value"] + }, + + "Text" : { + "type": "object", + "timestamp": {"$ref": "#/$defs/timestamp"}, + "mode": {"$ref": "#/$defs/mmdvm_mode"}, + "slot": {"$ref": "#/$defs/dmr_slot"}, + "value": {"type": "string"}, + "required": ["timestamp", "mode", "value"] + }, + "D-Star": { "type": "object", "timestamp": {"$ref": "#/$defs/timestamp"}, @@ -56,7 +83,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source", "action"] + "required": ["timestamp", "action"] }, "DMR": { @@ -79,7 +106,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "slot", "source", "action"] + "required": ["timestamp", "slot", "action"] }, "YSF": { @@ -99,7 +126,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source", "action"] + "required": ["timestamp", "action"] }, "P25": { @@ -119,7 +146,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source", "action"] + "required": ["timestamp", "action"] }, "NXDN": { @@ -138,7 +165,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source", "action"] + "required": ["timestamp", "action"] }, "POCSAG": { @@ -190,6 +217,6 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source", "action"] + "required": ["timestamp", "action"] } } From 09ba49d48676824e95df990b437ecb5024edd7b3 Mon Sep 17 00:00:00 2001 From: Chipster Date: Fri, 9 Jun 2023 16:39:35 -0500 Subject: [PATCH 09/29] Improve OLED status messages a bit: M17 tweaks from KC1AWV. Tweaks by W0CHP for Idle/Stopping status messages, and a new status for when the host is in Auto-AP mode. --- OLED.cpp | 110 ++++++++++++++++++++++++++++++++++++++++--------------- OLED.h | 2 + 2 files changed, 83 insertions(+), 29 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index b289894..7a823b1 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -243,8 +243,9 @@ bool COLED::open() m_display.display(); // display it (clear display) OLED_statusbar(); - m_display.setCursor(0,OLED_LINE3); - m_display.print("Startup"); + m_display.setCursor(0,OLED_LINE4); + m_display.setTextSize(1); + m_display.print(" -Initializing-"); m_display.display(); return true; @@ -257,11 +258,6 @@ void COLED::setIdleInt() m_display.clearDisplay(); OLED_statusbar(); -// m_display.setCursor(0,30); -// m_display.setTextSize(3); -// m_display.print("Idle"); - -// m_display.setTextSize(1); if (m_displayScroll && m_displayLogoScreensaver) m_display.startscrolldiagleft(0x00,0x0f); //the MMDVM logo scrolls the whole screen m_display.display(); @@ -284,6 +280,53 @@ void COLED::setIdleInt() networkInfoInitialized = true; passCounter = 0; } + + // Let's let the users know if they are in Auto-AP mode... + if (m_ipaddress.find("wlan0_ap") != std::string::npos) { + size_t pos = m_ipaddress.find("wlan0_ap"); + if (pos != std::string::npos) { + m_ipaddress.erase(pos, 9); // remove redundant/superfluous "wlan0_ap" from string + } + // Read ssid value from /etc/hostapd.conf if it exists... + std::string ssid; + std::ifstream configFile("/etc/hostapd.conf"); + if (configFile.is_open()) { + std::string line; + while (std::getline(configFile, line)) { + if (line.find("ssid=") != std::string::npos) { + std::istringstream iss(line); + std::string key, value; + if (std::getline(iss, key, '=') && std::getline(iss, value)) { + ssid = value; + break; + } + } + } + configFile.close(); + } else { + ssid = "Unknown"; // `/etc/hostapd.conf` does not exist... + } + + m_display.setCursor(0, OLED_LINE3); + m_display.setTextSize(1); + m_display.printf("Auto-AP Running..."); + m_display.setCursor(0, OLED_LINE4); + m_display.setTextSize(1); + m_display.printf("SSID: %s", ssid.c_str()); + m_display.setCursor(0, OLED_LINE5); + m_display.setTextSize(1); + m_display.printf("IP: %s", m_ipaddress.c_str()); + } else { // Connected to network - no Auto-AP mode; normal display layout... + m_display.setCursor(0,OLED_LINE3); + m_display.setTextSize(1); + m_display.print(" -IDLE-"); + m_display.setCursor(0, OLED_LINE5); + m_display.printf(" %s", m_ipaddress.c_str()); + } + + if (m_displayScroll && m_displayLogoScreensaver) + m_display.startscrolldiagleft(0x00, 0x0f); // the MMDVM logo scrolls the whole screen + m_display.display(); } void COLED::setErrorInt(const char* text) @@ -324,11 +367,12 @@ void COLED::setQuitInt() OLED_statusbar(); m_display.setCursor(0,30); - m_display.setTextSize(3); - m_display.print("Stopped"); + m_display.setTextSize(2); + m_display.print(" Stopping"); m_display.setTextSize(1); m_display.display(); + sleep(2); } void COLED::setFMInt() @@ -374,7 +418,7 @@ void COLED::clearDStarInt() m_display.fillRect(0,OLED_LINE3, m_display.width(),m_display.height(),BLACK); //clear everything beneath the logo m_display.setCursor(40,OLED_LINE3); - m_display.print("Listening"); + m_display.print("Standby"); m_display.setCursor(0,OLED_LINE5); m_display.printf("%s",m_ipaddress.c_str()); @@ -454,18 +498,18 @@ void COLED::clearDMRInt(unsigned int slotNo) if (slotNo == 1U) { m_display.fillRect(0, OLED_LINE3, m_display.width(), 40, BLACK); m_display.setCursor(0,OLED_LINE3); - m_display.print("Slot: 1 Listening"); + m_display.print("Slot: 1 Standby"); } else { m_display.fillRect(0, OLED_LINE5, m_display.width(), 40, BLACK); m_display.setCursor(0, OLED_LINE5); - m_display.print("Slot: 2 Listening"); + m_display.print("Slot: 2 Standby"); } } else { m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK); m_display.setCursor(0,OLED_LINE3); - m_display.printf("Slot: %i Listening",slotNo); + m_display.printf("Slot: %i Standby",slotNo); } m_display.fillRect(0, OLED_LINE6, m_display.width(), 20, BLACK); @@ -497,7 +541,7 @@ void COLED::clearFusionInt() m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK); m_display.setCursor(40,OLED_LINE4); - m_display.print("Listening"); + m_display.print("Standby"); m_display.setCursor(0,OLED_LINE6); m_display.printf("%s",m_ipaddress.c_str()); @@ -527,7 +571,7 @@ void COLED::clearP25Int() m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK); m_display.setCursor(40,OLED_LINE4); - m_display.print("Listening"); + m_display.print("Standby"); m_display.setCursor(0,OLED_LINE6); m_display.printf("%s",m_ipaddress.c_str()); @@ -577,7 +621,7 @@ void COLED::clearNXDNInt() m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK); m_display.setCursor(40,OLED_LINE3); - m_display.print("Listening"); + m_display.print("Standby"); m_display.setCursor(0,OLED_LINE6); m_display.printf("%s",m_ipaddress.c_str()); @@ -593,10 +637,14 @@ void COLED::writeM17Int(const char* source, const char* dest, const char* type) m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK); m_display.setCursor(0,OLED_LINE3); - m_display.printf("%s %s", type, source); + m_display.printf("from: %s %s", type, source); m_display.setCursor(0,OLED_LINE4); - m_display.printf(" %s", dest); + m_display.printf("to: %s", dest); + + m_display.setCursor(0,OLED_LINE6); + m_display.printf("%s",m_ipaddress.c_str()); + OLED_statusbar(); m_display.display(); @@ -607,7 +655,7 @@ void COLED::clearM17Int() m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK); m_display.setCursor(40,OLED_LINE4); - m_display.print("Listening"); + m_display.print("Standby"); m_display.setCursor(0,OLED_LINE6); m_display.printf("%s",m_ipaddress.c_str()); @@ -682,7 +730,7 @@ void COLED::clearPOCSAGInt() m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK); m_display.setCursor(40,OLED_LINE3); - m_display.print("Listening"); + m_display.print("Standby"); m_display.setCursor(0,OLED_LINE6); m_display.printf("%s",m_ipaddress.c_str()); @@ -696,7 +744,7 @@ void COLED::writeCWInt() m_display.setCursor(0,30); m_display.setTextSize(3); - m_display.print("CW TX"); + m_display.print("CW ID TX"); m_display.setTextSize(1); m_display.display(); @@ -708,14 +756,18 @@ void COLED::clearCWInt() { m_display.clearDisplay(); - m_display.setCursor(0,30); - m_display.setTextSize(3); - m_display.print("Idle"); - + m_display.setCursor(0,OLED_LINE1); + m_display.setTextSize(2); m_display.setTextSize(1); - m_display.display(); + m_display.print(" -IDLE-"); + m_display.setCursor(0,OLED_LINE3); + m_display.printf("%s",m_ipaddress.c_str()); + if (m_displayScroll) - m_display.startscrollleft(0x02,0x0f); + m_display.startscrolldiagleft(0x00,0x0f); + m_display.display(); + + } void COLED::close() @@ -724,9 +776,9 @@ void COLED::close() m_display.fillRect(0, 0, m_display.width(), 16, BLACK); if (m_displayScroll) m_display.startscrollleft(0x00,0x01); - m_display.setCursor(0,00); + m_display.setCursor(0,OLED_LINE3); m_display.setTextSize(2); - m_display.print("-CLOSE-"); + m_display.print(" -OFFLINE-"); m_display.display(); m_display.close(); diff --git a/OLED.h b/OLED.h index 9b6be22..14723cb 100644 --- a/OLED.h +++ b/OLED.h @@ -32,6 +32,8 @@ #include "UserDBentry.h" #include +#include +#include #include "ArduiPi_OLED_lib.h" #include "Adafruit_GFX.h" From 8da65564408f0dcad2bb5c0d4c8f0f32eb4e1684 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 11 Jun 2023 11:38:59 +0100 Subject: [PATCH 10/29] Add JSON RSSI, DMR and Talker Alias to DMR. --- DMRSlot.cpp | 191 +++++++++++++++++++++++++++++++++++++++++++--------- DMRSlot.h | 8 +++ 2 files changed, 166 insertions(+), 33 deletions(-) diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 962fbe3..9b0e096 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -69,6 +69,9 @@ const unsigned int NO_HEADERS_SIMPLEX = 8U; const unsigned int NO_HEADERS_DUPLEX = 3U; const unsigned int NO_PREAMBLE_CSBK = 15U; +const unsigned int RSSI_COUNT = 4U; // 4 * 360ms = 1440ms +const unsigned int BER_COUNT = 24U * 141U; // 24 * 60ms = 1440ms + // #define DUMP_DMR CDMRSlot::CDMRSlot(unsigned int slotNo, unsigned int timeout) : @@ -116,7 +119,11 @@ m_rssi(0U), m_maxRSSI(0U), m_minRSSI(0U), m_aveRSSI(0U), +m_rssiCountTotal(0U), +m_rssiAccum(0U), m_rssiCount(0U), +m_bitErrsAccum(0U), +m_bitsCount(0U), m_enabled(true), m_fp(NULL) { @@ -150,8 +157,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) FLCO flco = m_rfLC->getFLCO(); if (m_rssi != 0U) { - LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("lost", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("lost", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -204,7 +211,9 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } bool dataSync = (data[1U] & DMR_SYNC_DATA) == DMR_SYNC_DATA; @@ -285,11 +294,17 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_rfEmbeddedWriteN = 1U; m_rfTalkerId = TALKER_ID_NONE; - m_minRSSI = m_rssi; - m_maxRSSI = m_rssi; - m_aveRSSI = m_rssi; + m_minRSSI = m_rssi; + m_maxRSSI = m_rssi; + m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + m_bitsCount = 0U; + m_bitErrsAccum = 0U; + if (m_duplex) { m_queue.clear(); m_modem->writeDMRAbort(m_slotNo); @@ -370,8 +385,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) FLCO flco = m_rfLC->getFLCO(); if (m_rssi != 0U) { - LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("end", float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -613,12 +628,16 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) errors = m_fec.regenerateDMR(data + 2U); LogDebug("DMR Slot %u, audio sequence no. 0, errs: %u/141 (%.1f%%)", m_slotNo, errors, float(errors) / 1.41F); m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); - m_rfErrs += errors; + m_rfErrs += errors; + m_bitErrsAccum += errors; } - m_rfBits += 141U; + m_bitsCount += 141U; + m_rfBits += 141U; m_rfFrames++; + writeJSONBER(); + m_rfEmbeddedReadN = (m_rfEmbeddedReadN + 1U) % 2U; m_rfEmbeddedWriteN = (m_rfEmbeddedWriteN + 1U) % 2U; @@ -661,12 +680,16 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) errors = m_fec.regenerateDMR(data + 2U); LogDebug("DMR Slot %u, audio sequence no. %u, errs: %u/141 (%.1f%%)", m_slotNo, m_rfN, errors, float(errors) / 1.41F); m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); - m_rfErrs += errors; + m_rfErrs += errors; + m_bitErrsAccum += errors; } - m_rfBits += 141U; + m_bitsCount += 141U; + m_rfBits += 141U; m_rfFrames++; + writeJSONBER(); + // Get the LCSS from the EMB CDMREMB emb; emb.putData(data + 2U); @@ -705,8 +728,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_HEADER)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(0U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + + bool complete = m_rfTalkerAlias.add(0U, data + 2U, 7U); + if (complete) { + writeJSONText(m_rfTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); @@ -724,8 +751,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(1U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + + bool complete = m_rfTalkerAlias.add(1U, data + 2U, 7U); + if (complete) { + writeJSONText(m_rfTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); @@ -743,8 +774,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(2U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + + bool complete = m_rfTalkerAlias.add(2U, data + 2U, 7U); + if (complete) { + writeJSONText(m_rfTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); @@ -762,8 +797,12 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) { if (m_rfTalkerId == TALKER_ID_NONE) m_rfTalkerAlias.reset(); - m_rfTalkerAlias.add(3U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + + bool complete = m_rfTalkerAlias.add(3U, data + 2U, 7U); + if (complete) { + writeJSONText(m_rfTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias.get(), "R"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); @@ -889,11 +928,17 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_rfEmbeddedWriteN = 1U; m_rfTalkerId = TALKER_ID_NONE; - m_minRSSI = m_rssi; - m_maxRSSI = m_rssi; - m_aveRSSI = m_rssi; + m_minRSSI = m_rssi; + m_maxRSSI = m_rssi; + m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + if (m_duplex) { m_queue.clear(); m_modem->writeDMRAbort(m_slotNo); @@ -920,12 +965,16 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (fid == FID_ETSI || fid == FID_DMRA) { errors = m_fec.regenerateDMR(data + 2U); LogDebug("DMR Slot %u, audio sequence no. %u, errs: %u/141 (%.1f%%)", m_slotNo, m_rfN, errors, float(errors) / 1.41F); - m_rfErrs += errors; + m_bitErrsAccum += errors; + m_rfErrs += errors; } - m_rfBits += 141U; + m_bitsCount += 141U; + m_rfBits += 141U; m_rfFrames++; + writeJSONBER(); + data[0U] = TAG_DATA; data[1U] = 0x00U; @@ -1008,6 +1057,9 @@ void CDMRSlot::writeEndRF(bool writeEnd) m_rfErrs = 0U; m_rfBits = 1U; + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + m_rfSeqNo = 0U; m_rfN = 0U; @@ -1542,8 +1594,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) if (!(m_netTalkerId & TALKER_ID_HEADER)) { if (!m_netTalkerId) m_netTalkerAlias.reset(); - m_netTalkerAlias.add(0U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + + bool complete = m_netTalkerAlias.add(0U, data + 2U, 7U); + if (complete) { + writeJSONText(m_netTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); @@ -1557,8 +1613,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) if (!(m_netTalkerId & TALKER_ID_BLOCK1)) { if (!m_netTalkerId) m_netTalkerAlias.reset(); - m_netTalkerAlias.add(1U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + + bool complete = m_netTalkerAlias.add(1U, data + 2U, 7U); + if (complete) { + writeJSONText(m_netTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); @@ -1572,8 +1632,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) if (!(m_netTalkerId & TALKER_ID_BLOCK2)) { if (!m_netTalkerId) m_netTalkerAlias.reset(); - m_netTalkerAlias.add(2U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + + bool complete = m_netTalkerAlias.add(2U, data + 2U, 7U); + if (complete) { + writeJSONText(m_netTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); @@ -1587,8 +1651,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) if (!(m_netTalkerId & TALKER_ID_BLOCK3)) { if (!m_netTalkerId) m_netTalkerAlias.reset(); - m_netTalkerAlias.add(3U, data + 2U, 7U); - m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + + bool complete = m_netTalkerAlias.add(3U, data + 2U, 7U); + if (complete) { + writeJSONText(m_netTalkerAlias.get()); + m_display->writeDMRTA(m_slotNo, m_netTalkerAlias.get(), "N"); + } if (m_dumpTAData) { ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); @@ -2258,6 +2326,9 @@ void CDMRSlot::enable(bool enabled) m_rfErrs = 0U; m_rfBits = 1U; + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + m_rfSeqNo = 0U; m_rfN = 0U; @@ -2289,6 +2360,60 @@ void CDMRSlot::enable(bool enabled) m_enabled = enabled; } +void CDMRSlot::writeJSONRSSI() +{ + m_rssiAccum += m_rssi; + m_rssiCount++; + + if (m_rssiCount >= RSSI_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "DMR"; + json["slot"] = int(m_slotNo); + + json["value"] = -int(m_rssiAccum / m_rssiCount); + + WriteJSON("RSSI", json); + + m_rssiAccum = 0U; + m_rssiCount = 0U; + } +} + +void CDMRSlot::writeJSONBER() +{ + if (m_bitsCount >= BER_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "DMR"; + json["slot"] = int(m_slotNo); + + json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); + + WriteJSON("BER", json); + + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + } +} + +void CDMRSlot::writeJSONText(const unsigned char* text) +{ + assert(text != NULL); + + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "DMR"; + json["slot"] = int(m_slotNo); + + json["value"] = std::string((char*)text); + + WriteJSON("Text", json); +} + void CDMRSlot::writeJSONRF(const char* action) { assert(action != NULL); diff --git a/DMRSlot.h b/DMRSlot.h index 2e940c2..fcdbe1f 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -111,7 +111,11 @@ private: unsigned char m_maxRSSI; unsigned char m_minRSSI; unsigned int m_aveRSSI; + unsigned int m_rssiCountTotal; + unsigned int m_rssiAccum; unsigned int m_rssiCount; + unsigned int m_bitErrsAccum; + unsigned int m_bitsCount; bool m_enabled; FILE* m_fp; @@ -161,6 +165,10 @@ private: static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP, ACTIVITY_TYPE type = ACTIVITY_NONE); + void writeJSONRSSI(); + void writeJSONBER(); + void writeJSONText(const unsigned char* text); + void writeJSONRF(const char* action); void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames); From 74376d3b8cce03d1c14e306fd0c2e2bbe90a2b90 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 11 Jun 2023 13:23:11 +0100 Subject: [PATCH 11/29] Add JSON RSSI and BER reporting to D-Star. --- DStarControl.cpp | 107 +++++++++++++++++++++++++++++++++++++++-------- DStarControl.h | 8 ++++ 2 files changed, 98 insertions(+), 17 deletions(-) diff --git a/DStarControl.cpp b/DStarControl.cpp index 4f13e4d..2fa05cc 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -26,6 +26,9 @@ const unsigned int MAX_SYNC_BIT_ERRORS = 2U; const unsigned int FAST_DATA_BEEP_GRACE_FRAMES = 6U; +const unsigned int RSSI_COUNT = 3U * 21U; // 3 * 420ms = 1260ms +const unsigned int BER_COUNT = 63U * 48U; // 63 * 20ms = 1260ms + bool CallsignCompare(const std::string& arg, const unsigned char* my) { for (unsigned int i = 0U; i < (DSTAR_LONG_CALLSIGN_LENGTH - 1U); i++) { @@ -82,7 +85,11 @@ m_rssi(0U), m_maxRSSI(0U), m_minRSSI(0U), m_aveRSSI(0U), +m_rssiCountTotal(0U), +m_rssiAccum(0U), m_rssiCount(0U), +m_bitErrsAccum(0U), +m_bitsCount(0U), m_enabled(true), m_fp(NULL), m_rfVoiceSyncData(NULL), @@ -226,8 +233,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_rfHeader.getYourCall(your); if (m_rssi != 0U) { - LogMessage("D-Star, transmission lost from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("D-Star, transmission lost from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("lost", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("D-Star, transmission lost from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("lost", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -275,7 +282,9 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } // Have we got RSSI bytes on the end of D-Star data? @@ -298,7 +307,9 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } if (type == TAG_HEADER) { @@ -368,6 +379,9 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; if (m_duplex) { @@ -432,8 +446,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_rfHeader.getYourCall(your); if (m_rssi != 0U) { - LogMessage("D-Star, received RF end of transmission from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("D-Star, received RF end of transmission from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("D-Star, received RF end of transmission from %8.8s/%4.4s to %8.8s, %.1f seconds, BER: %.1f%%", my1, my2, your, float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("end", float(m_rfFrames) / 50.0F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -471,12 +485,16 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (!m_rfHeader.isDataPacket()) { errors = maybeFixupVoiceFrame(data, len, 1U, "RF", m_rfN, m_duplex, m_rfVoiceSyncData, m_rfVoiceSyncDataLen, m_rfNextFrameIsFastData, m_rfSkipDTMFBlankingFrames); m_display->writeDStarBER(float(errors) / 0.48F); - m_rfErrs += errors; + m_bitErrsAccum += errors; + m_rfErrs += errors; } - m_rfBits += 48U; + m_bitsCount += 48U; + m_rfBits += 48U; m_rfFrames++; + writeJSONBER(); + if (m_net) { if (m_rfN == 1U) writeNetworkDataRF(m_rfVoiceSyncData, 0U, false); @@ -573,7 +591,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; - m_rssiCount = 1U; + m_rssiCountTotal = 1U; if (m_duplex) { unsigned char start[DSTAR_HEADER_LENGTH_BYTES + 1U]; @@ -606,10 +624,14 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) unsigned int errors = 0U; if (!m_rfHeader.isDataPacket()) { errors = maybeFixupVoiceFrame(data, len, 1U, "RF", m_rfN, m_duplex, m_rfVoiceSyncData, m_rfVoiceSyncDataLen, m_rfNextFrameIsFastData, m_rfSkipDTMFBlankingFrames); - m_rfErrs += errors; + m_bitErrsAccum += errors; + m_rfErrs += errors; } - m_rfBits += 48U; + m_bitsCount += 48U; + m_rfBits += 48U; + + writeJSONBER(); if (m_net) writeNetworkDataRF(data, errors, false); @@ -1209,14 +1231,14 @@ void CDStarControl::sendAck() if (m_ackMessage == DSTAR_ACK_RSSI && m_rssi != 0) { if (status == LS_LINKED_DEXTRA || status == LS_LINKED_DPLUS || status == LS_LINKED_DCS || status == LS_LINKED_CCS || status == LS_LINKED_LOOPBACK) { CUtils::removeChar(reflector, ' ');//remove space from reflector so all nicely fits onto 20 chars in case rssi < 99dBm - ::sprintf(text, "%-8.8s %.1f%% -%udBm ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); + ::sprintf(text, "%-8.8s %.1f%% -%udBm ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCountTotal); } else { - ::sprintf(text, "BER:%.1f%% -%udBm ", float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); + ::sprintf(text, "BER:%.1f%% -%udBm ", float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCountTotal); } } else if (m_ackMessage == DSTAR_ACK_SMETER && m_rssi != 0) { unsigned int signal, plus; char signalText[15U]; - CSMeter::getSignal(m_aveRSSI / m_rssiCount, signal, plus); + CSMeter::getSignal(m_aveRSSI / m_rssiCountTotal, signal, plus); if (plus != 0U) ::sprintf(signalText, "S%u+%02u", signal, plus); else @@ -1274,14 +1296,14 @@ void CDStarControl::sendError() if (m_ackMessage == DSTAR_ACK_RSSI && m_rssi != 0) { if (status == LS_LINKED_DEXTRA || status == LS_LINKED_DPLUS || status == LS_LINKED_DCS || status == LS_LINKED_CCS || status == LS_LINKED_LOOPBACK) { CUtils::removeChar(reflector, ' ');//remove space from reflector so all nicely fits onto 20 chars in case rssi < 99dBm - ::sprintf(text, "%-8.8s %.1f%% -%udBm ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); + ::sprintf(text, "%-8.8s %.1f%% -%udBm ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCountTotal); } else { - ::sprintf(text, "BER:%.1f%% -%udBm ", float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); + ::sprintf(text, "BER:%.1f%% -%udBm ", float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCountTotal); } } else if (m_ackMessage == DSTAR_ACK_SMETER && m_rssi != 0) { unsigned int signal, plus; char signalText[15U]; - CSMeter::getSignal(m_aveRSSI / m_rssiCount, signal, plus); + CSMeter::getSignal(m_aveRSSI / m_rssiCountTotal, signal, plus); if (plus != 0U) ::sprintf(signalText, "S%u+%02u", signal, plus); else @@ -1338,6 +1360,57 @@ void CDStarControl::enable(bool enabled) m_enabled = enabled; } +void CDStarControl::writeJSONRSSI() +{ + m_rssiAccum += m_rssi; + m_rssiCountTotal++; + + if (m_rssiCountTotal >= RSSI_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "D-Star"; + + json["value"] = -int(m_rssiAccum / m_rssiCountTotal); + + WriteJSON("RSSI", json); + + m_rssiAccum = 0U; + m_rssiCountTotal = 0U; + } +} + +void CDStarControl::writeJSONBER() +{ + if (m_bitsCount >= BER_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "D-STar"; + + json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); + + WriteJSON("BER", json); + + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + } +} + +void CDStarControl::writeJSONText(const unsigned char* text) +{ + assert(text != NULL); + + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "D-Star"; + + json["value"] = std::string((char*)text); + + WriteJSON("Text", json); +} + void CDStarControl::writeJSONRF(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your) { assert(action != NULL); diff --git a/DStarControl.h b/DStarControl.h index dc6202f..9f24b78 100644 --- a/DStarControl.h +++ b/DStarControl.h @@ -96,7 +96,11 @@ private: unsigned char m_maxRSSI; unsigned char m_minRSSI; unsigned int m_aveRSSI; + unsigned int m_rssiCountTotal; + unsigned int m_rssiAccum; unsigned int m_rssiCount; + unsigned int m_bitErrsAccum; + unsigned int m_bitsCount; bool m_enabled; FILE* m_fp; unsigned char* m_rfVoiceSyncData; @@ -135,6 +139,10 @@ private: void writeEndRF(); void writeEndNet(); + void writeJSONRSSI(); + void writeJSONBER(); + void writeJSONText(const unsigned char* text); + void writeJSONRF(const char* action, const unsigned char* my1, const unsigned char* my2, const unsigned char* your); void writeJSONRF(const char* action, float duration, float ber); void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); From fb5e5b5fa13f65d09e402a6f75bc2423432bb6dd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 11 Jun 2023 14:39:18 +0100 Subject: [PATCH 12/29] Add JSON RSSI and BER messages to YSF. --- DStarControl.cpp | 2 +- YSFControl.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++----- YSFControl.h | 7 ++++ 3 files changed, 97 insertions(+), 10 deletions(-) diff --git a/DStarControl.cpp b/DStarControl.cpp index 2fa05cc..a8a9670 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -1386,7 +1386,7 @@ void CDStarControl::writeJSONBER() nlohmann::json json; json["timestamp"] = CUtils::createTimestamp(); - json["mode"] = "D-STar"; + json["mode"] = "D-Star"; json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); diff --git a/YSFControl.cpp b/YSFControl.cpp index 7492707..c8f4fed 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -21,6 +21,9 @@ #include #include +const unsigned int RSSI_COUNT = 13U; // 13 * 100ms = 1300ms +const unsigned int BER_COUNT = 13U; // 13 * 100ms = 1300ms + // #define DUMP_YSF CYSFControl::CYSFControl(const std::string& callsign, bool selfOnly, CYSFNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool lowDeviation, bool remoteGateway, CRSSIInterpolator* rssiMapper) : @@ -59,7 +62,11 @@ m_rssi(0U), m_maxRSSI(0U), m_minRSSI(0U), m_aveRSSI(0U), +m_rssiCountTotal(0U), +m_rssiAccum(0U), m_rssiCount(0U), +m_bitsCount(0U), +m_bitErrsAccum(0U), m_enabled(true), m_fp(NULL) { @@ -108,8 +115,8 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) { if (m_rssi != 0U) { - LogMessage("YSF, transmission lost from %10.10s to %10.10s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, m_rfDest, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("YSF, transmission lost from %10.10s to %10.10s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, m_rfDest, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("lost", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("YSF, transmission lost from %10.10s to %10.10s, %.1f seconds, BER: %.1f%%", m_rfSource, m_rfDest, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("lost", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -152,7 +159,9 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } CYSFFICH fich; @@ -255,7 +264,14 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + #if defined(DUMP_YSF) openFile(); #endif @@ -322,8 +338,8 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) m_rfFrames++; if (m_rssi != 0U) { - LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -361,6 +377,7 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) m_rfBits += 720U; m_display->writeFusionBER(float(errors) / 7.2F); LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 7.2F); + writeJSONBER(720U, errors); } fich.encode(data + 2U); @@ -429,7 +446,14 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + #if defined(DUMP_YSF) openFile(); #endif @@ -496,8 +520,8 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_rfFrames++; if (m_rssi != 0U) { - LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, BER: %.1f%%", m_rfSource, dgid, float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("end", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -531,6 +555,7 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_rfBits += 235U; m_display->writeFusionBER(float(errors) / 2.35F); LogDebug("YSF, V/D Mode 1, seq %u, AMBE FEC %u/235 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 2.35F); + writeJSONBER(235U, errors); } break; @@ -541,6 +566,7 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_rfBits += 405U; m_display->writeFusionBER(float(errors) / 4.05F); LogDebug("YSF, V/D Mode 2, seq %u, Repetition FEC %u/405 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 4.05F); + writeJSONBER(405U, errors); } break; @@ -624,7 +650,14 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + #if defined(DUMP_YSF) openFile(); #endif @@ -735,7 +768,14 @@ bool CYSFControl::processFRData(bool valid, unsigned char *data) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + #if defined(DUMP_YSF) openFile(); #endif @@ -801,8 +841,8 @@ bool CYSFControl::processFRData(bool valid, unsigned char *data) m_rfFrames++; if (m_rssi != 0U) { - LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", float(m_rfFrames) / 10.0F, 0.0F, m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds, RSSI: -%u/-%u/-%u dBm", m_rfSource, dgid, float(m_rfFrames) / 10.0F, m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 10.0F, 0.0F, m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("YSF, received RF end of transmission from %10.10s to DG-ID %u, %.1f seconds", m_rfSource, dgid, float(m_rfFrames) / 10.0F); writeJSONRF("end", float(m_rfFrames) / 10.0F, 0.0F); @@ -1275,6 +1315,46 @@ void CYSFControl::writeJSONRF(const char* action, float duration, float ber) WriteJSON("YSF", json); } +void CYSFControl::writeJSONRSSI() +{ + m_rssiAccum += m_rssi; + m_rssiCount++; + + if (m_rssiCount >= RSSI_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "YSF"; + + json["value"] = -int(m_rssiAccum / m_rssiCount); + + WriteJSON("RSSI", json); + + m_rssiAccum = 0U; + m_rssiCount = 0U; + } +} + +void CYSFControl::writeJSONBER(unsigned int bits, unsigned int errs) +{ + m_bitsCount += bits; + m_bitErrsAccum += errs; + + if (m_bitsCount >= (BER_COUNT * bits)) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "YSF"; + + json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); + + WriteJSON("BER", json); + + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + } +} + void CYSFControl::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); diff --git a/YSFControl.h b/YSFControl.h index fba0378..2ff85c4 100644 --- a/YSFControl.h +++ b/YSFControl.h @@ -86,7 +86,11 @@ private: unsigned char m_maxRSSI; unsigned char m_minRSSI; unsigned int m_aveRSSI; + unsigned int m_rssiCountTotal; + unsigned int m_rssiAccum; unsigned int m_rssiCount; + unsigned int m_bitsCount; + unsigned int m_bitErrsAccum; bool m_enabled; FILE* m_fp; @@ -102,6 +106,9 @@ private: void writeEndRF(); void writeEndNet(); + void writeJSONRSSI(); + void writeJSONBER(unsigned int bits, unsigned int errs); + void writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid); void writeJSONRF(const char* action, float duration, float ber); void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); From c52ae588162dca70bc93fd416261291efcbface9 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 11 Jun 2023 14:58:29 +0100 Subject: [PATCH 13/29] Add JSON RSSI and BER to P25. --- P25Control.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++---- P25Control.h | 7 +++++ YSFControl.cpp | 60 +++++++++++++++++++++---------------------- 3 files changed, 102 insertions(+), 35 deletions(-) diff --git a/P25Control.cpp b/P25Control.cpp index 0e69298..e7689ad 100644 --- a/P25Control.cpp +++ b/P25Control.cpp @@ -31,6 +31,9 @@ #include #include +const unsigned int RSSI_COUNT = 7U; // 7 * 180ms = 1260ms +const unsigned int BER_COUNT = 7U * 1233U; // 7 * 180ms = 1260ms + // #define DUMP_P25 const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -79,7 +82,11 @@ m_rssi(0U), m_maxRSSI(0U), m_minRSSI(0U), m_aveRSSI(0U), +m_rssiCountTotal(0U), +m_rssiAccum(0U), m_rssiCount(0U), +m_bitsCount(0U), +m_bitErrsAccum(0U), m_enabled(true), m_fp(NULL) { @@ -128,8 +135,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) std::string source = m_lookup->find(srcId); if (m_rssi != 0U) { - LogMessage("P25, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("P25, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("lost", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("P25, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("lost", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -217,7 +224,9 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } if (duid == P25_DUID_LDU1) { @@ -266,8 +275,14 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + createRFHeader(); writeNetwork(data + 2U, P25_DUID_HEADER, false); } else if (m_rfState == RS_RF_AUDIO) { @@ -298,6 +313,10 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_rfFrames++; m_lastDUID = duid; + m_bitsCount += 1233U; + m_bitErrsAccum += errors; + writeJSONBER(); + // Add busy bits addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); @@ -344,6 +363,10 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_rfFrames++; m_lastDUID = duid; + m_bitsCount += 1233U; + m_bitErrsAccum += errors; + writeJSONBER(); + // Add busy bits addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); @@ -469,8 +492,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_lastDUID = duid; if (m_rssi != 0U) { - LogMessage("P25, received RF end of voice transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("P25, received RF end of voice transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("P25, received RF end of voice transmission from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("end", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -1213,6 +1236,43 @@ void CP25Control::enable(bool enabled) m_enabled = enabled; } +void CP25Control::writeJSONRSSI() +{ + m_rssiAccum += m_rssi; + m_rssiCount++; + + if (m_rssiCount >= RSSI_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "P25"; + + json["value"] = -int(m_rssiAccum / m_rssiCount); + + WriteJSON("RSSI", json); + + m_rssiAccum = 0U; + m_rssiCount = 0U; + } +} + +void CP25Control::writeJSONBER() +{ + if (m_bitsCount >= BER_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "P25"; + + json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); + + WriteJSON("BER", json); + + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + } +} + void CP25Control::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); diff --git a/P25Control.h b/P25Control.h index de4d917..7d4814e 100644 --- a/P25Control.h +++ b/P25Control.h @@ -93,7 +93,11 @@ private: unsigned char m_maxRSSI; unsigned char m_minRSSI; unsigned int m_aveRSSI; + unsigned int m_rssiCountTotal; + unsigned int m_rssiAccum; unsigned int m_rssiCount; + unsigned int m_bitsCount; + unsigned int m_bitErrsAccum; bool m_enabled; FILE* m_fp; @@ -121,6 +125,9 @@ private: bool writeFile(const unsigned char* data, unsigned char length); void closeFile(); + void writeJSONRSSI(); + void writeJSONBER(); + void writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); void writeJSONRF(const char* action, float duration, float ber); void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); diff --git a/YSFControl.cpp b/YSFControl.cpp index c8f4fed..5816e62 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -265,7 +265,7 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; m_rssiCountTotal = 1U; - + m_rssiAccum = m_rssi; m_rssiCount = 1U; @@ -1286,35 +1286,6 @@ void CYSFControl::enable(bool enabled) m_enabled = enabled; } -void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid) -{ - assert(action != NULL); - assert(mode != NULL); - assert(source != NULL); - - nlohmann::json json; - - writeJSONRF(json, action, source, dgid); - - json["mode"] = mode; - - WriteJSON("YSF", json); -} - -void CYSFControl::writeJSONRF(const char* action, float duration, float ber) -{ - assert(action != NULL); - - nlohmann::json json; - - writeJSONRF(json, action); - - json["duration"] = duration; - json["ber"] = ber; - - WriteJSON("YSF", json); -} - void CYSFControl::writeJSONRSSI() { m_rssiAccum += m_rssi; @@ -1355,6 +1326,35 @@ void CYSFControl::writeJSONBER(unsigned int bits, unsigned int errs) } } +void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsigned char* source, unsigned char dgid) +{ + assert(action != NULL); + assert(mode != NULL); + assert(source != NULL); + + nlohmann::json json; + + writeJSONRF(json, action, source, dgid); + + json["mode"] = mode; + + WriteJSON("YSF", json); +} + +void CYSFControl::writeJSONRF(const char* action, float duration, float ber) +{ + assert(action != NULL); + + nlohmann::json json; + + writeJSONRF(json, action); + + json["duration"] = duration; + json["ber"] = ber; + + WriteJSON("YSF", json); +} + void CYSFControl::writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI) { assert(action != NULL); From e2ef49209bd4ac637b870016e7e0f1d9007a3f30 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 11 Jun 2023 15:09:58 +0100 Subject: [PATCH 14/29] Add JSON RSSI and BER to NXDN. --- NXDNControl.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++--- NXDNControl.h | 7 +++++ 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/NXDNControl.cpp b/NXDNControl.cpp index 7417571..beac8a6 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -34,6 +34,9 @@ const unsigned char SCRAMBLER[] = { // #define DUMP_NXDN +const unsigned int RSSI_COUNT = 28U; // 28 * 40ms = 1120ms +const unsigned int BER_COUNT = 28U; // 28 * 40ms = 1120ms + const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) @@ -70,7 +73,11 @@ m_rssi(0U), m_maxRSSI(0U), m_minRSSI(0U), m_aveRSSI(0U), +m_rssiCountTotal(0U), +m_rssiAccum(0U), m_rssiCount(0U), +m_bitsCount(0U), +m_bitErrsAccum(0U), m_enabled(true), m_fp(NULL) { @@ -99,8 +106,8 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) std::string source = m_lookup->find(srcId); if (m_rssi != 0U) { - LogMessage("NXDN, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("NXDN, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("lost", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("NXDN, transmission lost from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("lost", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -141,7 +148,9 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } scrambler(data + 2U); @@ -274,8 +283,8 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne m_rfFrames++; if (m_rssi != 0U) { - LogMessage("NXDN, received RF end of transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("end", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("NXDN, received RF end of transmission from %s to %s%u, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("end", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("NXDN, received RF end of transmission from %s to %s%u, %.1f seconds, BER: %.1f%%", source.c_str(), grp ? "TG " : "", dstId, float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("end", float(m_rfFrames) / 12.5F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -285,12 +294,22 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne m_rfFrames = 0U; m_rfErrs = 0U; m_rfBits = 1U; + m_rfTimeoutTimer.start(); + m_rfState = RS_RF_AUDIO; + m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + #if defined(DUMP_NXDN) openFile(); #endif @@ -391,13 +410,22 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne m_rfFrames = 0U; m_rfErrs = 0U; m_rfBits = 1U; + m_rfTimeoutTimer.start(); + m_rfState = RS_RF_AUDIO; m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + #if defined(DUMP_NXDN) openFile(); #endif @@ -493,6 +521,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne errors += ambe.regenerateYSFDN(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 27U); m_rfErrs += errors; m_rfBits += 188U; + writeJSONBER(188U, errors); m_display->writeNXDNBER(float(errors) / 1.88F); LogDebug("NXDN, AMBE FEC %u/188 (%.1f%%)", errors, float(errors) / 1.88F); @@ -512,6 +541,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne errors += ambe.regenerateYSFDN(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 27U); m_rfErrs += errors; m_rfBits += 94U; + writeJSONBER(94U, errors); m_display->writeNXDNBER(float(errors) / 0.94F); LogDebug("NXDN, AMBE FEC %u/94 (%.1f%%)", errors, float(errors) / 0.94F); @@ -524,6 +554,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne errors += ambe.regenerateYSFDN(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 9U); m_rfErrs += errors; m_rfBits += 94U; + writeJSONBER(94U, errors); m_display->writeNXDNBER(float(errors) / 0.94F); LogDebug("NXDN, AMBE FEC %u/94 (%.1f%%)", errors, float(errors) / 0.94F); @@ -1159,6 +1190,46 @@ void CNXDNControl::enable(bool enabled) m_enabled = enabled; } +void CNXDNControl::writeJSONRSSI() +{ + m_rssiAccum += m_rssi; + m_rssiCount++; + + if (m_rssiCount >= RSSI_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "NXDN"; + + json["value"] = -int(m_rssiAccum / m_rssiCount); + + WriteJSON("RSSI", json); + + m_rssiAccum = 0U; + m_rssiCount = 0U; + } +} + +void CNXDNControl::writeJSONBER(unsigned int bits, unsigned int errs) +{ + m_bitErrsAccum += errs; + m_bitsCount += bits; + + if (m_bitsCount >= (BER_COUNT * bits)) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "NXDN"; + + json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); + + WriteJSON("BER", json); + + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + } +} + void CNXDNControl::writeJSONRF(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId) { assert(action != NULL); diff --git a/NXDNControl.h b/NXDNControl.h index 9925000..5b538d1 100644 --- a/NXDNControl.h +++ b/NXDNControl.h @@ -82,7 +82,11 @@ private: unsigned char m_maxRSSI; unsigned char m_minRSSI; unsigned int m_aveRSSI; + unsigned int m_rssiCountTotal; + unsigned int m_rssiAccum; unsigned int m_rssiCount; + unsigned int m_bitsCount; + unsigned int m_bitErrsAccum; bool m_enabled; FILE* m_fp; @@ -103,6 +107,9 @@ private: bool writeFile(const unsigned char* data); void closeFile(); + void writeJSONRSSI(); + void writeJSONBER(unsigned int bits, unsigned int errs); + void writeJSONRF(const char* action, unsigned short srcId, const std::string& srcInfo, bool grp, unsigned short dstId); void writeJSONRF(const char* action, float duration, float ber); void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); From 8bcd02b468cfd870735de0553f9fc39f0ec2b907 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 11 Jun 2023 15:34:38 +0100 Subject: [PATCH 15/29] Add JSON RSSI and BER reporting to M17. --- M17Control.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++++---- M17Control.h | 8 +++++ 2 files changed, 97 insertions(+), 7 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index fa2e3a8..75fc13f 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -50,6 +50,9 @@ const unsigned char SCRAMBLER[] = { 0x5DU, 0x0CU, 0xC8U, 0x52U, 0x43U, 0x91U, 0x1DU, 0xF8U, 0x6EU, 0x68U, 0x2FU, 0x35U, 0xDAU, 0x14U, 0xEAU, 0xCDU, 0x76U, 0x19U, 0x8DU, 0xD5U, 0x80U, 0xD1U, 0x33U, 0x87U, 0x13U, 0x57U, 0x18U, 0x2DU, 0x29U, 0x78U, 0xC3U}; +const unsigned int RSSI_COUNT = 28U; // 28 * 40ms = 1120ms +const unsigned int BER_COUNT = 28U * 272U; // 28 * 40ms = 1120ms + // #define DUMP_M17 const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; @@ -91,7 +94,11 @@ m_rssi(0U), m_maxRSSI(0U), m_minRSSI(0U), m_aveRSSI(0U), +m_rssiCountTotal(0U), +m_rssiAccum(0U), m_rssiCount(0U), +m_bitsCount(0U), +m_bitErrsAccum(0U), m_enabled(true), m_fp(NULL) { @@ -114,8 +121,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (type == TAG_LOST && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA_AUDIO)) { if (m_rssi != 0U) { - LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); - writeJSONRF("lost", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); + writeJSONRF("lost", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } else { LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeJSONRF("lost", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); @@ -159,7 +166,9 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI += m_rssi; - m_rssiCount++; + m_rssiCountTotal++; + + writeJSONRSSI(); } unsigned char temp[M17_FRAME_LENGTH_BYTES]; @@ -190,13 +199,22 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rfFrames = 0U; m_rfErrs = ber; m_rfBits = 368U; + m_rfCollectingLSF.reset(); m_rfCollectedLSF.reset(); m_rfTimeoutTimer.start(); + m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; - m_rssiCount = 1U; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; + m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + m_rfLSFn = 0U; m_rfLSFCount = 0U; @@ -244,13 +262,22 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rfFrames = 0U; m_rfErrs = 0U; m_rfBits = 1U; + m_rfCollectingLSF.reset(); m_rfCollectedLSF.reset(); m_rfTimeoutTimer.start(); + m_minRSSI = m_rssi; m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; - m_rssiCount = 1U; + m_rssiCountTotal = 1U; + + m_rssiAccum = m_rssi; + m_rssiCount = 1U; + + m_bitErrsAccum = 0U; + m_bitsCount = 0U; + m_rfLSFCount = 0U; #if defined(DUMP_M17) @@ -316,6 +343,10 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rfBits += 272U; m_rfErrs += errors; + m_bitErrsAccum += errors; + m_bitsCount += 272U; + writeJSONBER(); + float ber = float(m_rfErrs) / float(m_rfBits); m_display->writeM17BER(ber); @@ -422,11 +453,11 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) } if (m_rssi != 0U) { - LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); writeJSONRF("end", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); } else { LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%", m_source.c_str(), m_dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); - writeJSONRF("end", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); + writeJSONRF("end", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCountTotal); } writeEndRF(); @@ -925,6 +956,57 @@ void CM17Control::enable(bool enabled) m_enabled = enabled; } +void CM17Control::writeJSONRSSI() +{ + m_rssiAccum += m_rssi; + m_rssiCountTotal++; + + if (m_rssiCountTotal >= RSSI_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "M17"; + + json["value"] = -int(m_rssiAccum / m_rssiCountTotal); + + WriteJSON("RSSI", json); + + m_rssiAccum = 0U; + m_rssiCountTotal = 0U; + } +} + +void CM17Control::writeJSONBER() +{ + if (m_bitsCount >= BER_COUNT) { + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "M17"; + + json["value"] = float(m_bitErrsAccum * 100U) / float(m_bitsCount); + + WriteJSON("BER", json); + + m_bitErrsAccum = 0U; + m_bitsCount = 1U; + } +} + +void CM17Control::writeJSONText(const unsigned char* text) +{ + assert(text != NULL); + + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["mode"] = "M17"; + + json["value"] = std::string((char*)text); + + WriteJSON("Text", json); +} + void CM17Control::writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest) { assert(action != NULL); diff --git a/M17Control.h b/M17Control.h index 731f987..6cdf45a 100644 --- a/M17Control.h +++ b/M17Control.h @@ -83,7 +83,11 @@ private: unsigned char m_maxRSSI; unsigned char m_minRSSI; unsigned int m_aveRSSI; + unsigned int m_rssiCountTotal; + unsigned int m_rssiAccum; unsigned int m_rssiCount; + unsigned int m_bitsCount; + unsigned int m_bitErrsAccum; bool m_enabled; FILE* m_fp; @@ -105,6 +109,10 @@ private: void writeEndRF(); void writeEndNet(); + void writeJSONRSSI(); + void writeJSONBER(); + void writeJSONText(const unsigned char* text); + void writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest); void writeJSONRF(const char* action, float duration, float ber); void writeJSONRF(const char* action, float duration, float ber, unsigned char minRSSI, unsigned char maxRSSI, unsigned int aveRSSI); From 3a7d087628dd6df260e450fb387e39c594b66667 Mon Sep 17 00:00:00 2001 From: Chipster Date: Sun, 11 Jun 2023 10:35:39 -0500 Subject: [PATCH 16/29] Removed extranneous `m_display.startscrolldiagleft` func. --- OLED.cpp | 6 +----- Version.h | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index 7a823b1..3955f0a 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -258,10 +258,6 @@ void COLED::setIdleInt() m_display.clearDisplay(); OLED_statusbar(); - if (m_displayScroll && m_displayLogoScreensaver) - m_display.startscrolldiagleft(0x00,0x0f); //the MMDVM logo scrolls the whole screen - m_display.display(); - unsigned char info[100U]; CNetworkInfo* m_network; @@ -325,7 +321,7 @@ void COLED::setIdleInt() } if (m_displayScroll && m_displayLogoScreensaver) - m_display.startscrolldiagleft(0x00, 0x0f); // the MMDVM logo scrolls the whole screen + m_display.startscrolldiagleft(0x00,0x0f); // the MMDVM logo scrolls the whole screen m_display.display(); } diff --git a/Version.h b/Version.h index f5c6244..75f257c 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20220523"; +const char* VERSION = "20230611"; #endif From dca4301b6eb85ac6c5e3237426bce325e3d2217e Mon Sep 17 00:00:00 2001 From: Chipster Date: Sun, 11 Jun 2023 10:35:39 -0500 Subject: [PATCH 17/29] Removed extranneous `m_display.startscrolldiagleft` func. --- OLED.cpp | 6 +----- Version.h | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index 7a823b1..3955f0a 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -258,10 +258,6 @@ void COLED::setIdleInt() m_display.clearDisplay(); OLED_statusbar(); - if (m_displayScroll && m_displayLogoScreensaver) - m_display.startscrolldiagleft(0x00,0x0f); //the MMDVM logo scrolls the whole screen - m_display.display(); - unsigned char info[100U]; CNetworkInfo* m_network; @@ -325,7 +321,7 @@ void COLED::setIdleInt() } if (m_displayScroll && m_displayLogoScreensaver) - m_display.startscrolldiagleft(0x00, 0x0f); // the MMDVM logo scrolls the whole screen + m_display.startscrolldiagleft(0x00,0x0f); // the MMDVM logo scrolls the whole screen m_display.display(); } diff --git a/Version.h b/Version.h index f5c6244..75f257c 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20220523"; +const char* VERSION = "20230611"; #endif From 8837696b23a27c4320d882931711bbb7a94262ee Mon Sep 17 00:00:00 2001 From: Chipster Date: Sun, 11 Jun 2023 14:14:39 -0500 Subject: [PATCH 18/29] Fix version # per G4KLX, fix OLED IP spacing in idle mode, improve auto-ap stats in OLED --- OLED.cpp | 8 ++++---- Version.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index 3955f0a..2d0f7b7 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -285,7 +285,7 @@ void COLED::setIdleInt() } // Read ssid value from /etc/hostapd.conf if it exists... std::string ssid; - std::ifstream configFile("/etc/hostapd.conf"); + std::ifstream configFile("/etc/hostapd/hostapd.conf"); if (configFile.is_open()) { std::string line; while (std::getline(configFile, line)) { @@ -306,10 +306,10 @@ void COLED::setIdleInt() m_display.setCursor(0, OLED_LINE3); m_display.setTextSize(1); m_display.printf("Auto-AP Running..."); - m_display.setCursor(0, OLED_LINE4); + m_display.setCursor(0, OLED_LINE5); m_display.setTextSize(1); m_display.printf("SSID: %s", ssid.c_str()); - m_display.setCursor(0, OLED_LINE5); + m_display.setCursor(0, OLED_LINE6); m_display.setTextSize(1); m_display.printf("IP: %s", m_ipaddress.c_str()); } else { // Connected to network - no Auto-AP mode; normal display layout... @@ -317,7 +317,7 @@ void COLED::setIdleInt() m_display.setTextSize(1); m_display.print(" -IDLE-"); m_display.setCursor(0, OLED_LINE5); - m_display.printf(" %s", m_ipaddress.c_str()); + m_display.printf("%s", m_ipaddress.c_str()); } if (m_displayScroll && m_displayLogoScreensaver) diff --git a/Version.h b/Version.h index 75f257c..f5c6244 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20230611"; +const char* VERSION = "20220523"; #endif From 216bfaa7bb89187a7480570ed8255227e7b94a76 Mon Sep 17 00:00:00 2001 From: Chipster Date: Sun, 11 Jun 2023 14:14:39 -0500 Subject: [PATCH 19/29] Fix version # per G4KLX, fix OLED IP spacing in idle mode, improve auto-ap stats in OLED --- OLED.cpp | 8 ++++---- Version.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index 3955f0a..2d0f7b7 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -285,7 +285,7 @@ void COLED::setIdleInt() } // Read ssid value from /etc/hostapd.conf if it exists... std::string ssid; - std::ifstream configFile("/etc/hostapd.conf"); + std::ifstream configFile("/etc/hostapd/hostapd.conf"); if (configFile.is_open()) { std::string line; while (std::getline(configFile, line)) { @@ -306,10 +306,10 @@ void COLED::setIdleInt() m_display.setCursor(0, OLED_LINE3); m_display.setTextSize(1); m_display.printf("Auto-AP Running..."); - m_display.setCursor(0, OLED_LINE4); + m_display.setCursor(0, OLED_LINE5); m_display.setTextSize(1); m_display.printf("SSID: %s", ssid.c_str()); - m_display.setCursor(0, OLED_LINE5); + m_display.setCursor(0, OLED_LINE6); m_display.setTextSize(1); m_display.printf("IP: %s", m_ipaddress.c_str()); } else { // Connected to network - no Auto-AP mode; normal display layout... @@ -317,7 +317,7 @@ void COLED::setIdleInt() m_display.setTextSize(1); m_display.print(" -IDLE-"); m_display.setCursor(0, OLED_LINE5); - m_display.printf(" %s", m_ipaddress.c_str()); + m_display.printf("%s", m_ipaddress.c_str()); } if (m_displayScroll && m_displayLogoScreensaver) diff --git a/Version.h b/Version.h index 75f257c..f5c6244 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20230611"; +const char* VERSION = "20220523"; #endif From a0f1005f66432743f79d06f03896be97b8bc6769 Mon Sep 17 00:00:00 2001 From: Chipster Date: Wed, 14 Jun 2023 06:16:14 -0500 Subject: [PATCH 20/29] Fixed issue in `OLED.cpp` where display would not fully clear on idle when LogoScreensaver=0 --- OLED.cpp | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index 2d0f7b7..19ca09f 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -258,6 +258,9 @@ void COLED::setIdleInt() m_display.clearDisplay(); OLED_statusbar(); + if (m_displayScroll && m_displayLogoScreensaver) + m_display.startscrolldiagleft(0x00,0x0f); //the MMDVM logo scrolls the whole screen + unsigned char info[100U]; CNetworkInfo* m_network; @@ -303,26 +306,28 @@ void COLED::setIdleInt() ssid = "Unknown"; // `/etc/hostapd.conf` does not exist... } - m_display.setCursor(0, OLED_LINE3); - m_display.setTextSize(1); - m_display.printf("Auto-AP Running..."); - m_display.setCursor(0, OLED_LINE5); - m_display.setTextSize(1); - m_display.printf("SSID: %s", ssid.c_str()); - m_display.setCursor(0, OLED_LINE6); - m_display.setTextSize(1); - m_display.printf("IP: %s", m_ipaddress.c_str()); + if (m_displayLogoScreensaver) { + m_display.setCursor(0, OLED_LINE3); + m_display.setTextSize(1); + m_display.printf("Auto-AP Running..."); + m_display.setCursor(0, OLED_LINE5); + m_display.setTextSize(1); + m_display.printf("SSID: %s", ssid.c_str()); + m_display.setCursor(0, OLED_LINE6); + m_display.setTextSize(1); + m_display.printf("IP: %s", m_ipaddress.c_str()); + } } else { // Connected to network - no Auto-AP mode; normal display layout... - m_display.setCursor(0,OLED_LINE3); - m_display.setTextSize(1); - m_display.print(" -IDLE-"); - m_display.setCursor(0, OLED_LINE5); - m_display.printf("%s", m_ipaddress.c_str()); + if (m_displayLogoScreensaver) { + m_display.setCursor(0,OLED_LINE3); + m_display.setTextSize(1); + m_display.print(" -IDLE-"); + m_display.setCursor(0, OLED_LINE5); + m_display.printf("%s", m_ipaddress.c_str()); + } } - - if (m_displayScroll && m_displayLogoScreensaver) - m_display.startscrolldiagleft(0x00,0x0f); // the MMDVM logo scrolls the whole screen m_display.display(); + } void COLED::setErrorInt(const char* text) From 9aecc6a228779f6c5f38d122cb5adb4c8367ef28 Mon Sep 17 00:00:00 2001 From: Chipster Date: Wed, 14 Jun 2023 06:16:14 -0500 Subject: [PATCH 21/29] Fixed issue in `OLED.cpp` where display would not fully clear on idle when LogoScreensaver=0 --- OLED.cpp | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index 2d0f7b7..19ca09f 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -258,6 +258,9 @@ void COLED::setIdleInt() m_display.clearDisplay(); OLED_statusbar(); + if (m_displayScroll && m_displayLogoScreensaver) + m_display.startscrolldiagleft(0x00,0x0f); //the MMDVM logo scrolls the whole screen + unsigned char info[100U]; CNetworkInfo* m_network; @@ -303,26 +306,28 @@ void COLED::setIdleInt() ssid = "Unknown"; // `/etc/hostapd.conf` does not exist... } - m_display.setCursor(0, OLED_LINE3); - m_display.setTextSize(1); - m_display.printf("Auto-AP Running..."); - m_display.setCursor(0, OLED_LINE5); - m_display.setTextSize(1); - m_display.printf("SSID: %s", ssid.c_str()); - m_display.setCursor(0, OLED_LINE6); - m_display.setTextSize(1); - m_display.printf("IP: %s", m_ipaddress.c_str()); + if (m_displayLogoScreensaver) { + m_display.setCursor(0, OLED_LINE3); + m_display.setTextSize(1); + m_display.printf("Auto-AP Running..."); + m_display.setCursor(0, OLED_LINE5); + m_display.setTextSize(1); + m_display.printf("SSID: %s", ssid.c_str()); + m_display.setCursor(0, OLED_LINE6); + m_display.setTextSize(1); + m_display.printf("IP: %s", m_ipaddress.c_str()); + } } else { // Connected to network - no Auto-AP mode; normal display layout... - m_display.setCursor(0,OLED_LINE3); - m_display.setTextSize(1); - m_display.print(" -IDLE-"); - m_display.setCursor(0, OLED_LINE5); - m_display.printf("%s", m_ipaddress.c_str()); + if (m_displayLogoScreensaver) { + m_display.setCursor(0,OLED_LINE3); + m_display.setTextSize(1); + m_display.print(" -IDLE-"); + m_display.setCursor(0, OLED_LINE5); + m_display.printf("%s", m_ipaddress.c_str()); + } } - - if (m_displayScroll && m_displayLogoScreensaver) - m_display.startscrolldiagleft(0x00,0x0f); // the MMDVM logo scrolls the whole screen m_display.display(); + } void COLED::setErrorInt(const char* text) From af21cef54dfa72ed4608de6e4599044d6eb210b6 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 11:35:16 +0100 Subject: [PATCH 22/29] Add interpretation of D-Star slow data text. --- DStarControl.cpp | 35 +++++++++++++----- DStarControl.h | 3 +- DStarSlowData.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++---- DStarSlowData.h | 9 +++-- 4 files changed, 118 insertions(+), 22 deletions(-) diff --git a/DStarControl.cpp b/DStarControl.cpp index be07f08..c0d727a 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -57,7 +57,8 @@ m_netHeader(), m_rfState(RS_RF_LISTENING), m_netState(RS_NET_IDLE), m_net(false), -m_slowData(), +m_rfSlowData(), +m_netSlowData(), m_rfN(0U), m_netN(0U), m_networkWatchdog(1000U, 0U, 1500U), @@ -363,6 +364,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_aveRSSI = m_rssi; m_rssiCount = 1U; + m_rfSlowData.start(); + if (m_duplex) { // Modify the header header.setRepeater(false); @@ -440,15 +443,17 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) } else if (m_rfState == RS_RF_LISTENING) { // The sync is regenerated by the modem so can do exact match if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) { - m_slowData.start(); + m_rfSlowData.start(); m_rfState = RS_RF_LATE_ENTRY; } return false; } else if (m_rfState == RS_RF_AUDIO) { // The sync is regenerated by the modem so can do exact match - if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) + if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) { + m_rfSlowData.start(); m_rfN = 0U; + } // Regenerate the sync and send the RSSI data to the display if (m_rfN == 0U) { @@ -466,6 +471,10 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_rfBits += 48U; m_rfFrames++; + const unsigned char* text = m_rfSlowData.addText(data + 1U); + if (text != NULL) + LogMessage("D-Star, slow data text = \"%s\"", text); + if (m_net) { if (m_rfN == 1U) writeNetworkDataRF(m_rfVoiceSyncData, 0U, false); @@ -484,11 +493,11 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) } else if (m_rfState == RS_RF_LATE_ENTRY) { // The sync is regenerated by the modem so can do exact match if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) { - m_slowData.reset(); + m_rfSlowData.reset(); return false; } - CDStarHeader* header = m_slowData.add(data + 1U); + CDStarHeader* header = m_rfSlowData.addHeader(data + 1U); if (header == NULL) return false; @@ -803,8 +812,14 @@ void CDStarControl::writeNetwork() m_netN = n; // Regenerate the sync - if (n == 0U) + if (n == 0U) { CSync::addDStarSync(data + 2U); + m_netSlowData.start(); + } + + const unsigned char* text = m_netSlowData.addText(data + 2U); + if (text != NULL) + LogMessage("D-Star, slow data text = \"%s\"", text); m_packetTimer.start(); m_netFrames++; @@ -1209,12 +1224,12 @@ void CDStarControl::sendAck() ::sprintf(text, "BER: %.1f%% ", float(m_rfErrs * 100U) / float(m_rfBits)); } - m_slowData.setText(text); + m_rfSlowData.setText(text); ::memcpy(data, DSTAR_NULL_FRAME_DATA_BYTES, DSTAR_FRAME_LENGTH_BYTES + 1U); for (unsigned int i = 0U; i < 19U; i++) { - m_slowData.get(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); + m_rfSlowData.getSlowData(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); writeQueueDataRF(data); } @@ -1274,12 +1289,12 @@ void CDStarControl::sendError() ::sprintf(text, "BER: %.1f%% ", float(m_rfErrs * 100U) / float(m_rfBits)); } - m_slowData.setText(text); + m_rfSlowData.setText(text); ::memcpy(data, DSTAR_NULL_FRAME_DATA_BYTES, DSTAR_FRAME_LENGTH_BYTES + 1U); for (unsigned int i = 0U; i < 19U; i++) { - m_slowData.get(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); + m_rfSlowData.getSlowData(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES); writeQueueDataRF(data); } diff --git a/DStarControl.h b/DStarControl.h index d899c68..61bf03f 100644 --- a/DStarControl.h +++ b/DStarControl.h @@ -69,7 +69,8 @@ private: RPT_RF_STATE m_rfState; RPT_NET_STATE m_netState; bool m_net; - CDStarSlowData m_slowData; + CDStarSlowData m_rfSlowData; + CDStarSlowData m_netSlowData; unsigned char m_rfN; unsigned char m_netN; CTimer m_networkWatchdog; diff --git a/DStarSlowData.cpp b/DStarSlowData.cpp index d33ca7e..5f11b70 100644 --- a/DStarSlowData.cpp +++ b/DStarSlowData.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2023 by Jonathan Naylor G4KLX * * 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 @@ -18,6 +18,7 @@ #include "DStarSlowData.h" #include "DStarDefines.h" +#include "Utils.h" #include "CRC.h" #include "Log.h" @@ -31,6 +32,7 @@ m_ptr(0U), m_buffer(NULL), m_text(NULL), m_textPtr(0U), +m_textBits(0x00U), m_state(SDD_FIRST) { m_header = new unsigned char[50U]; // DSTAR_HEADER_LENGTH_BYTES @@ -45,7 +47,7 @@ CDStarSlowData::~CDStarSlowData() delete[] m_text; } -CDStarHeader* CDStarSlowData::add(const unsigned char* data) +CDStarHeader* CDStarSlowData::addHeader(const unsigned char* data) { assert(data != NULL); @@ -93,18 +95,92 @@ CDStarHeader* CDStarSlowData::add(const unsigned char* data) return new CDStarHeader(m_header); } +const unsigned char* CDStarSlowData::addText(const unsigned char* data) +{ + assert(data != NULL); + + switch (m_state) { + case SDD_FIRST: + m_buffer[0U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U]; + m_buffer[1U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U]; + m_buffer[2U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U]; + m_state = SDD_SECOND; + return NULL; + + case SDD_SECOND: + m_buffer[3U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U]; + m_buffer[4U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U]; + m_buffer[5U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U]; + m_state = SDD_FIRST; + break; + } + + switch (m_buffer[0U]) { + case DSTAR_SLOW_DATA_TYPE_TEXT | 0U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[0U] = m_buffer[1U] & 0x7FU; + m_text[1U] = m_buffer[2U] & 0x7FU; + m_text[2U] = m_buffer[3U] & 0x7FU; + m_text[3U] = m_buffer[4U] & 0x7FU; + m_text[4U] = m_buffer[5U] & 0x7FU; + m_textBits |= 0x01U; + break; + case DSTAR_SLOW_DATA_TYPE_TEXT | 1U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[5U] = m_buffer[1U] & 0x7FU; + m_text[6U] = m_buffer[2U] & 0x7FU; + m_text[7U] = m_buffer[3U] & 0x7FU; + m_text[8U] = m_buffer[4U] & 0x7FU; + m_text[9U] = m_buffer[5U] & 0x7FU; + m_textBits |= 0x02U; + break; + case DSTAR_SLOW_DATA_TYPE_TEXT | 2U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[10U] = m_buffer[1U] & 0x7FU; + m_text[11U] = m_buffer[2U] & 0x7FU; + m_text[12U] = m_buffer[3U] & 0x7FU; + m_text[13U] = m_buffer[4U] & 0x7FU; + m_text[14U] = m_buffer[5U] & 0x7FU; + m_textBits |= 0x04U; + break; + case DSTAR_SLOW_DATA_TYPE_TEXT | 3U: + CUtils::dump(1U, "D-Star slow data text fragment", m_buffer, 6U); + m_text[15U] = m_buffer[1U] & 0x7FU; + m_text[16U] = m_buffer[2U] & 0x7FU; + m_text[17U] = m_buffer[3U] & 0x7FU; + m_text[18U] = m_buffer[4U] & 0x7FU; + m_text[19U] = m_buffer[5U] & 0x7FU; + m_text[20U] = 0x00U; + m_textBits |= 0x08U; + break; + default: + return NULL; + } + + if (m_textBits != 0x0FU) + return NULL; + + CUtils::dump(1U, "D-STar slow data text", m_text, 20U); + + m_textBits = 0x00U; + + return m_text; +} + void CDStarSlowData::start() { ::memset(m_header, 0x00U, DSTAR_HEADER_LENGTH_BYTES); - m_ptr = 0U; - m_state = SDD_FIRST; + m_ptr = 0U; + m_state = SDD_FIRST; + m_textBits = 0x00U; } void CDStarSlowData::reset() { - m_ptr = 0U; - m_state = SDD_FIRST; + m_ptr = 0U; + m_state = SDD_FIRST; + m_textBits = 0x00U; } void CDStarSlowData::setText(const char* text) @@ -139,10 +215,11 @@ void CDStarSlowData::setText(const char* text) m_text[22U] = text[18U]; m_text[23U] = text[19U]; - m_textPtr = 0U; + m_textPtr = 0U; + m_textBits = 0x00U; } -void CDStarSlowData::get(unsigned char* data) +void CDStarSlowData::getSlowData(unsigned char* data) { assert(data != NULL); diff --git a/DStarSlowData.h b/DStarSlowData.h index 52e0f5c..eaedf45 100644 --- a/DStarSlowData.h +++ b/DStarSlowData.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2023 by Jonathan Naylor G4KLX * * 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 @@ -26,13 +26,15 @@ public: CDStarSlowData(); ~CDStarSlowData(); - CDStarHeader* add(const unsigned char* data); + CDStarHeader* addHeader(const unsigned char* data); + + const unsigned char* addText(const unsigned char* data); void start(); void reset(); void setText(const char* text); - void get(unsigned char* data); + void getSlowData(unsigned char* data); private: unsigned char* m_header; @@ -40,6 +42,7 @@ private: unsigned char* m_buffer; unsigned char* m_text; unsigned int m_textPtr; + unsigned char m_textBits; enum SDD_STATE { SDD_FIRST, From d3f8c17bc8233a8cff5ef787e57b547e0e1776bb Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 12:14:35 +0100 Subject: [PATCH 23/29] Add M17 LSF Text data interpretation. --- M17Control.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++--- M17Control.h | 4 +++ 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index 5d7f7e6..192b5fa 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -86,6 +86,10 @@ m_rfCollectedLSF(), m_rfLSFn(0U), m_netLSF(), m_netLSFn(0U), +m_rfTextBits(0x00U), +m_netTextBits(0x00U), +m_rfText(NULL), +m_netText(NULL), m_rssiMapper(rssiMapper), m_rssi(0U), m_maxRSSI(0U), @@ -97,10 +101,15 @@ m_fp(NULL) { assert(display != NULL); assert(rssiMapper != NULL); + + m_rfText = new char[4U * M17_META_LENGTH_BYTES]; + m_netText = new char[4U * M17_META_LENGTH_BYTES]; } CM17Control::~CM17Control() { + delete[] m_netText; + delete[] m_rfText; } bool CM17Control::writeModem(unsigned char* data, unsigned int len) @@ -196,7 +205,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_rssiCount = 1U; m_rfLSFn = 0U; m_rfLSFCount = 0U; - + m_rfTextBits = 0x00U; + ::memset(m_rfText, 0x00U, 4U * M17_META_LENGTH_BYTES); #if defined(DUMP_M17) openFile(); #endif @@ -249,7 +259,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_aveRSSI = m_rssi; m_rssiCount = 1U; m_rfLSFCount = 0U; - + m_rfTextBits = 0x00U; + ::memset(m_rfText, 0x00U, 4U * M17_META_LENGTH_BYTES); #if defined(DUMP_M17) openFile(); #endif @@ -282,6 +293,38 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (valid) { m_rfCollectedLSF = m_rfCollectingLSF; m_rfCollectingLSF.reset(); + + unsigned char encryptionType = m_rfCollectedLSF.getEncryptionType(); + unsigned char encryptionSubType = m_rfCollectedLSF.getEncryptionSubType(); + if (encryptionType == M17_ENCRYPTION_TYPE_NONE && encryptionSubType == M17_ENCRYPTION_SUB_TYPE_TEXT) { + unsigned char meta[20U]; + m_rfCollectedLSF.getMeta(meta); + CUtils::dump(1U, "M17, LSF text data fragment", meta, M17_META_LENGTH_BYTES); + + m_rfTextBits |= meta[0U]; + + switch (meta[0U] & 0x0FU) { + case 0x01U: + ::memcpy(m_rfText + 0U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x02U: + ::memcpy(m_rfText + 13U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x04U: + ::memcpy(m_rfText + 26U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x08U: + ::memcpy(m_rfText + 39U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + default: + break; + } + + if (m_rfTextBits == 0x11U || m_rfTextBits == 0x33U || m_rfTextBits == 0x77U || m_rfTextBits == 0xFFU) { + LogMessage("M17, text Data: \"%s\"", m_rfText); + m_rfTextBits = 0x00U; + } + } } } @@ -547,8 +590,10 @@ void CM17Control::writeNetwork() m_netTimeoutTimer.start(); m_elapsed.start(); - m_netFrames = 0U; - m_netLSFn = 0U; + m_netFrames = 0U; + m_netLSFn = 0U; + m_netTextBits = 0x00U; + ::memset(m_netText, 0x00U, 4U * M17_META_LENGTH_BYTES); // Create a dummy start message unsigned char start[M17_FRAME_LENGTH_BYTES + 2U]; @@ -580,6 +625,38 @@ void CM17Control::writeNetwork() m_netLSF.setSource(m_callsign); m_netLSF.setCAN(m_can); + + unsigned char encryptionType = m_netLSF.getEncryptionType(); + unsigned char encryptionSubType = m_netLSF.getEncryptionSubType(); + if (encryptionType == M17_ENCRYPTION_TYPE_NONE && encryptionSubType == M17_ENCRYPTION_SUB_TYPE_TEXT) { + unsigned char meta[20U]; + m_netLSF.getMeta(meta); + CUtils::dump(1U, "M17, LSF text data fragment", meta, M17_META_LENGTH_BYTES); + + m_netTextBits |= meta[0U]; + + switch (meta[0U] & 0x0FU) { + case 0x01U: + ::memcpy(m_netText + 0U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x02U: + ::memcpy(m_netText + 13U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x04U: + ::memcpy(m_netText + 26U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + case 0x08U: + ::memcpy(m_netText + 39U, meta + 1U, M17_META_LENGTH_BYTES - 1U); + break; + default: + break; + } + + if (m_netTextBits == 0x11U || m_netTextBits == 0x33U || m_netTextBits == 0x77U || m_netTextBits == 0xFFU) { + LogMessage("M17, text Data: \"%s\"", m_netText); + m_netTextBits = 0x00U; + } + } } unsigned char data[M17_FRAME_LENGTH_BYTES + 2U]; diff --git a/M17Control.h b/M17Control.h index 1e06a28..5a2274e 100644 --- a/M17Control.h +++ b/M17Control.h @@ -76,6 +76,10 @@ private: unsigned int m_rfLSFn; CM17LSF m_netLSF; unsigned int m_netLSFn; + unsigned char m_rfTextBits; + unsigned char m_netTextBits; + char* m_rfText; + char* m_netText; CRSSIInterpolator* m_rssiMapper; unsigned char m_rssi; unsigned char m_maxRSSI; From c0eb51f0ba23daca6bdf9f79f1c2ff2cee0eb310 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 12:38:01 +0100 Subject: [PATCH 24/29] Clean up the D-Star JSON handling. --- DStarControl.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/DStarControl.cpp b/DStarControl.cpp index b941a59..acfc8f5 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -285,7 +285,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_aveRSSI += m_rssi; m_rssiCountTotal++; - writeJSONRSSI(); + m_rssiAccum += m_rssi; + m_rssiCountTotal++; } // Have we got RSSI bytes on the end of D-Star data? @@ -310,7 +311,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_aveRSSI += m_rssi; m_rssiCountTotal++; - writeJSONRSSI(); + m_rssiAccum += m_rssi; + m_rssiCountTotal++; } if (type == TAG_HEADER) { @@ -412,6 +414,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (m_netState == RS_NET_IDLE) { m_display->writeDStar((char*)my1, (char*)my2, (char*)your, "R", " "); m_display->writeDStarRSSI(m_rssi); + writeJSONRSSI(); } LogMessage("D-Star, received RF header from %8.8s/%4.4s to %8.8s", my1, my2, your); @@ -484,25 +487,27 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (m_rfN == 0U) { CSync::addDStarSync(data + 1U); m_display->writeDStarRSSI(m_rssi); + writeJSONRSSI(); } unsigned int errors = 0U; if (!m_rfHeader.isDataPacket()) { errors = maybeFixupVoiceFrame(data, len, 1U, "RF", m_rfN, m_duplex, m_rfVoiceSyncData, m_rfVoiceSyncDataLen, m_rfNextFrameIsFastData, m_rfSkipDTMFBlankingFrames); - m_display->writeDStarBER(float(errors) / 0.48F); m_bitErrsAccum += errors; m_rfErrs += errors; + m_display->writeDStarBER(float(errors) / 0.48F); + writeJSONBER(); } m_bitsCount += 48U; m_rfBits += 48U; m_rfFrames++; - writeJSONBER(); - const unsigned char* text = m_rfSlowData.addText(data + 1U); - if (text != NULL) + if (text != NULL) { LogMessage("D-Star, slow data text = \"%s\"", text); + writeJSONText(text); + } if (m_net) { if (m_rfN == 1U) @@ -640,8 +645,6 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_bitsCount += 48U; m_rfBits += 48U; - writeJSONBER(); - if (m_net) writeNetworkDataRF(data, errors, false); @@ -656,6 +659,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_display->writeDStar((char*)my1, (char*)my2, (char*)your, "R", " "); m_display->writeDStarRSSI(m_rssi); m_display->writeDStarBER(float(errors) / 0.48F); + writeJSONRSSI(); + writeJSONBER(); } LogMessage("D-Star, received RF late entry from %8.8s/%4.4s to %8.8s", my1, my2, your); @@ -856,8 +861,10 @@ void CDStarControl::writeNetwork() } const unsigned char* text = m_netSlowData.addText(data + 2U); - if (text != NULL) + if (text != NULL) { LogMessage("D-Star, slow data text = \"%s\"", text); + writeJSONText(text); + } m_packetTimer.start(); m_netFrames++; @@ -1377,9 +1384,6 @@ void CDStarControl::enable(bool enabled) void CDStarControl::writeJSONRSSI() { - m_rssiAccum += m_rssi; - m_rssiCountTotal++; - if (m_rssiCountTotal >= RSSI_COUNT) { nlohmann::json json; From ac076a7a23c78a4a921a0ddec9607a3177d0a8ef Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 12:58:29 +0100 Subject: [PATCH 25/29] Fix DMR JSON handling. --- DMRSlot.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 9b0e096..6b7b994 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -213,7 +213,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_aveRSSI += m_rssi; m_rssiCountTotal++; - writeJSONRSSI(); + m_rssiAccum += m_rssi; + m_rssiCount++; } bool dataSync = (data[1U] & DMR_SYNC_DATA) == DMR_SYNC_DATA; @@ -321,6 +322,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE); m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R"); m_display->writeDMRRSSI(m_slotNo, m_rssi); + writeJSONRSSI(); + writeJSONBER(); } LogMessage("DMR Slot %u, received RF voice header from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str()); @@ -457,6 +460,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA); m_display->writeDMR(m_slotNo, src, gi, dst, "R"); m_display->writeDMRRSSI(m_slotNo, m_rssi); + writeJSONRSSI(); } LogMessage("DMR Slot %u, received RF data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_rfFrames); @@ -567,6 +571,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA); m_display->writeDMR(m_slotNo, src, gi, dst, "R"); m_display->writeDMRRSSI(m_slotNo, m_rssi); + writeJSONRSSI(); } return true; @@ -627,23 +632,24 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (fid == FID_ETSI || fid == FID_DMRA) { errors = m_fec.regenerateDMR(data + 2U); LogDebug("DMR Slot %u, audio sequence no. 0, errs: %u/141 (%.1f%%)", m_slotNo, errors, float(errors) / 1.41F); - m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); m_rfErrs += errors; m_bitErrsAccum += errors; + + m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); + writeJSONBER(); } m_bitsCount += 141U; m_rfBits += 141U; m_rfFrames++; - writeJSONBER(); - m_rfEmbeddedReadN = (m_rfEmbeddedReadN + 1U) % 2U; m_rfEmbeddedWriteN = (m_rfEmbeddedWriteN + 1U) % 2U; m_rfEmbeddedData[m_rfEmbeddedWriteN].reset(); m_display->writeDMRRSSI(m_slotNo, m_rssi); + writeJSONRSSI(); if (!m_rfTimeout) { data[0U] = TAG_DATA; @@ -679,17 +685,17 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (fid == FID_ETSI || fid == FID_DMRA) { errors = m_fec.regenerateDMR(data + 2U); LogDebug("DMR Slot %u, audio sequence no. %u, errs: %u/141 (%.1f%%)", m_slotNo, m_rfN, errors, float(errors) / 1.41F); - m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); m_rfErrs += errors; m_bitErrsAccum += errors; + + m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); + writeJSONBER(); } m_bitsCount += 141U; m_rfBits += 141U; m_rfFrames++; - writeJSONBER(); - // Get the LCSS from the EMB CDMREMB emb; emb.putData(data + 2U); @@ -973,8 +979,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_rfBits += 141U; m_rfFrames++; - writeJSONBER(); - data[0U] = TAG_DATA; data[1U] = 0x00U; @@ -990,6 +994,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R"); m_display->writeDMRRSSI(m_slotNo, m_rssi); m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); + writeJSONRSSI(); + writeJSONBER(); } LogMessage("DMR Slot %u, received RF late entry from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str()); @@ -2362,9 +2368,6 @@ void CDMRSlot::enable(bool enabled) void CDMRSlot::writeJSONRSSI() { - m_rssiAccum += m_rssi; - m_rssiCount++; - if (m_rssiCount >= RSSI_COUNT) { nlohmann::json json; From 3b89c3f94d820da886c66b7a7fc822869e99f8a2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 15:07:17 +0100 Subject: [PATCH 26/29] Fixuo M17 BER, RSSI, and Text JSON. --- M17Control.cpp | 15 +++++++++------ M17Control.h | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index e31311d..c1abf2e 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -177,7 +177,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_aveRSSI += m_rssi; m_rssiCountTotal++; - writeJSONRSSI(); + m_rssiAccum += m_rssi; + m_rssiCountTotal++; } unsigned char temp[M17_FRAME_LENGTH_BYTES]; @@ -352,6 +353,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_rfTextBits == 0x11U || m_rfTextBits == 0x33U || m_rfTextBits == 0x77U || m_rfTextBits == 0xFFU) { LogMessage("M17, text Data: \"%s\"", m_rfText); + writeJSONText(m_rfText); m_rfTextBits = 0x00U; } } @@ -390,6 +392,9 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_bitsCount += 272U; writeJSONBER(); + m_display->writeM17RSSI(m_rssi); + writeJSONRSSI(); + float ber = float(m_rfErrs) / float(m_rfBits); m_display->writeM17BER(ber); @@ -694,6 +699,7 @@ void CM17Control::writeNetwork() if (m_netTextBits == 0x11U || m_netTextBits == 0x33U || m_netTextBits == 0x77U || m_netTextBits == 0xFFU) { LogMessage("M17, text Data: \"%s\"", m_netText); + writeJSONText(m_netText); m_netTextBits = 0x00U; } } @@ -1035,9 +1041,6 @@ void CM17Control::enable(bool enabled) void CM17Control::writeJSONRSSI() { - m_rssiAccum += m_rssi; - m_rssiCountTotal++; - if (m_rssiCountTotal >= RSSI_COUNT) { nlohmann::json json; @@ -1070,7 +1073,7 @@ void CM17Control::writeJSONBER() } } -void CM17Control::writeJSONText(const unsigned char* text) +void CM17Control::writeJSONText(const char* text) { assert(text != NULL); @@ -1079,7 +1082,7 @@ void CM17Control::writeJSONText(const unsigned char* text) json["timestamp"] = CUtils::createTimestamp(); json["mode"] = "M17"; - json["value"] = std::string((char*)text); + json["value"] = std::string(text); WriteJSON("Text", json); } diff --git a/M17Control.h b/M17Control.h index 81a7282..3472232 100644 --- a/M17Control.h +++ b/M17Control.h @@ -115,7 +115,7 @@ private: void writeJSONRSSI(); void writeJSONBER(); - void writeJSONText(const unsigned char* text); + void writeJSONText(const char* text); void writeJSONRF(const char* action, RPT_RF_STATE state, const std::string& source, const std::string& dest); void writeJSONRF(const char* action, float duration, float ber); From fd5baf790f8916c0d5e1c8bc35566dc1d66ffc82 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 15:28:22 +0100 Subject: [PATCH 27/29] Fix NXDN RSSI and BER JSON. --- NXDNControl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NXDNControl.cpp b/NXDNControl.cpp index beac8a6..ca25f0c 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -150,7 +150,8 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) m_aveRSSI += m_rssi; m_rssiCountTotal++; - writeJSONRSSI(); + m_rssiAccum += m_rssi; + m_rssiCount++; } scrambler(data + 2U); @@ -597,6 +598,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne m_rfFrames++; m_display->writeNXDNRSSI(m_rssi); + writeJSONRSSI(); } return true; @@ -645,6 +647,7 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data) m_display->writeNXDN(source.c_str(), grp, dstId, "R"); m_display->writeNXDNRSSI(m_rssi); + writeJSONRSSI(); LogMessage("NXDN, received RF data header from %s to %s%u, %u blocks", source.c_str(), grp ? "TG " : "", dstId, frames); writeJSONNet("start", srcId, source, grp, dstId, frames); @@ -1192,9 +1195,6 @@ void CNXDNControl::enable(bool enabled) void CNXDNControl::writeJSONRSSI() { - m_rssiAccum += m_rssi; - m_rssiCount++; - if (m_rssiCount >= RSSI_COUNT) { nlohmann::json json; From 44783544fe0ce7180b8629544fdb542eef835681 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 15:32:16 +0100 Subject: [PATCH 28/29] Fix JSON RSSI and BER. --- P25Control.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/P25Control.cpp b/P25Control.cpp index e7689ad..c75d891 100644 --- a/P25Control.cpp +++ b/P25Control.cpp @@ -226,7 +226,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) m_aveRSSI += m_rssi; m_rssiCountTotal++; - writeJSONRSSI(); + m_rssiAccum += m_rssi; + m_rssiCount++; } if (duid == P25_DUID_LDU1) { @@ -333,6 +334,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) } m_display->writeP25RSSI(m_rssi); + writeJSONRSSI(); return true; } @@ -383,6 +385,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len) } m_display->writeP25RSSI(m_rssi); + writeJSONRSSI(); return true; } @@ -1238,9 +1241,6 @@ void CP25Control::enable(bool enabled) void CP25Control::writeJSONRSSI() { - m_rssiAccum += m_rssi; - m_rssiCount++; - if (m_rssiCount >= RSSI_COUNT) { nlohmann::json json; From 46ce993c5d1426ca051ff55392df3bc41148483d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 16 Jun 2023 15:44:20 +0100 Subject: [PATCH 29/29] Fix YSF RSSI and BER JSON. --- YSFControl.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/YSFControl.cpp b/YSFControl.cpp index 5816e62..ee65f4c 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -161,7 +161,8 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) m_aveRSSI += m_rssi; m_rssiCountTotal++; - writeJSONRSSI(); + m_rssiAccum += m_rssi; + m_rssiCount++; } CYSFFICH fich; @@ -303,6 +304,7 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) m_rfFrames++; m_display->writeFusionRSSI(m_rssi); + writeJSONRSSI(); return true; } @@ -400,6 +402,7 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) m_rfFrames++; m_display->writeFusionRSSI(m_rssi); + wrteJSONRSSI(); return true; } @@ -485,6 +488,7 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_rfFrames++; m_display->writeFusionRSSI(m_rssi); + writeJSONRSSI(); return true; } @@ -596,6 +600,7 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_rfFrames++; m_display->writeFusionRSSI(m_rssi); + writeJSONRSSI(); return true; } else if (valid && m_rfState == RS_RF_LISTENING) { @@ -725,6 +730,7 @@ bool CYSFControl::processDNData(bool valid, unsigned char *data) m_rfFrames++; m_display->writeFusionRSSI(m_rssi); + writeJSONRSSI(); return true; } @@ -806,6 +812,7 @@ bool CYSFControl::processFRData(bool valid, unsigned char *data) m_rfFrames++; m_display->writeFusionRSSI(m_rssi); + writeJSONRSSI(); return true; } @@ -891,6 +898,7 @@ bool CYSFControl::processFRData(bool valid, unsigned char *data) m_rfFrames++; m_display->writeFusionRSSI(m_rssi); + writeJSONRSSI(); return true; } @@ -1288,9 +1296,6 @@ void CYSFControl::enable(bool enabled) void CYSFControl::writeJSONRSSI() { - m_rssiAccum += m_rssi; - m_rssiCount++; - if (m_rssiCount >= RSSI_COUNT) { nlohmann::json json;