Update the C++ version and other changes.

This commit is contained in:
Jonathan Naylor
2025-03-17 14:09:42 +00:00
parent fd54e3eb7c
commit 4ff688045f
7 changed files with 119 additions and 108 deletions

View File

@@ -26,23 +26,23 @@
const int BUFFER_SIZE = 500;
enum SECTION {
SECTION_NONE,
SECTION_GENERAL,
SECTION_LOG,
SECTION_VOICE,
SECTION_INFO,
SECTION_DMR_NETWORK_1,
SECTION_DMR_NETWORK_2,
SECTION_DMR_NETWORK_3,
SECTION_DMR_NETWORK_4,
SECTION_DMR_NETWORK_5,
SECTION_XLX_NETWORK,
SECTION_GPSD,
SECTION_APRS,
SECTION_MQTT,
SECTION_DYNAMIC_TG_CONTROL,
SECTION_REMOTE_COMMANDS
enum class SECTION {
NONE,
GENERAL,
LOG,
VOICE,
INFO,
DMR_NETWORK_1,
DMR_NETWORK_2,
DMR_NETWORK_3,
DMR_NETWORK_4,
DMR_NETWORK_5,
XLX_NETWORK,
GPSD,
APRS,
MQTT,
DYNAMIC_TG_CONTROL,
REMOTE_COMMANDS
};
CConf::CConf(const std::string& file) :
@@ -209,37 +209,37 @@ bool CConf::read()
if (buffer[0U] == '[') {
if (::strncmp(buffer, "[General]", 9U) == 0)
section = SECTION_GENERAL;
section = SECTION::GENERAL;
else if (::strncmp(buffer, "[Log]", 5U) == 0)
section = SECTION_LOG;
section = SECTION::LOG;
else if (::strncmp(buffer, "[Voice]", 7U) == 0)
section = SECTION_VOICE;
section = SECTION::VOICE;
else if (::strncmp(buffer, "[Info]", 6U) == 0)
section = SECTION_INFO;
section = SECTION::INFO;
else if (::strncmp(buffer, "[XLX Network]", 13U) == 0)
section = SECTION_XLX_NETWORK;
section = SECTION::XLX_NETWORK;
else if (::strncmp(buffer, "[DMR Network 1]", 15U) == 0)
section = SECTION_DMR_NETWORK_1;
section = SECTION::DMR_NETWORK_1;
else if (::strncmp(buffer, "[DMR Network 2]", 15U) == 0)
section = SECTION_DMR_NETWORK_2;
section = SECTION::DMR_NETWORK_2;
else if (::strncmp(buffer, "[DMR Network 3]", 15U) == 0)
section = SECTION_DMR_NETWORK_3;
section = SECTION::DMR_NETWORK_3;
else if (::strncmp(buffer, "[DMR Network 4]", 15U) == 0)
section = SECTION_DMR_NETWORK_4;
section = SECTION::DMR_NETWORK_4;
else if (::strncmp(buffer, "[DMR Network 5]", 15U) == 0)
section = SECTION_DMR_NETWORK_5;
section = SECTION::DMR_NETWORK_5;
else if (::strncmp(buffer, "[GPSD]", 6U) == 0)
section = SECTION_GPSD;
section = SECTION::GPSD;
else if (::strncmp(buffer, "[APRS]", 6U) == 0)
section = SECTION_APRS;
section = SECTION::APRS;
else if (::strncmp(buffer, "[MQTT]", 6U) == 0)
section = SECTION_MQTT;
section = SECTION::MQTT;
else if (::strncmp(buffer, "[Dynamic TG Control]", 20U) == 0)
section = SECTION_DYNAMIC_TG_CONTROL;
section = SECTION::DYNAMIC_TG_CONTROL;
else if (::strncmp(buffer, "[Remote Commands]", 17U) == 0)
section = SECTION_REMOTE_COMMANDS;
section = SECTION::REMOTE_COMMANDS;
else
section = SECTION_NONE;
section = SECTION::NONE;
continue;
}
@@ -290,12 +290,12 @@ bool CConf::read()
m_ruleTrace = ::atoi(value) == 1;
else if (::strcmp(key, "Debug") == 0)
m_debug = ::atoi(value) == 1;
} else if (section == SECTION_LOG) {
} else if (section == SECTION::LOG) {
if (::strcmp(key, "MQTTLevel") == 0)
m_logMQTTLevel = (unsigned int)::atoi(value);
else if (::strcmp(key, "DisplayLevel") == 0)
m_logDisplayLevel = (unsigned int)::atoi(value);
} else if (section == SECTION_VOICE) {
} else if (section == SECTION::VOICE) {
if (::strcmp(key, "Enabled") == 0)
m_voiceEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Language") == 0)
@@ -354,7 +354,7 @@ bool CConf::read()
m_xlxNetworkUserControl = ::atoi(value) ==1;
else if (::strcmp(key, "Module") == 0)
m_xlxNetworkModule = ::toupper(value[0]);
} else if (section == SECTION_DMR_NETWORK_1) {
} else if (section == SECTION::DMR_NETWORK_1) {
if (::strcmp(key, "Enabled") == 0)
m_dmrNetwork1Enabled = ::atoi(value) == 1;
else if (::strcmp(key, "Name") == 0)
@@ -980,7 +980,7 @@ bool CConf::read()
m_aprsDescription = value;
else if (::strcmp(key, "Symbol") == 0)
m_aprsSymbol = value;
} else if (section == SECTION_MQTT) {
} else if (section == SECTION::MQTT) {
if (::strcmp(key, "Address") == 0)
m_mqttAddress = value;
else if (::strcmp(key, "Port") == 0)
@@ -989,10 +989,10 @@ bool CConf::read()
m_mqttKeepalive = (unsigned int)::atoi(value);
else if (::strcmp(key, "Name") == 0)
m_mqttName = value;
} else if (section == SECTION_DYNAMIC_TG_CONTROL) {
} else if (section == SECTION::DYNAMIC_TG_CONTROL) {
if (::strcmp(key, "Enable") == 0)
m_dynamicTGControlEnabled = ::atoi(value) == 1;
} else if (section == SECTION_REMOTE_COMMANDS) {
} else if (section == SECTION::REMOTE_COMMANDS) {
if (::strcmp(key, "Enable") == 0)
m_remoteCommandsEnabled = ::atoi(value) == 1;
}

