Merge pull request #103 from f1rmb/f1rmb_remote_control

Implement remote command support.
This commit is contained in:
Jonathan Naylor 2021-03-22 22:06:31 +00:00 committed by GitHub
commit fdbe0e0fb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 533 additions and 74 deletions

View file

@ -40,7 +40,8 @@ enum SECTION {
SECTION_XLX_NETWORK,
SECTION_GPSD,
SECTION_APRS,
SECTION_DYNAMIC_TG_CONTROL
SECTION_DYNAMIC_TG_CONTROL,
SECTION_REMOTE_CONTROL
};
CConf::CConf(const std::string& file) :
@ -182,7 +183,10 @@ m_aprsPort(0U),
m_aprsSuffix(),
m_aprsDescription(),
m_dynamicTGControlEnabled(false),
m_dynamicTGControlPort(3769U)
m_dynamicTGControlPort(3769U),
m_remoteControlEnabled(false),
m_remoteControlAddress("127.0.0.1"),
m_remoteControlPort(0U)
{
}
@ -232,6 +236,8 @@ bool CConf::read()
section = SECTION_APRS;
else if (::strncmp(buffer, "[Dynamic TG Control]", 20U) == 0)
section = SECTION_DYNAMIC_TG_CONTROL;
else if (::strncmp(buffer, "[Remote Control]", 16U) == 0)
section = SECTION_REMOTE_CONTROL;
else
section = SECTION_NONE;
@ -977,6 +983,13 @@ bool CConf::read()
m_dynamicTGControlEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Port") == 0)
m_dynamicTGControlPort = (unsigned int)::atoi(value);
} else if (section == SECTION_REMOTE_CONTROL) {
if (::strcmp(key, "Enable") == 0)
m_remoteControlEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Address") == 0)
m_remoteControlAddress = value;
else if (::strcmp(key, "Port") == 0)
m_remoteControlPort = (unsigned int)::atoi(value);
}
}
@ -1687,3 +1700,18 @@ unsigned int CConf::getDynamicTGControlPort() const
{
return m_dynamicTGControlPort;
}
bool CConf::getRemoteControlEnabled() const
{
return m_remoteControlEnabled;
}
std::string CConf::getRemoteControlAddress() const
{
return m_remoteControlAddress;
}
unsigned int CConf::getRemoteControlPort() const
{
return m_remoteControlPort;
}

9
Conf.h
View file

@ -241,6 +241,11 @@ public:
bool getDynamicTGControlEnabled() const;
unsigned int getDynamicTGControlPort() const;
// The Remote Control section
bool getRemoteControlEnabled() const;
std::string getRemoteControlAddress() const;
unsigned int getRemoteControlPort() const;
private:
std::string m_file;
bool m_daemon;
@ -393,6 +398,10 @@ private:
bool m_dynamicTGControlEnabled;
unsigned int m_dynamicTGControlPort;
bool m_remoteControlEnabled;
std::string m_remoteControlAddress;
unsigned int m_remoteControlPort;
};
#endif

View file

