Add MQTT subscriptions for display and remote commands.

This commit is contained in:
Jonathan Naylor
2023-06-19 17:16:14 +01:00
parent ff004211b9
commit 0615a4218d
4 changed files with 162 additions and 89 deletions

View File

@@ -77,6 +77,8 @@ static void sigHandler2(int signum)
} }
#endif #endif
static CMMDVMHost* host = NULL;
const char* HEADER1 = "This software is for use on amateur radio networks only,"; const char* HEADER1 = "This software is for use on amateur radio networks only,";
const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on";
const char* HEADER3 = "commercial networks is strictly prohibited."; const char* HEADER3 = "commercial networks is strictly prohibited.";
@@ -112,10 +114,11 @@ int main(int argc, char** argv)
do { do {
m_signal = 0; m_signal = 0;
CMMDVMHost* host = new CMMDVMHost(std::string(iniFile)); host = new CMMDVMHost(std::string(iniFile));
ret = host->run(); ret = host->run();
delete host; delete host;
host = NULL;
switch (m_signal) { switch (m_signal) {
case 2: case 2:
@@ -289,7 +292,11 @@ int CMMDVMHost::run()
return 1; return 1;
} }
m_mqtt = new CMQTTConnection(m_conf.getMQTTHost(), m_conf.getMQTTPort(), m_conf.getMQTTName(), m_conf.getMQTTKeepalive()); std::vector<std::pair<std::string, void (*)(const std::string&)>> subscriptions;
subscriptions.push_back(std::make_pair("display", CMMDVMHost::onDisplay));
subscriptions.push_back(std::make_pair("command", CMMDVMHost::onCommand));
m_mqtt = new CMQTTConnection(m_conf.getMQTTHost(), m_conf.getMQTTPort(), m_conf.getMQTTName(), subscriptions, m_conf.getMQTTKeepalive());
ret = m_mqtt->open(); ret = m_mqtt->open();
if (!ret) { if (!ret) {
::fprintf(stderr, "MMDVMHost: unable to start the MQTT Publisher\n"); ::fprintf(stderr, "MMDVMHost: unable to start the MQTT Publisher\n");
@@ -2796,3 +2803,11 @@ void CMMDVMHost::writeJSONMessage(const std::string& message)
WriteJSON("MMDVM", json); WriteJSON("MMDVM", json);
} }
void CMMDVMHost::onCommand(const std::string& command)
{
}
void CMMDVMHost::onDisplay(const std::string& message)
{
}

View File

@@ -49,99 +49,102 @@
class CMMDVMHost class CMMDVMHost
{ {
public: public:
CMMDVMHost(const std::string& confFile); CMMDVMHost(const std::string& confFile);
~CMMDVMHost(); ~CMMDVMHost();
int run(); int run();
void buildNetworkStatusString(std::string &str); void buildNetworkStatusString(std::string &str);
void buildNetworkHostsString(std::string &str); void buildNetworkHostsString(std::string &str);
private: private:
CConf m_conf; CConf m_conf;
CModem* m_modem; CModem* m_modem;
CDStarControl* m_dstar; CDStarControl* m_dstar;
CDMRControl* m_dmr; CDMRControl* m_dmr;
CYSFControl* m_ysf; CYSFControl* m_ysf;
CP25Control* m_p25; CP25Control* m_p25;
CNXDNControl* m_nxdn; CNXDNControl* m_nxdn;
CM17Control* m_m17; CM17Control* m_m17;
CPOCSAGControl* m_pocsag; CPOCSAGControl* m_pocsag;
CFMControl* m_fm; CFMControl* m_fm;
CAX25Control* m_ax25; CAX25Control* m_ax25;
CDStarNetwork* m_dstarNetwork; CDStarNetwork* m_dstarNetwork;
CDMRNetwork* m_dmrNetwork; CDMRNetwork* m_dmrNetwork;
CYSFNetwork* m_ysfNetwork; CYSFNetwork* m_ysfNetwork;
CP25Network* m_p25Network; CP25Network* m_p25Network;
INXDNNetwork* m_nxdnNetwork; INXDNNetwork* m_nxdnNetwork;
CM17Network* m_m17Network; CM17Network* m_m17Network;
CPOCSAGNetwork* m_pocsagNetwork; CPOCSAGNetwork* m_pocsagNetwork;
CFMNetwork* m_fmNetwork; CFMNetwork* m_fmNetwork;
CAX25Network* m_ax25Network; CAX25Network* m_ax25Network;
unsigned char m_mode; unsigned char m_mode;
unsigned int m_dstarRFModeHang; unsigned int m_dstarRFModeHang;
unsigned int m_dmrRFModeHang; unsigned int m_dmrRFModeHang;
unsigned int m_ysfRFModeHang; unsigned int m_ysfRFModeHang;
unsigned int m_p25RFModeHang; unsigned int m_p25RFModeHang;
unsigned int m_nxdnRFModeHang; unsigned int m_nxdnRFModeHang;
unsigned int m_m17RFModeHang; unsigned int m_m17RFModeHang;
unsigned int m_fmRFModeHang; unsigned int m_fmRFModeHang;
unsigned int m_dstarNetModeHang; unsigned int m_dstarNetModeHang;
unsigned int m_dmrNetModeHang; unsigned int m_dmrNetModeHang;
unsigned int m_ysfNetModeHang; unsigned int m_ysfNetModeHang;
unsigned int m_p25NetModeHang; unsigned int m_p25NetModeHang;
unsigned int m_nxdnNetModeHang; unsigned int m_nxdnNetModeHang;
unsigned int m_m17NetModeHang; unsigned int m_m17NetModeHang;
unsigned int m_pocsagNetModeHang; unsigned int m_pocsagNetModeHang;
unsigned int m_fmNetModeHang; unsigned int m_fmNetModeHang;
CTimer m_modeTimer; CTimer m_modeTimer;
CTimer m_dmrTXTimer; CTimer m_dmrTXTimer;
CTimer m_cwIdTimer; CTimer m_cwIdTimer;
bool m_duplex; bool m_duplex;
unsigned int m_timeout; unsigned int m_timeout;
bool m_dstarEnabled; bool m_dstarEnabled;
bool m_dmrEnabled; bool m_dmrEnabled;
bool m_ysfEnabled; bool m_ysfEnabled;
bool m_p25Enabled; bool m_p25Enabled;
bool m_nxdnEnabled; bool m_nxdnEnabled;
bool m_m17Enabled; bool m_m17Enabled;
bool m_pocsagEnabled; bool m_pocsagEnabled;
bool m_fmEnabled; bool m_fmEnabled;
bool m_ax25Enabled; bool m_ax25Enabled;
unsigned int m_cwIdTime; unsigned int m_cwIdTime;
CDMRLookup* m_dmrLookup; CDMRLookup* m_dmrLookup;
CNXDNLookup* m_nxdnLookup; CNXDNLookup* m_nxdnLookup;
std::string m_callsign; std::string m_callsign;
unsigned int m_id; unsigned int m_id;
std::string m_cwCallsign; std::string m_cwCallsign;
bool m_lockFileEnabled; bool m_lockFileEnabled;
std::string m_lockFileName; std::string m_lockFileName;
CRemoteControl* m_remoteControl; CRemoteControl* m_remoteControl;
bool m_fixedMode; bool m_fixedMode;
void readParams(); void readParams();
bool createModem(); bool createModem();
bool createDStarNetwork(); bool createDStarNetwork();
bool createDMRNetwork(); bool createDMRNetwork();
bool createYSFNetwork(); bool createYSFNetwork();
bool createP25Network(); bool createP25Network();
bool createNXDNNetwork(); bool createNXDNNetwork();
bool createM17Network(); bool createM17Network();
bool createPOCSAGNetwork(); bool createPOCSAGNetwork();
bool createFMNetwork(); bool createFMNetwork();
bool createAX25Network(); bool createAX25Network();
void remoteControl(); void remoteControl();
void processModeCommand(unsigned char mode, unsigned int timeout); void processModeCommand(unsigned char mode, unsigned int timeout);
void processEnableCommand(bool& mode, bool enabled); void processEnableCommand(bool& mode, bool enabled);
void setMode(unsigned char mode); void setMode(unsigned char mode);
void createLockFile(const char* mode) const; void createLockFile(const char* mode) const;
void removeLockFile() const; void removeLockFile() const;
void writeJSONMode(const std::string& mode); void writeJSONMode(const std::string& mode);
void writeJSONMessage(const std::string& message); void writeJSONMessage(const std::string& message);
static void onDisplay(const std::string& message);
static void onCommand(const std::string& command);
}; };
#endif #endif

View File

@@ -23,10 +23,11 @@
#include <cstring> #include <cstring>
CMQTTConnection::CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, unsigned int keepalive, MQTT_QOS qos) : CMQTTConnection::CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const std::vector<std::pair<std::string, void (*)(const std::string&)>>& subs, unsigned int keepalive, MQTT_QOS qos) :
m_host(host), m_host(host),
m_port(port), m_port(port),
m_name(name), m_name(name),
m_subs(subs),
m_keepalive(keepalive), m_keepalive(keepalive),
m_qos(qos), m_qos(qos),
m_mosq(NULL), m_mosq(NULL),
@@ -54,6 +55,8 @@ bool CMQTTConnection::open()
} }
::mosquitto_connect_callback_set(m_mosq, onConnect); ::mosquitto_connect_callback_set(m_mosq, onConnect);
::mosquitto_subscribe_callback_set(m_mosq, onSubscribe);
::mosquitto_message_callback_set(m_mosq, onMessage);
::mosquitto_disconnect_callback_set(m_mosq, onDisconnect); ::mosquitto_disconnect_callback_set(m_mosq, onDisconnect);
int rc = ::mosquitto_connect(m_mosq, m_host.c_str(), m_port, m_keepalive); int rc = ::mosquitto_connect(m_mosq, m_host.c_str(), m_port, m_keepalive);
@@ -111,9 +114,57 @@ void CMQTTConnection::onConnect(mosquitto* mosq, void* obj, int rc)
assert(obj != NULL); assert(obj != NULL);
::fprintf(stdout, "MQTT: on_connect: %s\n", ::mosquitto_connack_string(rc)); ::fprintf(stdout, "MQTT: on_connect: %s\n", ::mosquitto_connack_string(rc));
if (rc != 0) {
::mosquitto_disconnect(mosq);
return;
}
CMQTTConnection* p = static_cast<CMQTTConnection*>(obj); CMQTTConnection* p = static_cast<CMQTTConnection*>(obj);
p->m_connected = true; p->m_connected = true;
for (std::vector<std::pair<std::string, void (*)(const std::string&)>>::const_iterator it = p->m_subs.cbegin(); it != p->m_subs.cend(); ++it) {
std::string topic = (*it).first;
char topicEx[100U];
::sprintf(topicEx, "%s/%s", p->m_name.c_str(), topic.c_str());
rc = ::mosquitto_subscribe(mosq, NULL, topicEx, MQTT_QOS_AT_LEAST_ONCE);
if (rc != MOSQ_ERR_SUCCESS) {
::fprintf(stderr, "MQTT: error subscribing to %s - %s\n", topicEx, ::mosquitto_strerror(rc));
::mosquitto_disconnect(mosq);
}
}
}
void CMQTTConnection::onSubscribe(mosquitto* mosq, void* obj, int mid, int qosCount, const int* grantedQOS)
{
assert(mosq != NULL);
assert(obj != NULL);
assert(grantedQOS != NULL);
for (int i = 0; i < qosCount; i++)
::fprintf(stdout, "MQTT: on_subscribe: %d:%d\n", i, grantedQOS[i]);
}
void CMQTTConnection::onMessage(mosquitto* mosq, void* obj, const mosquitto_message* message)
{
assert(mosq != NULL);
assert(obj != NULL);
assert(message != NULL);
CMQTTConnection* p = static_cast<CMQTTConnection*>(obj);
for (std::vector<std::pair<std::string, void (*)(const std::string&)>>::const_iterator it = p->m_subs.cbegin(); it != p->m_subs.cend(); ++it) {
std::string topic = (*it).first;
char topicEx[100U];
::sprintf(topicEx, "%s/%s", p->m_name.c_str(), topic.c_str());
if (::strcmp(topicEx, message->topic) == 0) {
(*it).second(std::string((char*)message->payload, message->payloadlen));
break;
}
}
} }
void CMQTTConnection::onDisconnect(mosquitto* mosq, void* obj, int rc) void CMQTTConnection::onDisconnect(mosquitto* mosq, void* obj, int rc)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2022 by Jonathan Naylor G4KLX * Copyright (C) 2022,2023 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <mosquitto.h> #include <mosquitto.h>
#include <vector>
#include <string> #include <string>
enum MQTT_QOS { enum MQTT_QOS {
@@ -31,7 +32,7 @@ enum MQTT_QOS {
class CMQTTConnection { class CMQTTConnection {
public: public:
CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, 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 std::string&)>>& subs, unsigned int keepalive, MQTT_QOS qos = MQTT_QOS_EXACTLY_ONCE);
~CMQTTConnection(); ~CMQTTConnection();
bool open(); bool open();
@@ -44,12 +45,15 @@ private:
std::string m_host; std::string m_host;
unsigned short m_port; unsigned short m_port;
std::string m_name; std::string m_name;
std::vector<std::pair<std::string, void (*)(const std::string&)>> m_subs;
unsigned int m_keepalive; unsigned int m_keepalive;
MQTT_QOS m_qos; MQTT_QOS m_qos;
mosquitto* m_mosq; mosquitto* m_mosq;
bool m_connected; bool m_connected;
static void onConnect(mosquitto* mosq, void* obj, int rc); static void onConnect(mosquitto* mosq, void* obj, int rc);
static void onSubscribe(mosquitto* mosq, void* obj, int mid, int qosCount, const int* grantedQOS);
static void onMessage(mosquitto* mosq, void* obj, const mosquitto_message* message);
static void onDisconnect(mosquitto* mosq, void* obj, int rc); static void onDisconnect(mosquitto* mosq, void* obj, int rc);
}; };