View File

@@ -2529,12 +2529,15 @@ void CDMRGateway::processDynamicTGControl(const std::string& command)
{
std::vector<std::string> args;
std::stringstream tokeniser(command);
// Parse the original command into a vector of strings.
std::string token;
while (std::getline(tokeniser, token, ' '))
args.push_back(token);
size_t start = command.find_first_not_of(' ');
while (start != std::string::npos) {
size_t end = command.find_first_of(' ', start);
args.push_back(command.substr(start, end - start));
start = command.find_first_not_of(' ', end);
}
if (args.at(0U) == "DynTG") {
if (args.size() < 3) {

View File

@@ -369,7 +369,7 @@ void CDMRNetwork::clock(unsigned int ms)
if (m_status == STATUS::RUNNING) {
LogWarning("%s, Login to the master has failed, retrying login ...", m_name.c_str());
WriteJSONStatus("Failed login into DMR Network: " + m_name);
m_status = WAITING_LOGIN;
m_status = STATUS::WAITING_LOGIN;
m_timeoutTimer.start();
m_retryTimer.start();
} else {
@@ -403,7 +403,7 @@ void CDMRNetwork::clock(unsigned int ms)
if (m_options.empty()) {
LogMessage("%s, Logged into the master successfully", m_name.c_str());
WriteJSONStatus("Logged into DMR Network: " + m_name);
m_status = RUNNING;
m_status = STATUS::RUNNING;
} else {
LogDebug("%s, Sending options", m_name.c_str());
writeOptions();
@@ -415,7 +415,7 @@ void CDMRNetwork::clock(unsigned int ms)
case STATUS::WAITING_OPTIONS:
LogMessage("%s, Logged into the master successfully", m_name.c_str());
WriteJSONStatus("Logged into DMR Network: " + m_name);
m_status = RUNNING;
m_status = STATUS::RUNNING;
m_timeoutTimer.start();
m_retryTimer.start();
break;

View File

@@ -59,7 +59,7 @@ m_talkerAliasLen(0U)
m_talkerAliasData = new unsigned char[50U];
CStopWatch stopWatch;
::srand(stopWatch.start());
::srand((unsigned int)stopWatch.start());
}
CMMDVMNetwork::~CMMDVMNetwork()

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022,2023 by Jonathan Naylor G4KLX
* Copyright (C) 2022,2023,2025 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
@@ -21,7 +21,7 @@
#include <cassert>
#include <cstdio>
#include <cstring>
#include <ctime>
CMQTTConnection::CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const std::vector<std::pair<std::string, void (*)(const unsigned char*, unsigned int)>>& subs, unsigned int keepalive, MQTT_QOS qos) :
m_host(host),
@@ -30,7 +30,7 @@ m_name(name),
m_subs(subs),
m_keepalive(keepalive),
m_qos(qos),
m_mosq(NULL),
m_mosq(nullptr),
m_connected(false)
{
assert(!host.empty());
@@ -48,8 +48,13 @@ CMQTTConnection::~CMQTTConnection()
bool CMQTTConnection::open()
{
m_mosq = ::mosquitto_new(m_name.c_str(), true, this);
if (m_mosq == NULL){
char name[50U];
::sprintf(name, "DMRGateway.%lld", ::time(nullptr));
::fprintf(stdout, "DMRGateway (%s) connecting to MQTT as %s\n", m_name.c_str(), name);
m_mosq = ::mosquitto_new(name, true, this);
if (m_mosq == nullptr){
::fprintf(stderr, "MQTT Error newing: Out of memory.\n");
return false;
}
@@ -62,7 +67,7 @@ bool CMQTTConnection::open()
int rc = ::mosquitto_connect(m_mosq, m_host.c_str(), m_port, m_keepalive);
if (rc != MOSQ_ERR_SUCCESS) {
::mosquitto_destroy(m_mosq);
m_mosq = NULL;
m_mosq = nullptr;
::fprintf(stderr, "MQTT Error connecting: %s\n", ::mosquitto_strerror(rc));
return false;
}
@@ -71,7 +76,7 @@ bool CMQTTConnection::open()
if (rc != MOSQ_ERR_SUCCESS) {
::mosquitto_disconnect(m_mosq);
::mosquitto_destroy(m_mosq);
m_mosq = NULL;
m_mosq = nullptr;
::fprintf(stderr, "MQTT Error loop starting: %s\n", ::mosquitto_strerror(rc));
return false;
}
@@ -81,38 +86,38 @@ bool CMQTTConnection::open()
bool CMQTTConnection::publish(const char* topic, const char* text)
{
assert(topic != NULL);
assert(text != NULL);
assert(topic != nullptr);
assert(text != nullptr);
return publish(topic, (unsigned char*)text, ::strlen(text));
return publish(topic, (unsigned char*)text, (unsigned int)::strlen(text));
}
bool CMQTTConnection::publish(const char* topic, const std::string& text)
{
assert(topic != NULL);
assert(topic != nullptr);
return publish(topic, (unsigned char*)text.c_str(), text.size());
return publish(topic, (unsigned char*)text.c_str(), (unsigned int)text.size());
}
bool CMQTTConnection::publish(const char* topic, const unsigned char* data, unsigned int len)
{
assert(topic != NULL);
assert(data != NULL);
assert(topic != nullptr);
assert(data != nullptr);
if (!m_connected)
return false;
if (::strchr(topic, '/') == NULL) {
if (::strchr(topic, '/') == nullptr) {
char topicEx[100U];
::sprintf(topicEx, "%s/%s", m_name.c_str(), topic);
int rc = ::mosquitto_publish(m_mosq, NULL, topicEx, len, data, static_cast<int>(m_qos), false);
int rc = ::mosquitto_publish(m_mosq, nullptr, topicEx, len, data, static_cast<int>(m_qos), false);
if (rc != MOSQ_ERR_SUCCESS) {
::fprintf(stderr, "MQTT Error publishing: %s\n", ::mosquitto_strerror(rc));
return false;
}
} else {
int rc = ::mosquitto_publish(m_mosq, NULL, topic, len, data, static_cast<int>(m_qos), false);
int rc = ::mosquitto_publish(m_mosq, nullptr, topic, len, data, static_cast<int>(m_qos), false);
if (rc != MOSQ_ERR_SUCCESS) {
::fprintf(stderr, "MQTT Error publishing: %s\n", ::mosquitto_strerror(rc));
return false;
@@ -124,17 +129,17 @@ bool CMQTTConnection::publish(const char* topic, const unsigned char* data, unsi
void CMQTTConnection::close()
{
if (m_mosq != NULL) {
if (m_mosq != nullptr) {
::mosquitto_disconnect(m_mosq);
::mosquitto_destroy(m_mosq);
m_mosq = NULL;
m_mosq = nullptr;
}
}
void CMQTTConnection::onConnect(mosquitto* mosq, void* obj, int rc)
{
assert(mosq != NULL);
assert(obj != NULL);
assert(mosq != nullptr);
assert(obj != nullptr);
::fprintf(stdout, "MQTT: on_connect: %s\n", ::mosquitto_connack_string(rc));
if (rc != 0) {
@@ -152,13 +157,13 @@ void CMQTTConnection::onConnect(mosquitto* mosq, void* obj, int rc)
char topicEx[100U];
::sprintf(topicEx, "%s/%s", p->m_name.c_str(), topic.c_str());
rc = ::mosquitto_subscribe(mosq, NULL, topicEx, static_cast<int>(p->m_qos));
rc = ::mosquitto_subscribe(mosq, nullptr, topicEx, static_cast<int>(p->m_qos));
if (rc != MOSQ_ERR_SUCCESS) {
::fprintf(stderr, "MQTT: error subscribing to %s - %s\n", topicEx, ::mosquitto_strerror(rc));
::mosquitto_disconnect(mosq);
}
} else {
rc = ::mosquitto_subscribe(mosq, NULL, topic.c_str(), static_cast<int>(p->m_qos));
rc = ::mosquitto_subscribe(mosq, nullptr, topic.c_str(), static_cast<int>(p->m_qos));
if (rc != MOSQ_ERR_SUCCESS) {
::fprintf(stderr, "MQTT: error subscribing to %s - %s\n", topic.c_str(), ::mosquitto_strerror(rc));
::mosquitto_disconnect(mosq);
@@ -169,9 +174,9 @@ void CMQTTConnection::onConnect(mosquitto* mosq, void* obj, int rc)
void CMQTTConnection::onSubscribe(mosquitto* mosq, void* obj, int mid, int qosCount, const int* grantedQOS)
{
assert(mosq != NULL);
assert(obj != NULL);
assert(grantedQOS != NULL);
assert(mosq != nullptr);
assert(obj != nullptr);
assert(grantedQOS != nullptr);
for (int i = 0; i < qosCount; i++)
::fprintf(stdout, "MQTT: on_subscribe: %d:%d\n", i, grantedQOS[i]);
@@ -179,9 +184,9 @@ void CMQTTConnection::onSubscribe(mosquitto* mosq, void* obj, int mid, int qosCo
void CMQTTConnection::onMessage(mosquitto* mosq, void* obj, const mosquitto_message* message)
{
assert(mosq != NULL);
assert(obj != NULL);
assert(message != NULL);
assert(mosq != nullptr);
assert(obj != nullptr);
assert(message != nullptr);
CMQTTConnection* p = static_cast<CMQTTConnection*>(obj);
@@ -200,8 +205,8 @@ void CMQTTConnection::onMessage(mosquitto* mosq, void* obj, const mosquitto_mess
void CMQTTConnection::onDisconnect(mosquitto* mosq, void* obj, int rc)
{
assert(mosq != NULL);
assert(obj != NULL);
assert(mosq != nullptr);
assert(obj != nullptr);
::fprintf(stdout, "MQTT: on_disconnect: %s\n", ::mosquitto_reason_string(rc));

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022,2023 by Jonathan Naylor G4KLX
* Copyright (C) 2022,2023,2025 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
@@ -24,15 +24,15 @@
#include <vector>
#include <string>
enum MQTT_QOS {
MQTT_QOS_AT_MODE_ONCE = 0U,
MQTT_QOS_AT_LEAST_ONCE = 1U,
MQTT_QOS_EXACTLY_ONCE = 2U
enum class MQTT_QOS : int {
AT_MODE_ONCE = 0,
AT_LEAST_ONCE = 1,
EXACTLY_ONCE = 2
};
class CMQTTConnection {
public:
CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const std::vector<std::pair<std::string, void (*)(const unsigned char*, unsigned int)>>& subs, unsigned int keepalive, MQTT_QOS qos = MQTT_QOS_EXACTLY_ONCE);
CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const std::vector<std::pair<std::string, void (*)(const unsigned char*, unsigned int)>>& subs, unsigned int keepalive, MQTT_QOS qos = MQTT_QOS::EXACTLY_ONCE);
~CMQTTConnection();
bool open();

View File

@@ -36,7 +36,7 @@ extern CMQTTConnection* m_mqtt;
CRemoteControl::CRemoteControl(CDMRGateway* host) :
m_host(host),
m_command(RCD_NONE),
m_command(REMOTE_COMMAND::NONE),
m_args()
{
}
@@ -47,46 +47,49 @@ CRemoteControl::~CRemoteControl()
REMOTE_COMMAND CRemoteControl::processCommand(const std::string& command)
{
m_command = RCD_NONE;
m_command = REMOTE_COMMAND::NONE;
m_args.clear();
std::string replyStr = "OK";
std::stringstream tokeniser(command);
// Parse the original command into a vector of strings.
std::string token;
while (std::getline(tokeniser, token, ' '))
m_args.push_back(token);
size_t start = command.find_first_not_of(' ');
while (start != std::string::npos) {
size_t end = command.find_first_of(' ', start);
m_args.push_back(command.substr(start, end - start));
start = command.find_first_not_of(' ', end);
}
if (m_args.at(0U) == "enable" && m_args.size() >= ENABLE_ARGS) {
if (m_args.at(1U) == "net1")
m_command = RCD_ENABLE_NETWORK1;
m_command = REMOTE_COMMAND::ENABLE_NETWORK1;
else if (m_args.at(1U) == "net2")
m_command = RCD_ENABLE_NETWORK2;
m_command = REMOTE_COMMAND::ENABLE_NETWORK2;
else if (m_args.at(1U) == "net3")
m_command = RCD_ENABLE_NETWORK3;
m_command = REMOTE_COMMAND::ENABLE_NETWORK3;
else if (m_args.at(1U) == "net4")
m_command = RCD_ENABLE_NETWORK4;
m_command = REMOTE_COMMAND::ENABLE_NETWORK4;
else if (m_args.at(1U) == "net5")
m_command = RCD_ENABLE_NETWORK5;
m_command = REMOTE_COMMAND::ENABLE_NETWORK5;
else if (m_args.at(1U) == "xlx")
m_command = RCD_ENABLE_XLX;
m_command = REMOTE_COMMAND::ENABLE_XLX;
else
replyStr = "KO";
} else if (m_args.at(0U) == "disable" && m_args.size() >= DISABLE_ARGS) {
if (m_args.at(1U) == "net1")
m_command = RCD_DISABLE_NETWORK1;
m_command = REMOTE_COMMAND::DISABLE_NETWORK1;
else if (m_args.at(1U) == "net2")
m_command = RCD_DISABLE_NETWORK2;
m_command = REMOTE_COMMAND::DISABLE_NETWORK2;
else if (m_args.at(1U) == "net3")
m_command = RCD_DISABLE_NETWORK3;
m_command = REMOTE_COMMAND::DISABLE_NETWORK3;
else if (m_args.at(1U) == "net4")
m_command = RCD_DISABLE_NETWORK4;
m_command = REMOTE_COMMAND::DISABLE_NETWORK4;
else if (m_args.at(1U) == "net5")
m_command = RCD_DISABLE_NETWORK5;
m_command = REMOTE_COMMAND::DISABLE_NETWORK5;
else if (m_args.at(1U) == "xlx")
m_command = RCD_DISABLE_XLX;
m_command = REMOTE_COMMAND::DISABLE_XLX;
else
replyStr = "KO";
} else if (m_args.at(0U) == "status") {
@@ -95,22 +98,22 @@ REMOTE_COMMAND CRemoteControl::processCommand(const std::string& command)
else
replyStr = "KO";
m_command = RCD_CONNECTION_STATUS;
m_command = REMOTE_COMMAND::CONNECTION_STATUS;
} else if (m_args.at(0U) == "hosts") {
if (m_host != nullptr)
m_host->buildNetworkHostsString(replyStr);
else
replyStr = "KO";
m_command = RCD_CONFIG_HOSTS;
m_command = REMOTE_COMMAND::CONFIG_HOSTS;
} else {
replyStr = "KO";
}
char buffer[200U];
::snprintf(buffer, 200, "%s remote command of \"%s\" received", ((m_command == RCD_NONE) ? "Invalid" : "Valid"), command.c_str());
::snprintf(buffer, 200, "%s remote command of \"%s\" received", ((m_command == REMOTE_COMMAND::NONE) ? "Invalid" : "Valid"), command.c_str());
if (m_command == RCD_NONE) {
if (m_command == REMOTE_COMMAND::NONE) {
m_args.clear();
LogWarning(buffer);
} else {