@ -27,7 +27,6 @@
#include "PassAllPC.h"
#include "PassAllTG.h"
#include "DMRFullLC.h"
#include "XLXVoice.h"
#include "Version.h"
#include "Thread.h"
#include "DMRLC.h"
@ -159,6 +158,7 @@ m_xlxUserControl(true),
m_xlxModule(),
m_rptRewrite(NULL),
m_xlxRewrite(NULL),
m_xlxVoice(NULL),
m_dmr1NetRewrites(),
m_dmr1RFRewrites(),
m_dmr1SrcRewrites(),
@ -185,10 +185,17 @@ m_socket(NULL),
m_writer(NULL),
m_callsign(),
m_txFrequency(0U),
m_rxFrequency(0U)
m_rxFrequency(0U),
#if defined(USE_GPSD)
,m_gpsd(NULL)
m_gpsd(NULL),
#endif
m_network1Enabled(false),
m_network2Enabled(false),
m_network3Enabled(false),
m_network4Enabled(false),
m_network5Enabled(false),
m_networkXlxEnabled(false),
m_remoteControl(NULL)
{
CUDPSocket::startup();
@ -354,6 +361,13 @@ int CDMRGateway::run()
}
#endif
m_network1Enabled = m_conf.getDMRNetwork1Enabled();
m_network2Enabled = m_conf.getDMRNetwork2Enabled();
m_network3Enabled = m_conf.getDMRNetwork3Enabled();
m_network4Enabled = m_conf.getDMRNetwork4Enabled();
m_network5Enabled = m_conf.getDMRNetwork5Enabled();
m_networkXlxEnabled = m_conf.getXLXNetworkEnabled();
LogInfo(HEADER1);
LogInfo(HEADER2);
LogInfo(HEADER3);
@ -409,13 +423,12 @@ int CDMRGateway::run()
bool ruleTrace = m_conf.getRuleTrace();
LogInfo("Rule trace: %s", ruleTrace ? "yes" : "no");
if (m_conf.getXLXNetworkEnabled()) {
if (m_networkXlxEnabled && m_conf.getXLXNetworkEnabled()) {
ret = createXLXNetwork();
if (!ret)
return 1;
}
CXLXVoice* xlxVoice = NULL;
if (m_conf.getVoiceEnabled()) {
std::string language = m_conf.getVoiceLanguage();
std::string directory = m_conf.getVoiceDirectory();
@ -426,40 +439,59 @@ int CDMRGateway::run()
LogInfo(" Directory: %s", directory.c_str());
if (m_xlxNetwork != NULL) {
xlxVoice = new CXLXVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG);
bool ret = xlxVoice->open();
m_xlxVoice = new CXLXVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG);
bool ret = m_xlxVoice->open();
if (!ret) {
delete xlxVoice;
xlxVoice = NULL;
delete m_xlxVoice;
m_xlxVoice = NULL;
}
}
}
if (m_conf.getDMRNetwork1Enabled()) {
bool remoteControlEnabled = m_conf.getRemoteControlEnabled();
if (remoteControlEnabled) {
std::string address = m_conf.getRemoteControlAddress();
unsigned int port = m_conf.getRemoteControlPort();
LogInfo("Remote Control Parameters");
LogInfo(" Address: %s", address.c_str());
LogInfo(" Port: %u", port);
m_remoteControl = new CRemoteControl(this, address, port);
ret = m_remoteControl->open();
if (!ret) {
LogInfo("Failed to open Remove Control Socket");
delete m_remoteControl;
m_remoteControl = NULL;
}
}
if (m_network1Enabled && m_conf.getDMRNetwork1Enabled()) {
ret = createDMRNetwork1();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork2Enabled()) {
if (m_network2Enabled && m_conf.getDMRNetwork2Enabled()) {
ret = createDMRNetwork2();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork3Enabled()) {
if (m_network3Enabled && m_conf.getDMRNetwork3Enabled()) {
ret = createDMRNetwork3();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork4Enabled()) {
if (m_network4Enabled && m_conf.getDMRNetwork4Enabled()) {
ret = createDMRNetwork4();
if (!ret)
return 1;
}
if (m_conf.getDMRNetwork5Enabled()) {
if (m_network5Enabled && m_conf.getDMRNetwork5Enabled()) {
ret = createDMRNetwork5();
if (!ret)
return 1;
@ -510,25 +542,25 @@ int CDMRGateway::run()
LogMessage("DMRGateway-%s is running", VERSION);
while (!m_killed) {
if (m_xlxNetwork != NULL) {
if (m_networkXlxEnabled && (m_xlxNetwork != NULL)) {
bool connected = m_xlxNetwork->isConnected();
if (connected && !m_xlxConnected) {
if (m_xlxReflector >= 4001U && m_xlxReflector <= 4026U) {
writeXLXLink(m_xlxId, m_xlxReflector, m_xlxNetwork);
char c = ('A' + (m_xlxReflector % 100U)) - 1U;
LogMessage("XLX, Linking to reflector XLX%03u %c", m_xlxNumber, c);
if (xlxVoice != NULL)
xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
if (m_xlxVoice != NULL)
m_xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
} else if (m_xlxRoom >= 4001U && m_xlxRoom <= 4026U) {
writeXLXLink(m_xlxId, m_xlxRoom, m_xlxNetwork);
char c = ('A' + (m_xlxRoom % 100U)) - 1U;
LogMessage("XLX, Linking to reflector XLX%03u %c", m_xlxNumber, c);
if (xlxVoice != NULL)
xlxVoice->linkedTo(m_xlxNumber, m_xlxRoom);
if (m_xlxVoice != NULL)
m_xlxVoice->linkedTo(m_xlxNumber, m_xlxRoom);
m_xlxReflector = m_xlxRoom;
} else {
if (xlxVoice != NULL)
xlxVoice->linkedTo(m_xlxNumber, 0U);
if (m_xlxVoice != NULL)
m_xlxVoice->linkedTo(m_xlxNumber, 0U);
}
m_xlxConnected = true;
@ -540,8 +572,8 @@ int CDMRGateway::run()
} else if (!connected && m_xlxConnected) {
LogMessage("XLX, Unlinking from XLX%03u due to loss of connection", m_xlxNumber);
if (xlxVoice != NULL)
xlxVoice->unlinked();
if (m_xlxVoice != NULL)
m_xlxVoice->unlinked();
m_xlxConnected = false;
m_xlxRelink.stop();
@ -572,11 +604,11 @@ int CDMRGateway::run()
}
m_xlxReflector = m_xlxRoom;
if (xlxVoice != NULL) {
if (m_xlxVoice != NULL) {
if (m_xlxReflector < 4001U || m_xlxReflector > 4026U)
xlxVoice->linkedTo(m_xlxNumber, 0U);
m_xlxVoice->linkedTo(m_xlxNumber, 0U);
else
xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
m_xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
}
}
}
@ -596,7 +628,9 @@ int CDMRGateway::run()
m_xlxRelink.start();
m_xlxRewrite->process(data, false);
if (m_networkXlxEnabled) {
m_xlxNetwork->write(data);
}
m_status[slotNo] = DMRGWS_XLXREFLECTOR;
timer[slotNo]->setTimeout(rfTimeout);
timer[slotNo]->start();
@ -629,16 +663,16 @@ int CDMRGateway::run()
timer[slotNo]->setTimeout(rfTimeout);
timer[slotNo]->start();
if (xlxVoice != NULL) {
if (m_xlxVoice != NULL) {
unsigned char type = data.getDataType();
if (type == DT_TERMINATOR_WITH_LC) {
if (m_xlxConnected) {
if (m_xlxReflector != 4000U)
xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
m_xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector);
else
xlxVoice->linkedTo(m_xlxNumber, 0U);
m_xlxVoice->linkedTo(m_xlxNumber, 0U);
} else {
xlxVoice->unlinked();
m_xlxVoice->unlinked();
}
}
}
@ -666,7 +700,7 @@ int CDMRGateway::run()
PROCESS_RESULT result = RESULT_UNMATCHED;
if (m_dmrNetwork1 != NULL) {
if (m_network1Enabled && (m_dmrNetwork1 != NULL)) {
// Rewrite the slot and/or TG or neither
for (std::vector<CRewrite*>::iterator it = m_dmr1RFRewrites.begin(); it != m_dmr1RFRewrites.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
@ -688,7 +722,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork2 != NULL) {
if (m_network2Enabled && (m_dmrNetwork2 != NULL)) {
// Rewrite the slot and/or TG or neither
for (std::vector<CRewrite*>::iterator it = m_dmr2RFRewrites.begin(); it != m_dmr2RFRewrites.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
@ -711,7 +745,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork3 != NULL) {
if (m_network3Enabled && (m_dmrNetwork3 != NULL)) {
// Rewrite the slot and/or TG or neither
for (std::vector<CRewrite*>::iterator it = m_dmr3RFRewrites.begin(); it != m_dmr3RFRewrites.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
@ -734,7 +768,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork4 != NULL) {
if (m_network4Enabled && (m_dmrNetwork4 != NULL)) {
// Rewrite the slot and/or TG or neither
for (std::vector<CRewrite*>::iterator it = m_dmr4RFRewrites.begin(); it != m_dmr4RFRewrites.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
@ -757,7 +791,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork5 != NULL) {
if (m_network5Enabled && (m_dmrNetwork5 != NULL)) {
// Rewrite the slot and/or TG or neither
for (std::vector<CRewrite*>::iterator it = m_dmr5RFRewrites.begin(); it != m_dmr5RFRewrites.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
@ -780,7 +814,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork1 != NULL) {
if (m_network1Enabled && (m_dmrNetwork1 != NULL)) {
for (std::vector<CRewrite*>::iterator it = m_dmr1Passalls.begin(); it != m_dmr1Passalls.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
if (res != RESULT_UNMATCHED) {
@ -802,7 +836,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork2 != NULL) {
if (m_network2Enabled && (m_dmrNetwork2 != NULL)) {
for (std::vector<CRewrite*>::iterator it = m_dmr2Passalls.begin(); it != m_dmr2Passalls.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
if (res != RESULT_UNMATCHED) {
@ -824,7 +858,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork3 != NULL) {
if (m_network3Enabled && (m_dmrNetwork3 != NULL)) {
for (std::vector<CRewrite*>::iterator it = m_dmr3Passalls.begin(); it != m_dmr3Passalls.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
if (res != RESULT_UNMATCHED) {
@ -846,7 +880,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork4 != NULL) {
if (m_network4Enabled && (m_dmrNetwork4 != NULL)) {
for (std::vector<CRewrite*>::iterator it = m_dmr4Passalls.begin(); it != m_dmr4Passalls.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
if (res != RESULT_UNMATCHED) {
@ -868,7 +902,7 @@ int CDMRGateway::run()
}
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork5 != NULL) {
if (m_network5Enabled && (m_dmrNetwork5 != NULL)) {
for (std::vector<CRewrite*>::iterator it = m_dmr5Passalls.begin(); it != m_dmr5Passalls.end(); ++it) {
PROCESS_RESULT res = (*it)->process(data, trace);
if (res != RESULT_UNMATCHED) {
@ -894,7 +928,7 @@ int CDMRGateway::run()
}
}
if (m_xlxNetwork != NULL) {
if (m_networkXlxEnabled && (m_xlxNetwork != NULL)) {
ret = m_xlxNetwork->read(data);
if (ret) {
if (m_status[m_xlxSlot] == DMRGWS_NONE || m_status[m_xlxSlot] == DMRGWS_XLXREFLECTOR) {
@ -914,7 +948,7 @@ int CDMRGateway::run()
}
}
if (m_dmrNetwork1 != NULL) {
if (m_network1Enabled && (m_dmrNetwork1 != NULL)) {
ret = m_dmrNetwork1->read(data);
if (ret) {
unsigned int slotNo = data.getSlotNo();
@ -964,7 +998,7 @@ int CDMRGateway::run()
m_repeater->writeBeacon();
}
if (m_dmrNetwork2 != NULL) {
if (m_network2Enabled && (m_dmrNetwork2 != NULL)) {
ret = m_dmrNetwork2->read(data);
if (ret) {
unsigned int slotNo = data.getSlotNo();
@ -1014,7 +1048,7 @@ int CDMRGateway::run()
m_repeater->writeBeacon();
}
if (m_dmrNetwork3 != NULL) {
if (m_network3Enabled && (m_dmrNetwork3 != NULL)) {
ret = m_dmrNetwork3->read(data);
if (ret) {
unsigned int slotNo = data.getSlotNo();
@ -1064,7 +1098,7 @@ int CDMRGateway::run()
m_repeater->writeBeacon();
}
if (m_dmrNetwork4 != NULL) {
if (m_network4Enabled && (m_dmrNetwork4 != NULL)) {
ret = m_dmrNetwork4->read(data);
if (ret) {
unsigned int slotNo = data.getSlotNo();
@ -1114,7 +1148,7 @@ int CDMRGateway::run()
m_repeater->writeBeacon();
}
if (m_dmrNetwork5 != NULL) {
if (m_network5Enabled && (m_dmrNetwork5 != NULL)) {
ret = m_dmrNetwork5->read(data);
if (ret) {
unsigned int slotNo = data.getSlotNo();
@ -1168,8 +1202,8 @@ int CDMRGateway::run()
processTalkerAlias();
if (xlxVoice != NULL) {
ret = xlxVoice->read(data);
if (m_networkXlxEnabled && (m_xlxVoice != NULL)) {
ret = m_xlxVoice->read(data);
if (ret) {
m_repeater->write(data);
m_status[m_xlxSlot] = DMRGWS_XLXREFLECTOR;
@ -1187,6 +1221,8 @@ int CDMRGateway::run()
if (m_socket != NULL)
processDynamicTGControl();
remoteControl();
unsigned int ms = stopWatch.elapsed();
stopWatch.start();
@ -1215,8 +1251,8 @@ int CDMRGateway::run()
if (m_xlxReflectors != NULL)
m_xlxReflectors->clock(ms);
if (xlxVoice != NULL)
xlxVoice->clock(ms);
if (m_xlxVoice != NULL)
m_xlxVoice->clock(ms);
#if defined(USE_GPSD)
if (m_gpsd != NULL)
@ -1241,11 +1277,16 @@ int CDMRGateway::run()
CThread::sleep(10U);
}
delete xlxVoice;
delete m_xlxVoice;
m_repeater->close();
delete m_repeater;
if (m_remoteControl != NULL) {
m_remoteControl->close();
delete m_remoteControl;
}
#if defined(USE_GPSD)
if (m_gpsd != NULL) {
m_gpsd->close();
@ -1491,6 +1532,8 @@ bool CDMRGateway::createDMRNetwork1()
m_dmr1NetRewrites.push_back(netPassAllPC);
}
m_dmrNetwork1->enable(true);
return true;
}
@ -1658,6 +1701,8 @@ bool CDMRGateway::createDMRNetwork2()
m_dmr2NetRewrites.push_back(netPassAllPC);
}
m_dmrNetwork2->enable(true);
return true;
}
@ -1825,6 +1870,8 @@ bool CDMRGateway::createDMRNetwork3()
m_dmr3NetRewrites.push_back(netPassAllPC);
}
m_dmrNetwork3->enable(true);
return true;
}
@ -1992,6 +2039,8 @@ bool CDMRGateway::createDMRNetwork4()
m_dmr4NetRewrites.push_back(netPassAllPC);
}
m_dmrNetwork4->enable(true);
return true;
}
@ -2159,6 +2208,8 @@ bool CDMRGateway::createDMRNetwork5()
m_dmr5NetRewrites.push_back(netPassAllPC);
}
m_dmrNetwork5->enable(true);
return true;
}
@ -2286,6 +2337,8 @@ bool CDMRGateway::linkXLX(unsigned int number)
LogMessage("XLX, Connecting to XLX%03u", m_xlxNumber);
m_xlxNetwork->enable(m_networkXlxEnabled);
return true;
}
@ -2412,19 +2465,19 @@ void CDMRGateway::processRadioPosition()
if (!ret)
return;
if (m_dmrNetwork1 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK1 || m_status[2U] == DMRGWS_DMRNETWORK1))
if (m_network1Enabled && (m_dmrNetwork1 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK1 || m_status[2U] == DMRGWS_DMRNETWORK1))
m_dmrNetwork1->writeRadioPosition(buffer, length);
if (m_dmrNetwork2 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK2 || m_status[2U] == DMRGWS_DMRNETWORK2))
if (m_network2Enabled && (m_dmrNetwork2 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK2 || m_status[2U] == DMRGWS_DMRNETWORK2))
m_dmrNetwork2->writeRadioPosition(buffer, length);
if (m_dmrNetwork3 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK3 || m_status[2U] == DMRGWS_DMRNETWORK3))
if (m_network3Enabled && (m_dmrNetwork3 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK3 || m_status[2U] == DMRGWS_DMRNETWORK3))
m_dmrNetwork3->writeRadioPosition(buffer, length);
if (m_dmrNetwork4 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK4 || m_status[2U] == DMRGWS_DMRNETWORK4))
if (m_network4Enabled && (m_dmrNetwork4 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK4 || m_status[2U] == DMRGWS_DMRNETWORK4))
m_dmrNetwork4->writeRadioPosition(buffer, length);
if (m_dmrNetwork5 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK5 || m_status[2U] == DMRGWS_DMRNETWORK5))
if (m_network5Enabled && (m_dmrNetwork5 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK5 || m_status[2U] == DMRGWS_DMRNETWORK5))
m_dmrNetwork5->writeRadioPosition(buffer, length);
}
@ -2436,19 +2489,19 @@ void CDMRGateway::processTalkerAlias()
if (!ret)
return;
if (m_dmrNetwork1 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK1 || m_status[2U] == DMRGWS_DMRNETWORK1))
if (m_network1Enabled && (m_dmrNetwork1 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK1 || m_status[2U] == DMRGWS_DMRNETWORK1))
m_dmrNetwork1->writeTalkerAlias(buffer, length);
if (m_dmrNetwork2 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK2 || m_status[2U] == DMRGWS_DMRNETWORK2))
if (m_network2Enabled && (m_dmrNetwork2 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK2 || m_status[2U] == DMRGWS_DMRNETWORK2))
m_dmrNetwork2->writeTalkerAlias(buffer, length);
if (m_dmrNetwork3 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK3 || m_status[2U] == DMRGWS_DMRNETWORK3))
if (m_network3Enabled && (m_dmrNetwork3 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK3 || m_status[2U] == DMRGWS_DMRNETWORK3))
m_dmrNetwork3->writeTalkerAlias(buffer, length);
if (m_dmrNetwork4 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK4 || m_status[2U] == DMRGWS_DMRNETWORK4))
if (m_network4Enabled && (m_dmrNetwork4 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK4 || m_status[2U] == DMRGWS_DMRNETWORK4))
m_dmrNetwork4->writeTalkerAlias(buffer, length);
if (m_dmrNetwork5 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK5 || m_status[2U] == DMRGWS_DMRNETWORK5))
if (m_network5Enabled && (m_dmrNetwork5 != NULL) && (m_status[1U] == DMRGWS_DMRNETWORK5 || m_status[2U] == DMRGWS_DMRNETWORK5))
m_dmrNetwork5->writeTalkerAlias(buffer, length);
}
@ -2516,3 +2569,86 @@ void CDMRGateway::processDynamicTGControl()
LogWarning("Unknown dynamic TG control message: %s", buffer);
}
}
void CDMRGateway::remoteControl()
{
if (m_remoteControl == NULL)
return;
REMOTE_COMMAND command = m_remoteControl->getCommand();
switch (command) {
case RCD_ENABLE_NETWORK1:
processEnableCommand(m_dmrNetwork1, "DMR Network 1", m_network1Enabled, true);
break;
case RCD_ENABLE_NETWORK2:
processEnableCommand(m_dmrNetwork2, "DMR Network 2", m_network2Enabled, true);
break;
case RCD_ENABLE_NETWORK3:
processEnableCommand(m_dmrNetwork3, "DMR Network 3", m_network3Enabled, true);
break;
case RCD_ENABLE_NETWORK4:
processEnableCommand(m_dmrNetwork4, "DMR Network 4", m_network4Enabled, true);
break;
case RCD_ENABLE_NETWORK5:
processEnableCommand(m_dmrNetwork5, "DMR Network 5", m_network5Enabled, true);
break;
case RCD_ENABLE_XLX:
if (m_xlxVoice != NULL) {
m_xlxVoice->reset();
}
processEnableCommand(m_xlxNetwork, "XLX Network", m_networkXlxEnabled, true);
break;
case RCD_DISABLE_NETWORK1:
processEnableCommand(m_dmrNetwork1, "DMR Network 1", m_network1Enabled, false);
break;
case RCD_DISABLE_NETWORK2:
processEnableCommand(m_dmrNetwork2, "DMR Network 2", m_network2Enabled, false);
break;
case RCD_DISABLE_NETWORK3:
processEnableCommand(m_dmrNetwork3, "DMR Network 3", m_network3Enabled, false);
break;
case RCD_DISABLE_NETWORK4:
processEnableCommand(m_dmrNetwork4, "DMR Network 4", m_network4Enabled, false);
break;
case RCD_DISABLE_NETWORK5:
processEnableCommand(m_dmrNetwork5, "DMR Network 5", m_network5Enabled, false);
break;
case RCD_DISABLE_XLX:
processEnableCommand(m_xlxNetwork, "XLX Network", m_networkXlxEnabled, false);
break;
default:
break;
}
}
void CDMRGateway::processEnableCommand(CDMRNetwork* network, const std::string& name, bool& mode, bool enabled)
{
LogDebug("Setting '%s' mode current=%s new=%s", name.c_str(), mode ? "true" : "false", enabled ? "true" : "false");
if (network != NULL) {
mode = enabled;
network->enable(enabled);
}
}
void CDMRGateway::buildNetworkStatusString(std::string &str)
{
str = "";
buildNetworkStatusNetworkString(str, "xlx", m_xlxNetwork, m_networkXlxEnabled);
str += " ";
buildNetworkStatusNetworkString(str, "net1", m_dmrNetwork1, m_network1Enabled);
str += " ";
buildNetworkStatusNetworkString(str, "net2", m_dmrNetwork2, m_network2Enabled);
str += " ";
buildNetworkStatusNetworkString(str, "net3", m_dmrNetwork3, m_network3Enabled);
str += " ";
buildNetworkStatusNetworkString(str, "net4", m_dmrNetwork4, m_network4Enabled);
str += " ";
buildNetworkStatusNetworkString(str, "net5", m_dmrNetwork5, m_network5Enabled);
}
void CDMRGateway::buildNetworkStatusNetworkString(std::string &str, const std::string& name, CDMRNetwork* network, bool enabled)
{
str += name + ":"+ (((network == NULL) || (enabled == false)) ? "n/a" : (network->isConnected() ? "conn" : "disc"));
}

View file

@ -19,12 +19,14 @@
#if !defined(DMRGateway_H)
#define DMRGateway_H
#include "RemoteControl.h"
#include "RewriteDynTGNet.h"
#include "RewriteDynTGRF.h"
#include "MMDVMNetwork.h"
#include "DMRNetwork.h"
#include "APRSWriter.h"
#include "Reflectors.h"
#include "XLXVoice.h"
#include "UDPSocket.h"
#include "RewriteTG.h"
#include "DynVoice.h"
@ -53,6 +55,8 @@ public:
int run();
void buildNetworkStatusString(std::string &str);
private:
CConf m_conf;
DMRGW_STATUS* m_status;
@ -89,6 +93,7 @@ private:
char m_xlxModule;
CRewriteTG* m_rptRewrite;
CRewriteTG* m_xlxRewrite;
CXLXVoice* m_xlxVoice;
std::vector<CRewrite*> m_dmr1NetRewrites;
std::vector<CRewrite*> m_dmr1RFRewrites;
std::vector<CRewrite*> m_dmr1SrcRewrites;
@ -119,6 +124,13 @@ private:
#if defined(USE_GPSD)
CGPSD* m_gpsd;
#endif
bool m_network1Enabled;
bool m_network2Enabled;
bool m_network3Enabled;
bool m_network4Enabled;
bool m_network5Enabled;
bool m_networkXlxEnabled;
CRemoteControl* m_remoteControl;
bool createMMDVM();
bool createDMRNetwork1();
@ -141,6 +153,9 @@ private:
void processTalkerAlias();
void createAPRS();
void processDynamicTGControl();
void remoteControl();
void processEnableCommand(CDMRNetwork* network, const std::string& name, bool& mode, bool enabled);
void buildNetworkStatusNetworkString(std::string &str, const std::string& name, CDMRNetwork* network, bool enabled);
};
#endif

View file

@ -153,3 +153,8 @@ Suffix=3
[Dynamic TG Control]
Enabled=1
Port=3769
[Remote Control]
Enable=0
Address=127.0.0.1
Port=7643

View file

@ -40,6 +40,7 @@ m_name(name),
m_location(location),
m_debug(debug),
m_socket(local),
m_enabled(false),
m_status(WAITING_CONNECT),
m_retryTimer(1000U, 10U),
m_timeoutTimer(1000U, 60U),
@ -108,6 +109,14 @@ bool CDMRNetwork::open()
return true;
}
void CDMRNetwork::enable(bool enabled)
{
if (!enabled && m_enabled)
m_rxData.clear();
m_enabled = enabled;
}
bool CDMRNetwork::read(CDMRData& data)
{
if (m_status != RUNNING)
@ -345,9 +354,11 @@ void CDMRNetwork::clock(unsigned int ms)
if (m_debug)
CUtils::dump(1U, "Network Received", m_buffer, length);
if (m_enabled) {
unsigned char len = length;
m_rxData.addData(&len, 1U);
m_rxData.addData(m_buffer, len);
}
} else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) {
if (m_status == RUNNING) {
LogWarning("%s, Login to the master has failed, retrying login ...", m_name.c_str());

View file

@ -39,6 +39,8 @@ public:
bool open();
void enable(bool enabled);
bool read(CDMRData& data);
bool write(const CDMRData& data);
@ -66,6 +68,7 @@ private:
bool m_location;
bool m_debug;
CUDPSocket m_socket;
bool m_enabled;
enum STATUS {
WAITING_CONNECT,

View file

@ -13,7 +13,7 @@ LDFLAGS = -g
OBJECTS = APRSWriter.o BPTC19696.o Conf.o CRC.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREmbeddedData.o DMREMB.o DMRFullLC.o DMRGateway.o \
DMRLC.o DMRNetwork.o DMRSlotType.o DynVoice.o Golay2087.o GPSD.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o \
QR1676.o Reflectors.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o \
QR1676.o Reflectors.o RemoteControl.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o \
RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o Utils.o XLXVoice.o
all: DMRGateway

166
RemoteControl.cpp Normal file
View file

@ -0,0 +1,166 @@
/*
* Copyright (C) 2019,2021 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "RemoteControl.h"
#include "Log.h"
#include "DMRGateway.h"
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
const unsigned int ENABLE_ARGS = 2U;
const unsigned int DISABLE_ARGS = 2U;
const unsigned int BUFFER_LENGTH = 100U;
CRemoteControl::CRemoteControl(CDMRGateway* host, const std::string address, unsigned int port) :
m_host(host),
m_socket(address, port),
m_command(RCD_NONE),
m_args()
{
assert(port > 0U);
}
CRemoteControl::~CRemoteControl()
{
}
bool CRemoteControl::open()
{
return m_socket.open();
}
REMOTE_COMMAND CRemoteControl::getCommand()
{
m_command = RCD_NONE;
m_args.clear();
char command[BUFFER_LENGTH];
char buffer[BUFFER_LENGTH * 2];
std::string replyStr = "OK";
sockaddr_storage address;
unsigned int addrlen;
int ret = m_socket.read((unsigned char*)buffer, BUFFER_LENGTH, address, addrlen);
if (ret > 0) {
buffer[ret] = '\0';
// Make a copy of the original command for logging.
::strcpy(command, buffer);
// Parse the original command into a vector of strings.
char* b = buffer;
char* p = NULL;
while ((p = ::strtok(b, " ")) != NULL) {
b = NULL;
m_args.push_back(std::string(p));
}
if (m_args.at(0U) == "enable" && m_args.size() >= ENABLE_ARGS) {
if (m_args.at(1U) == "net1")
m_command = RCD_ENABLE_NETWORK1;
else if (m_args.at(1U) == "net2")
m_command = RCD_ENABLE_NETWORK2;
else if (m_args.at(1U) == "net3")
m_command = RCD_ENABLE_NETWORK3;
else if (m_args.at(1U) == "net4")
m_command = RCD_ENABLE_NETWORK4;
else if (m_args.at(1U) == "net5")
m_command = RCD_ENABLE_NETWORK5;
else if (m_args.at(1U) == "xlx")
m_command = RCD_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;
else if (m_args.at(1U) == "net2")
m_command = RCD_DISABLE_NETWORK2;
else if (m_args.at(1U) == "net3")
m_command = RCD_DISABLE_NETWORK3;
else if (m_args.at(1U) == "net4")
m_command = RCD_DISABLE_NETWORK4;
else if (m_args.at(1U) == "net5")
m_command = RCD_DISABLE_NETWORK5;
else if (m_args.at(1U) == "xlx")
m_command = RCD_DISABLE_XLX;
else
replyStr = "KO";
} else if (m_args.at(0U) == "status") {
if (m_host != NULL) {
m_host->buildNetworkStatusString(replyStr);
}
else {
replyStr = "KO";
}
m_command = RCD_CONNECTION_STATUS;
}
else
replyStr = "KO";
::snprintf(buffer, BUFFER_LENGTH * 2, "%s remote command of \"%s\" received", ((m_command == RCD_NONE) ? "Invalid" : "Valid"), command);
if (m_command == RCD_NONE) {
m_args.clear();
LogWarning(buffer);
} else {
LogMessage(buffer);
}
m_socket.write((unsigned char*)replyStr.c_str(), replyStr.length(), address, addrlen);
}
return m_command;
}
unsigned int CRemoteControl::getArgCount() const
{
switch (m_command) {
default:
return 0U;
}
}
std::string CRemoteControl::getArgString(unsigned int n) const
{
switch (m_command) {
default:
return "";
}
if (n >= m_args.size())
return "";
return m_args.at(n);
}
unsigned int CRemoteControl::getArgUInt(unsigned int n) const
{
return (unsigned int)::atoi(getArgString(n).c_str());
}
int CRemoteControl::getArgInt(unsigned int n) const
{
return ::atoi(getArgString(n).c_str());
}
void CRemoteControl::close()
{
m_socket.close();
}

71
RemoteControl.h Normal file
View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2019,2021 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef RemoteControl_H
#define RemoteControl_H
#include "UDPSocket.h"
#include <vector>
#include <string>
enum REMOTE_COMMAND {
RCD_ENABLE_NETWORK1,
RCD_ENABLE_NETWORK2,
RCD_ENABLE_NETWORK3,
RCD_ENABLE_NETWORK4,
RCD_ENABLE_NETWORK5,
RCD_ENABLE_XLX,
RCD_DISABLE_NETWORK1,
RCD_DISABLE_NETWORK2,
RCD_DISABLE_NETWORK3,
RCD_DISABLE_NETWORK4,
RCD_DISABLE_NETWORK5,
RCD_DISABLE_XLX,
RCD_CONNECTION_STATUS,
RCD_NONE
};
class CDMRGateway;
class CDMRNetwork;
class CRemoteControl {
public:
CRemoteControl(CDMRGateway* host, const std::string address, unsigned int port);
~CRemoteControl();
bool open();
REMOTE_COMMAND getCommand();
unsigned int getArgCount() const;
std::string getArgString(unsigned int n) const;
unsigned int getArgUInt(unsigned int n) const;
signed int getArgInt(unsigned int n) const;
void close();
private:
CDMRGateway* m_host;
CUDPSocket m_socket;
REMOTE_COMMAND m_command;
std::vector<std::string> m_args;
};
#endif

View file

@ -273,6 +273,19 @@ void CXLXVoice::createVoice(const std::vector<std::string>& words)
m_timer.start();
}
void CXLXVoice::reset()
{
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
m_timer.stop();
m_status = XLXVS_NONE;
m_data.clear();
m_seqNo = 0U;
m_streamId = 0U;
m_sent = 0U;
}
bool CXLXVoice::read(CDMRData& data)
{
if (m_status != XLXVS_SENDING)

View file

@ -50,6 +50,8 @@ public:
void linkedTo(unsigned int number, unsigned int room);
void unlinked();
void reset();
bool read(CDMRData& data);
void clock(unsigned int ms);