Add DMR to JSON/MQTT.

This commit is contained in:
Jonathan Naylor
2023-01-18 17:58:53 +00:00
parent a87cac4140
commit 72f249b12e
3 changed files with 265 additions and 29 deletions

View File

@@ -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
@@ -142,14 +142,20 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
return false;
if (data[0U] == TAG_LOST && m_rfState == RS_RF_AUDIO) {
std::string src = m_lookup->find(m_rfLC->getSrcId());
std::string dst = m_lookup->find(m_rfLC->getDstId());
unsigned int srcId = m_rfLC->getSrcId();
unsigned int dstId = m_rfLC->getDstId();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
FLCO flco = m_rfLC->getFLCO();
if (m_rssi != 0U)
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);
else
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);
} 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));
}
if (m_rfTimeout) {
writeEndRF();
return false;
@@ -160,11 +166,14 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
if (data[0U] == TAG_LOST && m_rfState == RS_RF_DATA) {
std::string src = m_lookup->find(m_rfLC->getSrcId());
std::string dst = m_lookup->find(m_rfLC->getDstId());
unsigned int srcId = m_rfLC->getSrcId();
unsigned int dstId = m_rfLC->getDstId();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
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);
writeEndRF();
return false;
}
@@ -219,10 +228,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
unsigned int srcId = lc->getSrcId();
unsigned int dstId = lc->getDstId();
FLCO flco = lc->getFLCO();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
FLCO flco = lc->getFLCO();
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);
delete lc;
m_rfState = RS_RF_LISTENING;
return false;
@@ -230,6 +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);
delete lc;
m_rfState = RS_RF_LISTENING;
return false;
@@ -288,9 +301,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfState = RS_RF_AUDIO;
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R");
@@ -298,6 +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);
return true;
} else if (dataType == DT_VOICE_PI_HEADER) {
@@ -351,14 +362,19 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
}
}
std::string src = m_lookup->find(m_rfLC->getSrcId());
std::string dst = m_lookup->find(m_rfLC->getDstId());
unsigned int srcId = m_rfLC->getSrcId();
unsigned int dstId = m_rfLC->getDstId();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
FLCO flco = m_rfLC->getFLCO();
if (m_rssi != 0U)
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);
else
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);
} 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));
}
m_display->writeDMRTA(m_slotNo, NULL, " ");
@@ -381,15 +397,19 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
bool gi = dataHeader.getGI();
unsigned int srcId = dataHeader.getSrcId();
unsigned int dstId = dataHeader.getDstId();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
if (!CDMRAccessControl::validateSrcId(srcId)) {
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
writeJSONRF("rejected", m_slotNo, 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);
m_rfState = RS_RF_LISTENING;
return false;
}
@@ -417,9 +437,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfState = RS_RF_DATA;
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA);
m_display->writeDMR(m_slotNo, src, gi, dst, "R");
@@ -427,9 +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);
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);
writeEndRF();
}
@@ -453,16 +472,20 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
bool gi = csbk.getGI();
unsigned int srcId = csbk.getSrcId();
unsigned int dstId = csbk.getDstId();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
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);
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);
m_rfState = RS_RF_LISTENING;
return false;
}
@@ -485,33 +508,38 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
writeNetworkRF(data, DT_CSBK, gi ? FLCO_GROUP : FLCO_USER_USER, srcId, dstId);
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
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);
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);
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);
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);
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);
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);
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);
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);
break;
default:
LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko);
@@ -530,6 +558,11 @@ 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;
@@ -566,6 +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);
writeEndRF();
}
@@ -799,10 +833,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (lc != NULL) {
unsigned int srcId = lc->getSrcId();
unsigned int dstId = lc->getDstId();
FLCO flco = lc->getFLCO();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
FLCO flco = lc->getFLCO();
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);
delete lc;
m_rfState = RS_RF_LISTENING;
return false;
@@ -810,6 +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);
delete lc;
m_rfState = RS_RF_LISTENING;
return false;
@@ -902,9 +940,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfState = RS_RF_AUDIO;
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R");
@@ -913,6 +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);
return true;
}
@@ -1147,6 +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);
} else if (dataType == DT_VOICE_PI_HEADER) {
if (m_netState != RS_NET_AUDIO) {
CDMRLC* lc = new CDMRLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());
@@ -1217,6 +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);
}
// Regenerate the Slot Type
@@ -1276,13 +1314,16 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeFile(data);
closeFile();
#endif
std::string src = m_lookup->find(m_netLC->getSrcId());
std::string dst = m_lookup->find(m_netLC->getDstId());
unsigned int srcId = m_netLC->getSrcId();
unsigned int dstId = m_netLC->getDstId();
std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId);
FLCO flco = m_netLC->getFLCO();
// 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));
m_display->writeDMRTA(m_slotNo, NULL, " ");
writeEndNet();
} else if (dataType == DT_DATA_HEADER) {
@@ -1333,9 +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);
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);
writeEndNet();
}
} else if (dataType == DT_VOICE_SYNC) {
@@ -1418,6 +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);
}
if (m_netState == RS_NET_AUDIO) {
@@ -1680,24 +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);
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);
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);
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);
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);
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);
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);
break;
default:
LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko);
@@ -1753,7 +1804,12 @@ 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", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId);
writeEndNet();
}
} else {
@@ -1817,7 +1873,12 @@ 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", m_slotNo, srcId, src, m_rfLC->getFLCO() == FLCO_GROUP, dstId);
m_rfTimeout = true;
}
}
@@ -1825,7 +1886,12 @@ 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", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId);
m_netTimeout = true;
}
}
@@ -1835,15 +1901,25 @@ 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", 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));
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", m_slotNo, srcId, src, m_netLC->getFLCO() == FLCO_GROUP, dstId);
writeEndNet();
#if defined(DUMP_DMR)
closeFile();
@@ -2236,3 +2312,147 @@ 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)
{
assert(action != NULL);
nlohmann::json json;
writeJSON(json, "rf", action, slotNo, 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)
{
assert(action != NULL);
assert(desc != NULL);
nlohmann::json json;
writeJSON(json, "rf", action, slotNo, 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)
{
assert(action != NULL);
nlohmann::json json;
writeJSON(json, "rf", action, slotNo, 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)
{
assert(action != NULL);
nlohmann::json json;
writeJSON(json, "rf", action, slotNo, srcId, srcInfo, grp, dstId);
json["duration"] = duration;
json["ber"] = ber;
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)
{
assert(action != NULL);
nlohmann::json json;
writeJSON(json, "rf", action, slotNo, srcId, srcInfo, grp, dstId);
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("DMR", json);
}
void CDMRSlot::writeJSONNet(const char* action, unsigned int slotNo, 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("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)
{
assert(action != NULL);
assert(desc != NULL);
nlohmann::json json;
writeJSON(json, "network", action, slotNo, 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)
{
assert(action != NULL);
nlohmann::json json;
writeJSON(json, "network", action, slotNo, 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)
{
assert(action != NULL);
nlohmann::json json;
writeJSON(json, "network", action, slotNo, srcId, srcInfo, grp, dstId);
json["duration"] = duration;
json["loss"] = loss;
json["ber"] = ber;
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)
{
assert(source != NULL);
assert(action != NULL);
json["timestamp"] = CUtils::createTimestamp();
json["source"] = source;
json["action"] = action;
json["slot"] = int(slotNo);
json["source_id"] = int(srcId);
json["destination_id"] = int(dstId);
json["destination_type"] = grp ? "group" : "individual";
if (!srcInfo.empty())
json["source_info"] = srcInfo;
}