From d057f79bc4c29e9e41f7118db8910f77770b8812 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 23 Jul 2023 17:36:45 +0100 Subject: [PATCH] Add JSON link status commands for CCS, DCS, Dextra, and D-Plus. --- Common/CCSHandler.cpp | 11 +++++++++- Common/DCSHandler.cpp | 11 +++++++++- Common/DExtraHandler.cpp | 12 ++++++++++- Common/DPlusHandler.cpp | 13 ++++++++++-- Common/MQTTLog.cpp | 43 +++++++++++++++++++++++++++++++++++++++ Common/MQTTLog.h | 6 ++++++ Common/Version.h | 4 ++-- ircDDBGateway/schema.json | 11 +++++----- 8 files changed, 99 insertions(+), 12 deletions(-) diff --git a/Common/CCSHandler.cpp b/Common/CCSHandler.cpp index 470d648..a787256 100644 --- a/Common/CCSHandler.cpp +++ b/Common/CCSHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013,2014 by Jonathan Naylor G4KLX + * Copyright (C) 2013,2014,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 @@ -19,6 +19,7 @@ #include "RepeaterHandler.h" #include "DStarDefines.h" #include "CCSHandler.h" +#include "MQTTLog.h" #include "Utils.h" @@ -252,6 +253,7 @@ void CCCSHandler::process(CAMBEData& data) m_handler->ccsLinkMade(m_yourCall, m_direction); wxLogMessage(wxT("CCS: New incoming link to %s from %s @ %s"), m_local.c_str(), m_yourCall.c_str(), m_rptCall1.c_str()); + WriteJSONLinking("ccs", "in", "network", m_local, m_yourCall); } else { if (!m_yourCall.IsSameAs(myCall1) && !m_rptCall1.IsSameAs(rptCall1)) { wxLogMessage(wxT("CCS: Rejecting new incoming CCS link from %s @ %s to %s"), myCall1.c_str(), rptCall1.c_str(), yourCall.c_str()); @@ -303,6 +305,7 @@ void CCCSHandler::process(CCCSData& data) case CT_TERMINATE: if (m_state == CS_ACTIVE) { wxLogMessage(wxT("CCS: Link between %s and %s has been terminated"), data.getLocal().c_str(), data.getRemote().c_str()); + WriteJSONUnlinked("ccs", "user", m_local, m_yourCall); m_stateChange = true; m_state = CS_CONNECTED; m_inactivityTimer.stop(); @@ -420,11 +423,13 @@ void CCCSHandler::startLink(const wxString& dtmf, const wxString& user, const wx wxString callsign = findInCache(dtmf); if (!callsign.IsEmpty()) { wxLogMessage(wxT("CCS: New outgoing link to %s/%s via %s by %s"), dtmf.c_str(), callsign.c_str(), type.c_str(), user.c_str()); + WriteJSONLinking("ccs", "out", "user", user, callsign); m_handler->ccsLinkMade(callsign, m_direction); m_yourCall = callsign; m_rptCall1 = callsign; } else { wxLogMessage(wxT("CCS: New outgoing link to %s via %s by %s"), dtmf.c_str(), type.c_str(), user.c_str()); + WriteJSONLinking("ccs", "out", "user", user, dtmf); m_yourCall = dtmf; m_yourCall.resize(LONG_CALLSIGN_LENGTH, wxT(' ')); m_rptCall1.Clear(); @@ -447,6 +452,7 @@ void CCCSHandler::stopLink(const wxString& user, const wxString& type) if (!user.IsEmpty() && !type.IsEmpty()) wxLogMessage(wxT("CCS: Link to %s from %s has been terminated via %s by %s"), m_yourCall.c_str(), m_local.c_str(), type.c_str(), user.c_str()); + WriteJSONUnlinked("ccs", "user", m_local, m_yourCall); CCCSData data(m_local, m_yourCall, CT_TERMINATE); data.setDestination(m_ccsAddress, CCS_PORT); @@ -473,6 +479,7 @@ void CCCSHandler::unlink(const wxString& callsign) return; wxLogMessage(wxT("CCS: Link to %s from %s has been terminated by command"), m_yourCall.c_str(), m_local.c_str()); + WriteJSONUnlinked("ccs", "user", m_local, m_yourCall); CCCSData data(m_local, m_yourCall, CT_TERMINATE); data.setDestination(m_ccsAddress, CCS_PORT); @@ -543,6 +550,7 @@ void CCCSHandler::clockInt(unsigned int ms) if (m_pollInactivityTimer.isRunning() && m_pollInactivityTimer.hasExpired()) { wxLogMessage(wxT("CCS: Connection has failed (poll inactivity) for %s, reconnecting"), m_callsign.c_str()); + WriteJSONRelinking("ccs", m_local, m_yourCall); m_announceTimer.stop(); m_pollInactivityTimer.stop(); @@ -582,6 +590,7 @@ void CCCSHandler::clockInt(unsigned int ms) if (m_inactivityTimer.isRunning() && m_inactivityTimer.hasExpired()) { wxLogMessage(wxT("CCS: Activity timeout on link for %s"), m_callsign.c_str(), m_callsign.c_str()); + WriteJSONUnlinked("ccs", "timer", m_local, m_yourCall); CCCSData data(m_local, m_yourCall, CT_TERMINATE); data.setDestination(m_ccsAddress, CCS_PORT); diff --git a/Common/DCSHandler.cpp b/Common/DCSHandler.cpp index 2016805..2036267 100644 --- a/Common/DCSHandler.cpp +++ b/Common/DCSHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2012-2015,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 @@ -19,6 +19,7 @@ #include "RepeaterHandler.h" #include "DStarDefines.h" #include "DCSHandler.h" +#include "MQTTLog.h" #include "Utils.h" unsigned int CDCSHandler::m_maxReflectors = 0U; @@ -290,6 +291,7 @@ void CDCSHandler::process(CConnectData& connect) // A new connect packet indicates the need for a new entry wxLogMessage(wxT("New incoming DCS link to %s from %s"), reflectorCallsign.c_str(), repeaterCallsign.c_str()); + WriteJSONLinking("dcs", "in", "network", repeaterCallsign, reflectorCallsign); CDCSHandler* dcs = new CDCSHandler(handler, repeaterCallsign, reflectorCallsign, m_incoming, yourAddress, yourPort, DIR_INCOMING); @@ -359,6 +361,7 @@ void CDCSHandler::unlink(IReflectorCallback* handler, const wxString& callsign, if (exclude) { if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && !reflector->m_reflector.IsSameAs(callsign)) { wxLogMessage(wxT("Removing outgoing DCS link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + WriteJSONUnlinked("dcs", "user", reflector->m_repeater, reflector->m_reflector); if (reflector->m_linkState == DCS_LINKING || reflector->m_linkState == DCS_LINKED) { CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort); @@ -374,6 +377,7 @@ void CDCSHandler::unlink(IReflectorCallback* handler, const wxString& callsign, } else { if (reflector->m_destination == handler && reflector->m_reflector.IsSameAs(callsign)) { wxLogMessage(wxT("Removing DCS link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + WriteJSONUnlinked("dcs", "user", reflector->m_repeater, reflector->m_reflector); if (reflector->m_linkState == DCS_LINKING || reflector->m_linkState == DCS_LINKED) { CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort); @@ -418,6 +422,7 @@ void CDCSHandler::unlink() if (reflector != NULL) { if (!reflector->m_repeater.IsEmpty()) { wxLogMessage(wxT("Unlinking from DCS reflector %s"), reflector->m_reflector.c_str()); + WriteJSONUnlinked("dcs", "user", reflector->m_repeater, reflector->m_reflector); CConnectData connect(reflector->m_repeater, reflector->m_reflector, CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort); reflector->m_handler->writeConnect(connect); @@ -714,12 +719,15 @@ bool CDCSHandler::clockInt(unsigned int ms) switch (m_linkState) { case DCS_LINKING: wxLogMessage(wxT("DCS link to %s has failed to connect"), GET_DISP_REFLECTOR(this).c_str()); + WriteJSONUnlinked("dcs", "network", m_repeater, m_reflector); break; case DCS_LINKED: wxLogMessage(wxT("DCS link to %s has failed (poll inactivity)"), GET_DISP_REFLECTOR(this).c_str()); + WriteJSONUnlinked("dcs", "timer", m_repeater, m_reflector); break; case DCS_UNLINKING: wxLogMessage(wxT("DCS link to %s has failed to disconnect cleanly"), GET_DISP_REFLECTOR(this).c_str()); + WriteJSONUnlinked("dcs", "network", m_repeater, m_reflector); break; default: break; @@ -728,6 +736,7 @@ bool CDCSHandler::clockInt(unsigned int ms) if (m_direction == DIR_OUTGOING) { bool reconnect = m_destination->linkFailed(DP_DCS, GET_DISP_REFLECTOR(this), true); if (reconnect) { + WriteJSONLinking("dcs", "out", "user", m_repeater, m_reflector); CConnectData reply(m_gatewayType, m_repeater, m_reflector, CT_LINK1, m_yourAddress, m_yourPort); m_handler->writeConnect(reply); m_linkState = DCS_LINKING; diff --git a/Common/DExtraHandler.cpp b/Common/DExtraHandler.cpp index 2ec830e..02b1de9 100644 --- a/Common/DExtraHandler.cpp +++ b/Common/DExtraHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2010-2015,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 @@ -19,6 +19,7 @@ #include "RepeaterHandler.h" #include "DExtraHandler.h" #include "DStarDefines.h" +#include "MQTTLog.h" #include "Utils.h" unsigned int CDExtraHandler::m_maxReflectors = 0U; @@ -297,6 +298,7 @@ void CDExtraHandler::process(const CPollData& poll) // An unmatched poll indicates the need for a new entry wxLogMessage(wxT("New incoming DExtra Dongle from %s"), reflector.c_str()); + WriteJSONLinking("dextra", "in", "network", m_callsign, reflector); CDExtraHandler* handler = new CDExtraHandler(m_incoming, reflector, yourAddress, yourPort, DIR_INCOMING); @@ -372,6 +374,7 @@ void CDExtraHandler::process(CConnectData& connect) // A new connect packet indicates the need for a new entry wxLogMessage(wxT("New incoming DExtra link to %s from %s"), reflectorCallsign.c_str(), repeaterCallsign.c_str()); + WriteJSONLinking("dextra", "in", "network", repeaterCallsign, reflectorCallsign); CDExtraHandler* dextra = new CDExtraHandler(handler, repeaterCallsign, reflectorCallsign, m_incoming, yourAddress, yourPort, DIR_INCOMING); @@ -439,6 +442,7 @@ void CDExtraHandler::unlink(IReflectorCallback* handler, const wxString& callsig if (exclude) { if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && !reflector->m_reflector.IsSameAs(callsign)) { wxLogMessage(wxT("Removing outgoing DExtra link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + WriteJSONUnlinked("dextra", "network", reflector->m_repeater, reflector->m_reflector); if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) { CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort); @@ -454,6 +458,7 @@ void CDExtraHandler::unlink(IReflectorCallback* handler, const wxString& callsig } else { if (reflector->m_destination == handler && reflector->m_reflector.IsSameAs(callsign)) { wxLogMessage(wxT("Removing DExtra link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + WriteJSONUnlinked("dextra", "network", reflector->m_repeater, reflector->m_reflector); if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) { CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort); @@ -501,6 +506,7 @@ void CDExtraHandler::unlink() if (reflector != NULL) { if (!reflector->m_repeater.IsEmpty()) { wxLogMessage(wxT("Unlinking from DExtra reflector %s"), reflector->m_reflector.c_str()); + WriteJSONUnlinked("dextra", "user", reflector->m_repeater, reflector->m_reflector); CConnectData connect(reflector->m_repeater, reflector->m_yourAddress, reflector->m_yourPort); reflector->m_handler->writeConnect(connect); @@ -809,12 +815,15 @@ bool CDExtraHandler::clockInt(unsigned int ms) switch (m_linkState) { case DEXTRA_LINKING: wxLogMessage(wxT("DExtra link to %s has failed to connect"), m_reflector.c_str()); + WriteJSONUnlinked("dextra", "network", m_repeater, m_reflector); break; case DEXTRA_LINKED: wxLogMessage(wxT("DExtra link to %s has failed (poll inactivity)"), m_reflector.c_str()); + WriteJSONUnlinked("dextra", "timer", m_repeater, m_reflector); break; case DEXTRA_UNLINKING: wxLogMessage(wxT("DExtra link to %s has failed to disconnect cleanly"), m_reflector.c_str()); + WriteJSONUnlinked("dextra", "network", m_repeater, m_reflector); break; default: break; @@ -823,6 +832,7 @@ bool CDExtraHandler::clockInt(unsigned int ms) if (m_direction == DIR_OUTGOING) { bool reconnect = m_destination->linkFailed(DP_DEXTRA, m_reflector, true); if (reconnect) { + WriteJSONLinking("dextra", "out", "user", m_repeater, m_reflector); CConnectData reply(m_repeater, m_reflector, CT_LINK1, m_yourAddress, m_yourPort); m_handler->writeConnect(reply); m_linkState = DEXTRA_LINKING; diff --git a/Common/DPlusHandler.cpp b/Common/DPlusHandler.cpp index f0fb631..2a4e207 100644 --- a/Common/DPlusHandler.cpp +++ b/Common/DPlusHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2010-2015,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 @@ -19,6 +19,7 @@ #include "RepeaterHandler.h" #include "DPlusHandler.h" #include "DStarDefines.h" +#include "MQTTLog.h" #include "Utils.h" #include @@ -407,6 +408,7 @@ void CDPlusHandler::unlink(IReflectorCallback* handler, const wxString& callsign if (exclude) { if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && !reflector->m_reflector.IsSameAs(callsign)) { wxLogMessage(wxT("Removing outgoing D-Plus link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + WriteJSONUnlinked("d-plus", "network", reflector->m_repeater, reflector->m_reflector); if (reflector->m_linkState == DPLUS_LINKING || reflector->m_linkState == DPLUS_LINKED) { CConnectData connect(CT_UNLINK, reflector->m_yourAddress, DPLUS_PORT); @@ -425,6 +427,7 @@ void CDPlusHandler::unlink(IReflectorCallback* handler, const wxString& callsign } else { if (reflector->m_destination == handler && reflector->m_reflector.IsSameAs(callsign)) { wxLogMessage(wxT("Removing D-Plus link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str()); + WriteJSONUnlinked("d-plus", "network", reflector->m_repeater, reflector->m_reflector); if (reflector->m_linkState == DPLUS_LINKING || reflector->m_linkState == DPLUS_LINKED) { CConnectData connect(CT_UNLINK, reflector->m_yourAddress, DPLUS_PORT); @@ -469,8 +472,10 @@ void CDPlusHandler::unlink() for (unsigned int i = 0U; i < m_maxReflectors; i++) { CDPlusHandler* reflector = m_reflectors[i]; if (reflector != NULL) { - if (!reflector->m_reflector.IsEmpty()) + if (!reflector->m_reflector.IsEmpty()) { wxLogMessage(wxT("Unlinking from D-Plus reflector or dongle %s"), reflector->m_reflector.c_str()); + WriteJSONUnlinked("d-plus", "user", reflector->m_repeater, reflector->m_reflector); + } CConnectData connect(CT_UNLINK, reflector->m_yourAddress, reflector->m_yourPort); reflector->m_handler->writeConnect(connect); @@ -766,12 +771,15 @@ bool CDPlusHandler::clockInt(unsigned int ms) switch (m_linkState) { case DPLUS_LINKING: wxLogMessage(wxT("D-Plus link to %s has failed to connect"), m_reflector.c_str()); + WriteJSONUnlinked("d-plus", "network", m_repeater, m_reflector); break; case DPLUS_LINKED: wxLogMessage(wxT("D-Plus link to %s has failed (poll inactivity)"), m_reflector.c_str()); + WriteJSONUnlinked("d-plus", "timer", m_repeater, m_reflector); break; case DPLUS_UNLINKING: wxLogMessage(wxT("D-Plus link to %s has failed to disconnect cleanly"), m_reflector.c_str()); + WriteJSONUnlinked("d-plus", "network", m_repeater, m_reflector); break; default: break; @@ -781,6 +789,7 @@ bool CDPlusHandler::clockInt(unsigned int ms) if (m_direction == DIR_OUTGOING) { bool reconnect = m_destination->linkFailed(DP_DPLUS, m_reflector, true); if (reconnect) { + WriteJSONLinking("d-plus", "out", "user", m_repeater, m_reflector); CConnectData connect(CT_LINK1, m_yourAddress, DPLUS_PORT); m_handler->writeConnect(connect); m_linkState = DPLUS_LINKING; diff --git a/Common/MQTTLog.cpp b/Common/MQTTLog.cpp index 318fa20..a90d379 100644 --- a/Common/MQTTLog.cpp +++ b/Common/MQTTLog.cpp @@ -17,6 +17,7 @@ */ #include "MQTTLog.h" +#include "Utils.h" #include #include @@ -51,3 +52,45 @@ void WriteJSON(const std::string& topLevel, nlohmann::json& json) } } +void WriteJSONLinking(const std::string& protocol, const std::string& direction, const std::string& reason, const wxString& local, const wxString& remote) +{ + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["action"] = "linking"; + json["reason"] = reason; + json["remote"] = remote.char_str(); + json["local"] = local.char_str(); + json["protocol"] = protocol; + json["direction"] = direction; + + WriteJSON("link", json); +} + +void WriteJSONUnlinked(const std::string& protocol, const std::string& reason, const wxString& local, const wxString& remote) +{ + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["action"] = "unlinked"; + json["reason"] = reason; + json["remote"] = remote.char_str(); + json["local"] = local.char_str(); + json["protocol"] = protocol; + + WriteJSON("link", json); +} + +void WriteJSONRelinking(const std::string& protocol, const wxString& local, const wxString& remote) +{ + nlohmann::json json; + + json["timestamp"] = CUtils::createTimestamp(); + json["action"] = "relinking"; + json["remote"] = remote.char_str(); + json["local"] = local.char_str(); + json["protocol"] = protocol; + + WriteJSON("link", json); +} + diff --git a/Common/MQTTLog.h b/Common/MQTTLog.h index 9b562b6..1783bae 100644 --- a/Common/MQTTLog.h +++ b/Common/MQTTLog.h @@ -21,6 +21,8 @@ #include "MQTTConnection.h" +#include + #include #include @@ -30,4 +32,8 @@ extern void MQTTLogFinalise(); extern void WriteJSON(const std::string& topLevel, nlohmann::json& json); +extern void WriteJSONLinking(const std::string& protocol, const std::string& direction, const std::string& reason, const wxString& local, const wxString& remote); +extern void WriteJSONUnlinked(const std::string& protocol, const std::string& reason, const wxString& local, const wxString& remote); +extern void WriteJSONRelinking(const std::string& protocol, const wxString& local, const wxString& remote); + #endif diff --git a/Common/Version.h b/Common/Version.h index 43e2f0d..1d8a2d3 100644 --- a/Common/Version.h +++ b/Common/Version.h @@ -24,9 +24,9 @@ const wxString VENDOR_NAME = wxT("G4KLX"); #if defined(__WXDEBUG__) -const wxString VERSION = wxT("20230718 - DEBUG"); +const wxString VERSION = wxT("20230723 - DEBUG"); #else -const wxString VERSION = wxT("20230718"); +const wxString VERSION = wxT("20230723"); #endif #endif diff --git a/ircDDBGateway/schema.json b/ircDDBGateway/schema.json index ba508e4..5b9abe7 100644 --- a/ircDDBGateway/schema.json +++ b/ircDDBGateway/schema.json @@ -1,11 +1,11 @@ { "$defs": { "timestamp": {"type": "string"}, - "reflector": {"type": "string"}, + "callsign": {"type": "string"}, "action": {"type": "string", "enum": ["linking", "unlinked", "failed", "relinking"]}, - "protocol": {"type": "string", "enum": ["d-plus", "dextra", "dcs"]}, + "protocol": {"type": "string", "enum": ["d-plus", "dextra", "dcs", "ccs"]}, "direction": {"type": "string", "enum": ["in", "out"]}, - "reason": {"type": "string", "enum": ["user", "timer", "remote", "startup"]} + "reason": {"type": "string", "enum": ["user", "timer", "network"]} }, "status": { @@ -20,10 +20,11 @@ "timestamp": {"$ref": "#/$defs/timestamp"}, "action": {"$ref": "#/$defs/action"}, "reason": {"$ref": "#/$defs/reason"}, - "reflector": {"$ref": "#/defs/reflector"}, + "local": {"$ref": "#/defs/callsign"}, + "remote": {"$ref": "#/defs/callsign"}, "direction": {"$ref": "#/defs/direction"}, "protocol": {"$ref": "#/defs/protocol"}, - "required": ["timestamp", "action"] + "required": ["timestamp", "protocol", "action", "local", "remote"] } }