From 0ecf2dec39bcedf9b30d512f7646c4bd54113512 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 19 Jan 2023 10:08:50 +0000 Subject: [PATCH] Minor rework of JSON creation. --- AX25Control.cpp | 5 +- DMRSlot.cpp | 128 ++++++++++++++++++++++++------------------------ DMRSlot.h | 20 ++++---- YSFControl.cpp | 84 +++++++++++++++++++++---------- YSFControl.h | 12 +++-- schema.json | 7 +-- 6 files changed, 147 insertions(+), 109 deletions(-) diff --git a/AX25Control.cpp b/AX25Control.cpp index 53aec4d..20cd733 100644 --- a/AX25Control.cpp +++ b/AX25Control.cpp @@ -236,15 +236,16 @@ void CAX25Control::decodeJSON(const char* source, const unsigned char* data, uns nlohmann::json json; json["timestamp"] = CUtils::createTimestamp(); + json["source"] = source; std::string text; bool isDigi; bool more = decodeAddressJSON(data + 7U, text, isDigi); - json["source"] = text; + json["source_cs"] = text; decodeAddressJSON(data + 0U, text, isDigi); - json["destination"] = text; + json["destination_cs"] = text; unsigned int n = 14U; diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 7f472ea..268619e 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -150,10 +150,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", m_slotNo, 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", 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); } 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", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId, 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)); } if (m_rfTimeout) { @@ -173,7 +173,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", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("lost", srcId, src, flco == FLCO_GROUP, dstId); writeEndRF(); return false; } @@ -234,7 +234,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!CDMRAccessControl::validateSrcId(srcId)) { LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); - writeJSONRF("rejected", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId); delete lc; m_rfState = RS_RF_LISTENING; return false; @@ -242,7 +242,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) { LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); - writeJSONRF("rejected", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId); delete lc; m_rfState = RS_RF_LISTENING; return false; @@ -308,7 +308,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) } 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()); - writeJSONRF("start", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("start", srcId, src, flco == FLCO_GROUP, dstId); return true; } else if (dataType == DT_VOICE_PI_HEADER) { @@ -370,10 +370,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", m_slotNo, 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", 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); } 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", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId, 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)); } m_display->writeDMRTA(m_slotNo, NULL, " "); @@ -402,14 +402,14 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!CDMRAccessControl::validateSrcId(srcId)) { LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); - writeJSONRF("rejected", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("rejected", srcId, src, gi, dstId); m_rfState = RS_RF_LISTENING; return false; } if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) { LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); - writeJSONRF("rejected", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("rejected", srcId, src, gi, dstId); m_rfState = RS_RF_LISTENING; return false; } @@ -444,11 +444,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) } 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); - writeJSONRF("start", m_slotNo, srcId, src, gi, dstId, m_rfFrames); + writeJSONRF("start", srcId, src, gi, dstId, m_rfFrames); 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", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("end", srcId, src, gi, dstId); writeEndRF(); } @@ -478,14 +478,14 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (srcId != 0U || dstId != 0U) { if (!CDMRAccessControl::validateSrcId(srcId)) { LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); - writeJSONRF("rejected", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("rejected", srcId, src, gi, dstId); m_rfState = RS_RF_LISTENING; return false; } if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) { LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); - writeJSONRF("rejected", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("rejected", srcId, src, gi, dstId); m_rfState = RS_RF_LISTENING; return false; } @@ -511,35 +511,35 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) switch (csbko) { case CSBKO_UUVREQ: LogMessage("DMR Slot %u, received RF Unit to Unit Voice Service Request CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str()); - writeJSONRF("csbk", "Unit to Unit Voice Service Request", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Unit to Unit Voice Service Request", srcId, src, gi, dstId); break; case CSBKO_UUANSRSP: LogMessage("DMR Slot %u, received RF Unit to Unit Voice Service Answer Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str()); - writeJSONRF("csbk", "Unit to Unit Voice Answer Response", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Unit to Unit Voice Answer Response", srcId, src, gi, dstId); break; case CSBKO_NACKRSP: LogMessage("DMR Slot %u, received RF Negative Acknowledgment Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str()); - writeJSONRF("csbk", "Negative Acknowledgment Response", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Negative Acknowledgment Response", srcId, src, gi, dstId); break; case CSBKO_PRECCSBK: LogMessage("DMR Slot %u, received RF %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG ": "", dst.c_str()); - writeJSONRF("csbk", "Preamble", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Preamble", srcId, src, gi, dstId); break; case CSBKO_CALL_ALERT: LogMessage("DMR Slot %u, received RF Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONRF("csbk", "Call Alert", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Call Alert", srcId, src, gi, dstId); break; case CSBKO_CALL_ALERT_ACK: LogMessage("DMR Slot %u, received RF Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONRF("csbk", "Call Alert Ack", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Call Alert Ack", srcId, src, gi, dstId); break; case CSBKO_RADIO_CHECK: LogMessage("DMR Slot %u, received RF Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONRF("csbk", "Radio Check", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Radio Check", srcId, src, gi, dstId); break; case CSBKO_CALL_EMERGENCY: LogMessage("DMR Slot %u, received RF Call Emergency CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONRF("csbk", "Call Emergency", m_slotNo, srcId, src, gi, dstId); + writeJSONRF("csbk", "Call Emergency", srcId, src, gi, dstId); break; default: LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko); @@ -599,7 +599,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", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("end", srcId, src, flco == FLCO_GROUP, dstId); writeEndRF(); } @@ -839,7 +839,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!CDMRAccessControl::validateSrcId(srcId)) { LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId); - writeJSONRF("rejected", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId); delete lc; m_rfState = RS_RF_LISTENING; return false; @@ -847,7 +847,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) { LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId); - writeJSONRF("rejected", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("rejected", srcId, src, flco == FLCO_GROUP, dstId); delete lc; m_rfState = RS_RF_LISTENING; return false; @@ -948,7 +948,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) } 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()); - writeJSONRF("late_entry", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONRF("late_entry", srcId, src, flco == FLCO_GROUP, dstId); return true; } @@ -1183,7 +1183,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) #endif LogMessage("DMR Slot %u, received network voice header from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str()); - writeJSONNet("start", m_slotNo, srcId, src, flco == FLCO_GROUP, dstId); + writeJSONNet("start", srcId, src, flco == FLCO_GROUP, dstId); } else if (dataType == DT_VOICE_PI_HEADER) { if (m_netState != RS_NET_AUDIO) { CDMRLC* lc = new CDMRLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId()); @@ -1254,7 +1254,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_display->writeDMR(m_slotNo, cn, m_netLC->getFLCO() == FLCO_GROUP, dst, "N"); LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str()); - writeJSONNet("late_entry", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("late_entry", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); } // Regenerate the Slot Type @@ -1323,7 +1323,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", m_slotNo, 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", srcId, src, flco == FLCO_GROUP, dstId, 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) { @@ -1374,11 +1374,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_display->writeDMR(m_slotNo, src, gi, dst, "N"); LogMessage("DMR Slot %u, received network data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_netFrames); - writeJSONNet("start", m_slotNo, srcId, src, gi, dstId, m_netFrames); + writeJSONNet("start", srcId, src, gi, dstId, m_netFrames); 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", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("end", srcId, src, gi, dstId); writeEndNet(); } } else if (dataType == DT_VOICE_SYNC) { @@ -1461,7 +1461,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_display->writeDMR(m_slotNo, cn, m_netLC->getFLCO() == FLCO_GROUP, dst, "N"); LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str()); - writeJSONNet("late_entry", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("late_entry", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); } if (m_netState == RS_NET_AUDIO) { @@ -1724,31 +1724,31 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) switch (csbko) { case CSBKO_UUVREQ: LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Request CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str()); - writeJSONNet("csbk", "Unit to Unit Voice Service Request", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("csbk", "Unit to Unit Voice Service Request", srcId, src, gi, dstId); break; case CSBKO_UUANSRSP: LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Answer Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str()); - writeJSONNet("csbk", "Unit to Unit Voice Service Answer Response", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("csbk", "Unit to Unit Voice Service Answer Response", srcId, src, gi, dstId); break; case CSBKO_NACKRSP: LogMessage("DMR Slot %u, received network Negative Acknowledgment Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str()); - writeJSONNet("csbk", "UNegative Acknowledgment Response", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("csbk", "UNegative Acknowledgment Response", srcId, src, gi, dstId); break; case CSBKO_PRECCSBK: LogMessage("DMR Slot %u, received network %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONNet("csbk", "Preamble", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("csbk", "Preamble", srcId, src, gi, dstId); break; case CSBKO_CALL_ALERT: LogMessage("DMR Slot %u, received network Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONNet("csbk", "Call Alert", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("csbk", "Call Alert", srcId, src, gi, dstId); break; case CSBKO_CALL_ALERT_ACK: LogMessage("DMR Slot %u, received network Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONNet("csbk", "Call Alert Ack", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("csbk", "Call Alert Ack", srcId, src, gi, dstId); break; case CSBKO_RADIO_CHECK: LogMessage("DMR Slot %u, received network Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str()); - writeJSONNet("csbk", "Radio Check", m_slotNo, srcId, src, gi, dstId); + writeJSONNet("csbk", "Radio Check", srcId, src, gi, dstId); break; default: LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko); @@ -1809,7 +1809,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) std::string src = m_lookup->find(srcId); LogMessage("DMR Slot %u, ended network data transmission", m_slotNo); - writeJSONNet("end", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("end", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); writeEndNet(); } } else { @@ -1878,7 +1878,7 @@ void CDMRSlot::clock() std::string src = m_lookup->find(srcId); LogMessage("DMR Slot %u, RF user has timed out", m_slotNo); - writeJSONRF("timeout", m_slotNo, srcId, src, m_rfLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONRF("timeout", srcId, src, m_rfLC->getFLCO() == FLCO_GROUP, dstId); m_rfTimeout = true; } } @@ -1891,7 +1891,7 @@ void CDMRSlot::clock() std::string src = m_lookup->find(srcId); LogMessage("DMR Slot %u, network user has timed out", m_slotNo); - writeJSONNet("timeout", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("timeout", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); m_netTimeout = true; } } @@ -1908,7 +1908,7 @@ void CDMRSlot::clock() // 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", m_slotNo, 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", 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)); writeEndNet(true); #if defined(DUMP_DMR) closeFile(); @@ -1919,7 +1919,7 @@ void CDMRSlot::clock() std::string src = m_lookup->find(srcId); LogMessage("DMR Slot %u, network watchdog has expired", m_slotNo); - writeJSONNet("lost", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); + writeJSONNet("lost", srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId); writeEndNet(); #if defined(DUMP_DMR) closeFile(); @@ -2313,51 +2313,51 @@ void CDMRSlot::enable(bool enabled) m_enabled = enabled; } -void CDMRSlot::writeJSONRF(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) +void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); WriteJSON("DMR", json); } -void CDMRSlot::writeJSONRF(const char* action, const char* desc, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) +void CDMRSlot::writeJSONRF(const char* action, const char* desc, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); assert(desc != NULL); nlohmann::json json; - writeJSON(json, "rf", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); json["csbk_desc"] = desc; WriteJSON("DMR", json); } -void CDMRSlot::writeJSONRF(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames) +void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); json["frames"] = int(frames); WriteJSON("DMR", json); } -void CDMRSlot::writeJSONRF(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber) +void CDMRSlot::writeJSONRF(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); json["duration"] = duration; json["ber"] = ber; @@ -2365,13 +2365,13 @@ void CDMRSlot::writeJSONRF(const char* action, unsigned int slotNo, unsigned int WriteJSON("DMR", json); } -void CDMRSlot::writeJSONRF(const char* action, unsigned int slotNo, 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, 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) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "rf", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "rf", action, srcId, srcInfo, grp, dstId); json["duration"] = duration; json["ber"] = ber; @@ -2386,51 +2386,51 @@ void CDMRSlot::writeJSONRF(const char* action, unsigned int slotNo, unsigned int WriteJSON("DMR", json); } -void CDMRSlot::writeJSONNet(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) +void CDMRSlot::writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "network", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "network", action, srcId, srcInfo, grp, dstId); WriteJSON("DMR", json); } -void CDMRSlot::writeJSONNet(const char* action, const char* desc, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) +void CDMRSlot::writeJSONNet(const char* action, const char* desc, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) { assert(action != NULL); assert(desc != NULL); nlohmann::json json; - writeJSON(json, "network", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "network", action, srcId, srcInfo, grp, dstId); json["csbk_desc"] = desc; WriteJSON("DMR", json); } -void CDMRSlot::writeJSONNet(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames) +void CDMRSlot::writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "network", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "network", action, srcId, srcInfo, grp, dstId); json["frames"] = int(frames); WriteJSON("DMR", json); } -void CDMRSlot::writeJSONNet(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float loss, float ber) +void CDMRSlot::writeJSONNet(const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float loss, float ber) { assert(action != NULL); nlohmann::json json; - writeJSON(json, "network", action, slotNo, srcId, srcInfo, grp, dstId); + writeJSON(json, "network", action, srcId, srcInfo, grp, dstId); json["duration"] = duration; json["loss"] = loss; @@ -2439,7 +2439,7 @@ void CDMRSlot::writeJSONNet(const char* action, unsigned int slotNo, unsigned in WriteJSON("DMR", json); } -void CDMRSlot::writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId) +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); assert(action != NULL); @@ -2447,7 +2447,7 @@ void CDMRSlot::writeJSON(nlohmann::json& json, const char* source, const char* a json["timestamp"] = CUtils::createTimestamp(); json["source"] = source; json["action"] = action; - json["slot"] = int(slotNo); + json["slot"] = int(m_slotNo); json["source_id"] = int(srcId); json["destination_id"] = int(dstId); json["destination_type"] = grp ? "group" : "individual"; diff --git a/DMRSlot.h b/DMRSlot.h index b35bc4d..b791613 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -160,18 +160,18 @@ private: static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP, ACTIVITY_TYPE type = ACTIVITY_NONE); - void writeJSONRF(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); - void writeJSONRF(const char* action, unsigned int slotNo, 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 slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); - void writeJSONRF(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float ber); - void writeJSONRF(const char* action, unsigned int slotNo, 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, 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 writeJSONNet(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); - void writeJSONNet(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, unsigned int frames); - void writeJSONNet(const char* action, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId, float duration, float loss, float ber); - void writeJSONNet(const char* action, const char* desc, unsigned int slotNo, 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); + 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, 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, unsigned int slotNo, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); + void writeJSON(nlohmann::json& json, const char* source, const char* action, unsigned int srcId, const std::string& srcInfo, bool grp, unsigned int dstId); }; #endif diff --git a/YSFControl.cpp b/YSFControl.cpp index 2d57545..874a602 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -110,10 +110,10 @@ 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", "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("lost", m_rfSource, dgid, 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", "voice_dn", m_rfSource, dgid, 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)); } writeEndRF(); return false; @@ -951,7 +951,7 @@ void CYSFControl::writeNetwork() if (::memcmp(m_netSource, " ", 10U) != 0 && ::memcmp(m_netDest, " ", 10U) != 0) { m_display->writeFusion((char*)m_netSource, (char*)m_netDest, dgid, "N", (char*)(data + 4U)); LogMessage("YSF, received network data from %10.10s to DG-ID %u at %10.10s", m_netSource, dgid, data + 4U); - writeJSONNet("start", "voice_dn", m_netSource, dgid, data + 4U); + writeJSONNet("start", m_netSource, dgid, data + 4U); } m_netTimeoutTimer.start(); @@ -1064,7 +1064,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", "voice_dn", 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); writeEndNet(); } } @@ -1083,7 +1083,7 @@ void CYSFControl::clock(unsigned int 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", "voice_dn", m_netSource, dgid, 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); writeEndNet(); } } @@ -1210,7 +1210,7 @@ void CYSFControl::processNetCallsigns(const unsigned char* data, unsigned char d if (::memcmp(m_netSource, " ", 10U) != 0 && ::memcmp(m_netDest, " ", 10U) != 0) { m_display->writeFusion((char*)m_netSource, (char*)m_netDest, dgid, "N", (char*)(data + 4U)); LogMessage("YSF, received network data from %10.10s to DG-ID %u at %10.10s", m_netSource, dgid, data + 4U); - writeJSONNet("start", "voice_dn", m_netSource, dgid, data + 4U); + writeJSONNet("start", m_netSource, dgid, data + 4U); } } } @@ -1256,7 +1256,24 @@ void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsign nlohmann::json json; - writeJSONRF(json, action, mode, source, dgid); + writeJSONRF(json, action, source, dgid); + + json["mode"] = mode; + + WriteJSON("YSF", json); +} + +void CYSFControl::writeJSONRF(const char* action, const unsigned char* source, unsigned char dgid, float duration, float ber) +{ + assert(action != NULL); + assert(source != NULL); + + nlohmann::json json; + + writeJSONRF(json, action, source, dgid); + + json["duration"] = duration; + json["ber"] = ber; WriteJSON("YSF", json); } @@ -1269,23 +1286,23 @@ void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsign nlohmann::json json; - writeJSONRF(json, action, mode, source, dgid); + writeJSONRF(json, action, source, dgid); + json["mode"] = mode; json["duration"] = duration; json["ber"] = ber; 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) +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(mode != NULL); assert(source != NULL); nlohmann::json json; - writeJSONRF(json, action, mode, source, dgid); + writeJSONRF(json, action, source, dgid); json["duration"] = duration; json["ber"] = ber; @@ -1300,31 +1317,53 @@ void CYSFControl::writeJSONRF(const char* action, const char* mode, const unsign WriteJSON("YSF", json); } -void CYSFControl::writeJSONNet(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, const unsigned char* reflector) +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; + + nlohmann::json rssi; + rssi["min"] = -int(minRSSI); + rssi["max"] = -int(maxRSSI); + rssi["ave"] = -int(aveRSSI); + + json["rssi"] = rssi; + + WriteJSON("YSF", json); +} + +void CYSFControl::writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, const unsigned char* reflector) +{ + assert(action != NULL); + assert(source != NULL); assert(reflector != NULL); nlohmann::json json; - writeJSONNet(json, action, mode, source, dgid); + writeJSONNet(json, action, source, dgid); json["reflector"] = convertBuffer(reflector); WriteJSON("YSF", json); } -void CYSFControl::writeJSONNet(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, float duration, unsigned int loss) +void CYSFControl::writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, float duration, unsigned int loss) { assert(action != NULL); - assert(mode != NULL); assert(source != NULL); nlohmann::json json; - writeJSONNet(json, action, mode, source, dgid); + writeJSONNet(json, action, source, dgid); json["duration"] = duration; json["loss"] = loss; @@ -1332,16 +1371,15 @@ void CYSFControl::writeJSONNet(const char* action, const char* mode, const unsig WriteJSON("YSF", json); } -void CYSFControl::writeJSONNet(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, const unsigned char* reflector, float duration, unsigned int loss) +void CYSFControl::writeJSONNet(const char* action, const unsigned char* source, unsigned char dgid, const unsigned char* reflector, float duration, unsigned int loss) { assert(action != NULL); - assert(mode != NULL); assert(source != NULL); assert(reflector != NULL); nlohmann::json json; - writeJSONNet(json, action, mode, source, dgid); + writeJSONNet(json, action, source, dgid); json["reflector"] = convertBuffer(reflector); @@ -1351,10 +1389,9 @@ void CYSFControl::writeJSONNet(const char* action, const char* mode, const unsig WriteJSON("YSF", json); } -void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action, const char* mode, const unsigned char* source, unsigned char dgid) +void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid) { assert(action != NULL); - assert(mode != NULL); assert(source != NULL); json["timestamp"] = CUtils::createTimestamp(); @@ -1363,14 +1400,12 @@ void CYSFControl::writeJSONRF(nlohmann::json& json, const char* action, const ch json["source"] = "rf"; json["action"] = action; - json["mode"] = mode; json["dg-id"] = int(dgid); } -void CYSFControl::writeJSONNet(nlohmann::json& json, const char* action, const char* mode, const unsigned char* source, unsigned char dgid) +void CYSFControl::writeJSONNet(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid) { assert(action != NULL); - assert(mode != NULL); assert(source != NULL); json["timestamp"] = CUtils::createTimestamp(); @@ -1379,7 +1414,6 @@ void CYSFControl::writeJSONNet(nlohmann::json& json, const char* action, const c json["source"] = "network"; json["action"] = action; - json["mode"] = mode; json["dg-id"] = int(dgid); } diff --git a/YSFControl.h b/YSFControl.h index 5e2d47a..1fe92ad 100644 --- a/YSFControl.h +++ b/YSFControl.h @@ -103,15 +103,17 @@ 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 writeJSONNet(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, const unsigned char* reflector); - void writeJSONNet(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, float duration, unsigned int loss); - void writeJSONNet(const char* action, const char* mode, const unsigned char* source, unsigned char dgid, const unsigned char* reflector, float duration, unsigned int loss); + 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 writeJSONRF(nlohmann::json& json, const char* action, const char* mode, const unsigned char* source, unsigned char dgid); - void writeJSONNet(nlohmann::json& json, const char* action, const char* mode, const unsigned char* source, unsigned char dgid); + void writeJSONRF(nlohmann::json& json, const char* action, const unsigned char* source, unsigned char dgid); + 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 8301060..5ffd1f7 100644 --- a/schema.json +++ b/schema.json @@ -98,7 +98,7 @@ "max": {"$ref": "#/$defs/rssi"}, "ave": {"$ref": "#/$defs/rssi"} }, - "required": ["timestamp", "source_cs", "dg-id", "source", "action", "mode"] + "required": ["timestamp", "source_cs", "dg-id", "source", "action"] }, "P25": { @@ -160,8 +160,9 @@ "AX.25": { "type": "object", "timestamp": {"$ref": "#/$defs/timestamp"}, - "source": {"$ref": "#/$defs/ax25_callsign"}, - "destination": {"$ref": "#/$defs/ax25_callsign"}, + "source": {"$ref": "#/$defs/source"}, + "source_cs": {"$ref": "#/$defs/ax25_callsign"}, + "destination_cs": {"$ref": "#/$defs/ax25_callsign"}, "digipeaters": { "type": "array", "callsign": {"$ref": "#/$defs/ax25_callsign"},