Add JSON link status commands for CCS, DCS, Dextra, and D-Plus.

This commit is contained in:
Jonathan Naylor 2023-07-23 17:36:45 +01:00
parent 7da1a79730
commit d057f79bc4
8 changed files with 99 additions and 12 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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 <wx/filename.h>
@ -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;

View file

@ -17,6 +17,7 @@
*/
#include "MQTTLog.h"
#include "Utils.h"
#include <cstdio>
#include <cstdlib>
@ -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);
}

View file

@ -21,6 +21,8 @@
#include "MQTTConnection.h"
#include <wx/wx.h>
#include <string>
#include <nlohmann/json.hpp>
@ -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

View file

@ -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

View file

@ -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"]
}
}