Simplify the Host to DMR Gateway protocol.

This commit is contained in:
Jonathan Naylor
2020-08-26 14:20:04 +01:00
parent 6e89e4922f
commit b344248e0a
18 changed files with 375 additions and 380 deletions

View File

@@ -38,7 +38,8 @@ enum SECTION {
SECTION_DMR_NETWORK_4,
SECTION_DMR_NETWORK_5,
SECTION_XLX_NETWORK,
SECTION_DYNAMIC_TG_CONTROL
SECTION_DYNAMIC_TG_CONTROL,
SECTION_GPSD,
};
CConf::CConf(const std::string& file) :
@@ -59,14 +60,9 @@ m_logDisplayLevel(0U),
m_logFileLevel(0U),
m_logFilePath(),
m_logFileRoot(),
m_infoEnabled(false),
m_infoRXFrequency(0U),
m_infoTXFrequency(0U),
m_infoPower(0U),
m_infoLatitude(0.0F),
m_infoLongitude(0.0F),
m_infoHeight(0),
m_infoLocation(),
m_infoDescription(),
m_infoURL(),
m_dmrNetwork1Enabled(false),
@@ -175,7 +171,10 @@ m_xlxNetworkDebug(false),
m_xlxNetworkUserControl(true),
m_xlxNetworkModule(),
m_dynamicTGControlEnabled(false),
m_dynamicTGControlPort(3769U)
m_dynamicTGControlPort(3769U),
m_gpsdEnabled(false),
m_gpsdAddress(),
m_gpsdPort()
{
}
@@ -221,6 +220,8 @@ bool CConf::read()
section = SECTION_DMR_NETWORK_5;
else if (::strncmp(buffer, "[Dynamic TG Control]", 20U) == 0)
section = SECTION_DYNAMIC_TG_CONTROL;
else if (::strncmp(buffer, "[GPSD]", 6U) == 0)
section = SECTION_GPSD;
else
section = SECTION_NONE;
@@ -280,22 +281,12 @@ bool CConf::read()
else if (::strcmp(key, "Directory") == 0)
m_voiceDirectory = value;
} else if (section == SECTION_INFO) {
if (::strcmp(key, "Enabled") == 0)
m_infoEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "TXFrequency") == 0)
m_infoTXFrequency = (unsigned int)::atoi(value);
else if (::strcmp(key, "RXFrequency") == 0)
m_infoRXFrequency = (unsigned int)::atoi(value);
else if (::strcmp(key, "Power") == 0)
m_infoPower = (unsigned int)::atoi(value);
else if (::strcmp(key, "Latitude") == 0)
if (::strcmp(key, "Latitude") == 0)
m_infoLatitude = float(::atof(value));
else if (::strcmp(key, "Longitude") == 0)
m_infoLongitude = float(::atof(value));
else if (::strcmp(key, "Height") == 0)
m_infoHeight = ::atoi(value);
else if (::strcmp(key, "Location") == 0)
m_infoLocation = value;
else if (::strcmp(key, "Description") == 0)
m_infoDescription = value;
else if (::strcmp(key, "URL") == 0)
@@ -946,6 +937,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_GPSD) {
if (::strcmp(key, "Enable") == 0)
m_gpsdEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Address") == 0)
m_gpsdAddress = value;
else if (::strcmp(key, "Port") == 0)
m_gpsdPort = value;
}
}
@@ -1034,26 +1032,6 @@ std::string CConf::getVoiceDirectory() const
return m_voiceDirectory;
}
bool CConf::getInfoEnabled() const
{
return m_infoEnabled;
}
unsigned int CConf::getInfoRXFrequency() const
{
return m_infoRXFrequency;
}
unsigned int CConf::getInfoTXFrequency() const
{
return m_infoTXFrequency;
}
unsigned int CConf::getInfoPower() const
{
return m_infoPower;
}
float CConf::getInfoLatitude() const
{
return m_infoLatitude;
@@ -1069,11 +1047,6 @@ int CConf::getInfoHeight() const
return m_infoHeight;
}
std::string CConf::getInfoLocation() const
{
return m_infoLocation;
}
std::string CConf::getInfoDescription() const
{
return m_infoDescription;
@@ -1631,3 +1604,18 @@ unsigned int CConf::getDynamicTGControlPort() const
{
return m_dynamicTGControlPort;
}
bool CConf::getGPSDEnabled() const
{
return m_gpsdEnabled;
}
std::string CConf::getGPSDAddress() const
{
return m_gpsdAddress;
}
std::string CConf::getGPSDPort() const
{
return m_gpsdPort;
}

19
Conf.h
View File

@@ -100,14 +100,9 @@ public:
std::string getVoiceDirectory() const;
// The Info section
bool getInfoEnabled() const;
unsigned int getInfoRXFrequency() const;
unsigned int getInfoTXFrequency() const;
unsigned int getInfoPower() const;
float getInfoLatitude() const;
float getInfoLongitude() const;
int getInfoHeight() const;
std::string getInfoLocation() const;
std::string getInfoDescription() const;
std::string getInfoURL() const;
@@ -232,6 +227,11 @@ public:
bool getDynamicTGControlEnabled() const;
unsigned int getDynamicTGControlPort() const;
// The GPSD section
bool getGPSDEnabled() const;
std::string getGPSDAddress() const;
std::string getGPSDPort() const;
private:
std::string m_file;
bool m_daemon;
@@ -253,14 +253,9 @@ private:
std::string m_logFilePath;
std::string m_logFileRoot;
bool m_infoEnabled;
unsigned int m_infoRXFrequency;
unsigned int m_infoTXFrequency;
unsigned int m_infoPower;
float m_infoLatitude;
float m_infoLongitude;
int m_infoHeight;
std::string m_infoLocation;
std::string m_infoDescription;
std::string m_infoURL;
@@ -377,6 +372,10 @@ private:
bool m_dynamicTGControlEnabled;
unsigned int m_dynamicTGControlPort;
bool m_gpsdEnabled;
std::string m_gpsdAddress;
std::string m_gpsdPort;
};
#endif

View File

@@ -182,6 +182,9 @@ m_dmr5Passalls(),
m_dynVoices(),
m_dynRF(),
m_socket(NULL)
#if defined(USE_GPSD)
,m_gpsd(NULL)
#endif
{
m_status = new DMRGW_STATUS[3U];
m_status[1U] = DMRGWS_NONE;
@@ -354,7 +357,7 @@ int CDMRGateway::run()
LogMessage("Waiting for MMDVM to connect.....");
while (!m_killed) {
m_configLen = m_repeater->getConfig(m_config);
m_configLen = m_repeater->getShortConfig(m_config);
if (m_configLen > 0U && m_repeater->getId() > 1000U)
break;
@@ -371,6 +374,26 @@ int CDMRGateway::run()
LogMessage("MMDVM has connected");
#if defined(USE_GPSD)
bool gpsdEnabled = m_conf.getGPSDEnabled();
if (gpsdEnabled) {
std::string gpsdAddress = m_conf.getGPSDAddress();
std::string gpsdPort = m_conf.getGPSDPort();
LogInfo("GPSD Parameters");
LogInfo(" Address: %s", gpsdAddress.c_str());
LogInfo(" Port: %s", gpsdPort.c_str());
m_gpsd = new CGPSD(gpsdAddress, gpsdPort, m_dmrNetwork);
ret = m_gpsd->open();
if (!ret) {
delete m_gpsd;
m_gpsd = NULL;
}
}
#endif
bool ruleTrace = m_conf.getRuleTrace();
LogInfo("Rule trace: %s", ruleTrace ? "yes" : "no");
@@ -1131,8 +1154,6 @@ int CDMRGateway::run()
processTalkerAlias();
processHomePosition();
if (xlxVoice != NULL) {
ret = xlxVoice->read(data);
if (ret) {
@@ -1183,6 +1204,11 @@ int CDMRGateway::run()
if (xlxVoice != NULL)
xlxVoice->clock(ms);
#if defined(USE_GPSD)
if (m_gpsd != NULL)
m_gpsd->clock(ms);
#endif
for (std::vector<CDynVoice*>::iterator it = m_dynVoices.begin(); it != m_dynVoices.end(); ++it)
(*it)->clock(ms);
@@ -1203,6 +1229,13 @@ int CDMRGateway::run()
m_repeater->close();
delete m_repeater;
#if defined(USE_GPSD)
if (m_gpsd != NULL) {
m_gpsd->close();
delete m_gpsd;
}
#endif
if (m_dmrNetwork1 != NULL) {
m_dmrNetwork1->close();
delete m_dmrNetwork1;
@@ -1297,11 +1330,9 @@ bool CDMRGateway::createDMRNetwork1()
LogInfo(" Local: random");
LogInfo(" Location Data: %s", location ? "yes" : "no");
m_dmrNetwork1 = new CDMRNetwork(address, port, local, id, password, m_dmr1Name, VERSION, debug);
m_dmrNetwork1 = new CDMRNetwork(address, port, local, id, password, m_dmr1Name, VERSION, location, debug);
std::string options = m_conf.getDMRNetwork1Options();
if (options.empty())
options = m_repeater->getOptions();
if (!options.empty()) {
LogInfo(" Options: %s", options.c_str());
@@ -1310,10 +1341,6 @@ bool CDMRGateway::createDMRNetwork1()
unsigned char config[400U];
unsigned int len = getConfig(m_dmr1Name, config);
if (!location)
::memcpy(config + 30U, "0.00000000.000000", 17U);
m_dmrNetwork1->setConfig(config, len);
bool ret = m_dmrNetwork1->open();
@@ -1323,6 +1350,11 @@ bool CDMRGateway::createDMRNetwork1()
return false;
}
#if defined(USE_GPSD)
if (location)
m_gpsd->addNetwork(m_dmrNetwork1);
#endif
std::vector<CTGRewriteStruct> tgRewrites = m_conf.getDMRNetwork1TGRewrites();
for (std::vector<CTGRewriteStruct>::const_iterator it = tgRewrites.begin(); it != tgRewrites.end(); ++it) {
if ((*it).m_range == 1)
@@ -1465,11 +1497,9 @@ bool CDMRGateway::createDMRNetwork2()
LogInfo(" Local: random");
LogInfo(" Location Data: %s", location ? "yes" : "no");
m_dmrNetwork2 = new CDMRNetwork(address, port, local, id, password, m_dmr2Name, VERSION, debug);
m_dmrNetwork2 = new CDMRNetwork(address, port, local, id, password, m_dmr2Name, VERSION, location, debug);
std::string options = m_conf.getDMRNetwork2Options();
if (options.empty())
options = m_repeater->getOptions();
if (!options.empty()) {
LogInfo(" Options: %s", options.c_str());
@@ -1479,9 +1509,6 @@ bool CDMRGateway::createDMRNetwork2()
unsigned char config[400U];
unsigned int len = getConfig(m_dmr2Name, config);
if (!location)
::memcpy(config + 30U, "0.00000000.000000", 17U);
m_dmrNetwork2->setConfig(config, len);
bool ret = m_dmrNetwork2->open();
@@ -1491,6 +1518,11 @@ bool CDMRGateway::createDMRNetwork2()
return false;
}
#if defined(USE_GPSD)
if (location)
m_gpsd->addNetwork(m_dmrNetwork2);
#endif
std::vector<CTGRewriteStruct> tgRewrites = m_conf.getDMRNetwork2TGRewrites();
for (std::vector<CTGRewriteStruct>::const_iterator it = tgRewrites.begin(); it != tgRewrites.end(); ++it) {
if ((*it).m_range == 1)
@@ -1633,11 +1665,9 @@ bool CDMRGateway::createDMRNetwork3()
LogInfo(" Local: random");
LogInfo(" Location Data: %s", location ? "yes" : "no");
m_dmrNetwork3 = new CDMRNetwork(address, port, local, id, password, m_dmr3Name, VERSION, debug);
m_dmrNetwork3 = new CDMRNetwork(address, port, local, id, password, m_dmr3Name, VERSION, location, debug);
std::string options = m_conf.getDMRNetwork3Options();
if (options.empty())
options = m_repeater->getOptions();
if (!options.empty()) {
LogInfo(" Options: %s", options.c_str());
@@ -1646,10 +1676,6 @@ bool CDMRGateway::createDMRNetwork3()
unsigned char config[400U];
unsigned int len = getConfig(m_dmr3Name, config);
if (!location)
::memcpy(config + 30U, "0.00000000.000000", 17U);
m_dmrNetwork3->setConfig(config, len);
bool ret = m_dmrNetwork3->open();
@@ -1659,6 +1685,11 @@ bool CDMRGateway::createDMRNetwork3()
return false;
}
#if defined(USE_GPSD)
if (location)
m_gpsd->addNetwork(m_dmrNetwork3);
#endif
std::vector<CTGRewriteStruct> tgRewrites = m_conf.getDMRNetwork3TGRewrites();
for (std::vector<CTGRewriteStruct>::const_iterator it = tgRewrites.begin(); it != tgRewrites.end(); ++it) {
if ((*it).m_range == 1)
@@ -1801,11 +1832,9 @@ bool CDMRGateway::createDMRNetwork4()
LogInfo(" Local: random");
LogInfo(" Location Data: %s", location ? "yes" : "no");
m_dmrNetwork4 = new CDMRNetwork(address, port, local, id, password, m_dmr4Name, VERSION, debug);
m_dmrNetwork4 = new CDMRNetwork(address, port, local, id, password, m_dmr4Name, VERSION, location, debug);
std::string options = m_conf.getDMRNetwork4Options();
if (options.empty())
options = m_repeater->getOptions();
if (!options.empty()) {
LogInfo(" Options: %s", options.c_str());
@@ -1814,10 +1843,6 @@ bool CDMRGateway::createDMRNetwork4()
unsigned char config[400U];
unsigned int len = getConfig(m_dmr4Name, config);
if (!location)
::memcpy(config + 30U, "0.00000000.000000", 17U);
m_dmrNetwork4->setConfig(config, len);
bool ret = m_dmrNetwork4->open();
@@ -1827,6 +1852,11 @@ bool CDMRGateway::createDMRNetwork4()
return false;
}
#if defined(USE_GPSD)
if (location)
m_gpsd->addNetwork(m_dmrNetwork4);
#endif
std::vector<CTGRewriteStruct> tgRewrites = m_conf.getDMRNetwork4TGRewrites();
for (std::vector<CTGRewriteStruct>::const_iterator it = tgRewrites.begin(); it != tgRewrites.end(); ++it) {
if ((*it).m_range == 1)
@@ -1969,11 +1999,9 @@ bool CDMRGateway::createDMRNetwork5()
LogInfo(" Local: random");
LogInfo(" Location Data: %s", location ? "yes" : "no");
m_dmrNetwork5 = new CDMRNetwork(address, port, local, id, password, m_dmr5Name, VERSION, debug);
m_dmrNetwork5 = new CDMRNetwork(address, port, local, id, password, m_dmr5Name, VERSION, location, debug);
std::string options = m_conf.getDMRNetwork5Options();
if (options.empty())
options = m_repeater->getOptions();
if (!options.empty()) {
LogInfo(" Options: %s", options.c_str());
@@ -1982,10 +2010,6 @@ bool CDMRGateway::createDMRNetwork5()
unsigned char config[400U];
unsigned int len = getConfig(m_dmr5Name, config);
if (!location)
::memcpy(config + 30U, "0.00000000.000000", 17U);
m_dmrNetwork5->setConfig(config, len);
bool ret = m_dmrNetwork5->open();
@@ -1995,6 +2019,11 @@ bool CDMRGateway::createDMRNetwork5()
return false;
}
#if defined(USE_GPSD)
if (location)
m_gpsd->addNetwork(m_dmrNetwork5);
#endif
std::vector<CTGRewriteStruct> tgRewrites = m_conf.getDMRNetwork5TGRewrites();
for (std::vector<CTGRewriteStruct>::const_iterator it = tgRewrites.begin(); it != tgRewrites.end(); ++it) {
if ((*it).m_range == 1)
@@ -2213,7 +2242,7 @@ bool CDMRGateway::linkXLX(unsigned int number)
m_xlxConnected = false;
m_xlxRelink.stop();
m_xlxNetwork = new CDMRNetwork(reflector->m_address, m_xlxPort, m_xlxLocal, m_xlxId, m_xlxPassword, "XLX", VERSION, m_xlxDebug);
m_xlxNetwork = new CDMRNetwork(reflector->m_address, m_xlxPort, m_xlxLocal, m_xlxId, m_xlxPassword, "XLX", VERSION, false, m_xlxDebug);
unsigned char config[400U];
unsigned int len = getConfig("XLX", config);
@@ -2319,16 +2348,6 @@ unsigned int CDMRGateway::getConfig(const std::string& name, unsigned char* buff
{
assert(buffer != NULL);
bool enabled = m_conf.getInfoEnabled();
if (!enabled) {
LogInfo("%s: Using original configuration message: %*s", name.c_str(), m_configLen, m_config);
::memcpy(buffer, m_config, m_configLen);
return m_configLen;
}
LogInfo("%s: Original configuration message: %*s", name.c_str(), m_configLen, m_config);
char latitude[20U];
float lat = m_conf.getInfoLatitude();
::sprintf(latitude, "%08f", lat);
@@ -2337,25 +2356,18 @@ unsigned int CDMRGateway::getConfig(const std::string& name, unsigned char* buff
float lon = m_conf.getInfoLongitude();
::sprintf(longitude, "%09f", lon);
unsigned int power = m_conf.getInfoPower();
if (power > 99U)
power = 99U;
int height = m_conf.getInfoHeight();
if (height > 999)
height = 999;
unsigned int rxFrequency = m_conf.getInfoRXFrequency();
unsigned int txFrequency = m_conf.getInfoTXFrequency();
std::string location = m_conf.getInfoLocation();
std::string description = m_conf.getInfoDescription();
std::string url = m_conf.getInfoURL();
::sprintf((char*)buffer, "%-8.8s%09u%09u%02u%2.2s%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_config + 0U,
rxFrequency, txFrequency, power, m_config + 28U, latitude, longitude, height, location.c_str(),
description.c_str(), m_config[89U], url.c_str(), m_config + 214U, m_config + 254U);
::sprintf((char*)buffer, "%30.30s%9.9s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%80.80s",
m_config + 0U, latitude, longitude, height, m_config + 30U,
description.c_str(), m_config[50U], url.c_str(), m_config + 51U);
LogInfo("%s: New configuration message: %s", name.c_str(), buffer);
LogInfo("%s: configuration message: %s", name.c_str(), buffer);
return (unsigned int)::strlen((char*)buffer);
}
@@ -2368,9 +2380,6 @@ void CDMRGateway::processRadioPosition()
if (!ret)
return;
if (m_xlxNetwork != NULL && (m_status[1U] == DMRGWS_XLXREFLECTOR || m_status[2U] == DMRGWS_XLXREFLECTOR))
m_xlxNetwork->writeRadioPosition(buffer, length);
if (m_dmrNetwork1 != NULL && (m_status[1U] == DMRGWS_DMRNETWORK1 || m_status[2U] == DMRGWS_DMRNETWORK1))
m_dmrNetwork1->writeRadioPosition(buffer, length);
@@ -2414,33 +2423,6 @@ void CDMRGateway::processTalkerAlias()
m_dmrNetwork5->writeTalkerAlias(buffer, length);
}
void CDMRGateway::processHomePosition()
{
unsigned char buffer[50U];
unsigned int length;
bool ret = m_repeater->readHomePosition(buffer, length);
if (!ret)
return;
if (m_xlxNetwork != NULL)
m_xlxNetwork->writeHomePosition(buffer, length);
if (m_dmrNetwork1 != NULL)
m_dmrNetwork1->writeHomePosition(buffer, length);
if (m_dmrNetwork2 != NULL)
m_dmrNetwork2->writeHomePosition(buffer, length);
if (m_dmrNetwork3 != NULL)
m_dmrNetwork3->writeHomePosition(buffer, length);
if (m_dmrNetwork4 != NULL)
m_dmrNetwork4->writeHomePosition(buffer, length);
if (m_dmrNetwork5 != NULL)
m_dmrNetwork5->writeHomePosition(buffer, length);
}
void CDMRGateway::processDynamicTGControl()
{
unsigned char buffer[100U];

View File

@@ -19,7 +19,6 @@
#if !defined(DMRGateway_H)
#define DMRGateway_H
#include "RepeaterProtocol.h"
#include "RewriteDynTGNet.h"
#include "RewriteDynTGRF.h"
#include "MMDVMNetwork.h"
@@ -31,6 +30,7 @@
#include "Rewrite.h"
#include "Timer.h"
#include "Conf.h"
#include "GPSD.h"
#include <string>
@@ -55,7 +55,7 @@ public:
private:
CConf m_conf;
DMRGW_STATUS* m_status;
IRepeaterProtocol* m_repeater;
CMMDVMNetwork* m_repeater;
unsigned char* m_config;
unsigned int m_configLen;
CDMRNetwork* m_dmrNetwork1;
@@ -111,6 +111,9 @@ private:
std::vector<CDynVoice*> m_dynVoices;
std::vector<CRewriteDynTGRF*> m_dynRF;
CUDPSocket* m_socket;
#if defined(USE_GPSD)
CGPSD* m_gpsd;
#endif
bool createMMDVM();
bool createDMRNetwork1();
@@ -131,7 +134,6 @@ private:
void processRadioPosition();
void processTalkerAlias();
void processHomePosition();
void processDynamicTGControl();
};

View File

@@ -23,14 +23,9 @@ Language=en_GB
Directory=./Audio
[Info]
Enabled=0
RXFrequency=435000000
TXFrequency=435000000
Power=1
Latitude=0.0
Longitude=0.0
Height=0
Location=Nowhere
Description=Multi-Mode Repeater
URL=www.google.co.uk
@@ -137,6 +132,11 @@ Password=PASSWORD
Location=0
Debug=0
[GPSD]
Enable=0
Address=127.0.0.1
Port=2947
[Dynamic TG Control]
Enabled=1
Port=3769

View File

@@ -168,6 +168,7 @@
<ClInclude Include="DMRSlotType.h" />
<ClInclude Include="DynVoice.h" />
<ClInclude Include="Golay2087.h" />
<ClInclude Include="GPSD.h" />
<ClInclude Include="Hamming.h" />
<ClInclude Include="Log.h" />
<ClInclude Include="MMDVMNetwork.h" />
@@ -175,7 +176,6 @@
<ClInclude Include="PassAllTG.h" />
<ClInclude Include="QR1676.h" />
<ClInclude Include="Reflectors.h" />
<ClInclude Include="RepeaterProtocol.h" />
<ClInclude Include="Rewrite.h" />
<ClInclude Include="RewriteDstId.h" />
<ClInclude Include="RewriteDynTGNet.h" />
@@ -213,6 +213,7 @@
<ClCompile Include="DMRSlotType.cpp" />
<ClCompile Include="DynVoice.cpp" />
<ClCompile Include="Golay2087.cpp" />
<ClCompile Include="GPSD.cpp" />
<ClCompile Include="Hamming.cpp" />
<ClCompile Include="Log.cpp" />
<ClCompile Include="MMDVMNetwork.cpp" />
@@ -220,7 +221,6 @@
<ClCompile Include="PassAllTG.cpp" />
<ClCompile Include="QR1676.cpp" />
<ClCompile Include="Reflectors.cpp" />
<ClCompile Include="RepeaterProtocol.cpp" />
<ClCompile Include="Rewrite.cpp" />
<ClCompile Include="RewriteDstId.cpp" />
<ClCompile Include="RewriteDynTGNet.cpp" />

View File

@@ -83,9 +83,6 @@
<ClInclude Include="CRC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RepeaterProtocol.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMREMB.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -143,6 +140,9 @@
<ClInclude Include="DynVoice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GPSD.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Conf.cpp">
@@ -208,9 +208,6 @@
<ClCompile Include="CRC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RepeaterProtocol.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMREMB.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -268,5 +265,8 @@
<ClCompile Include="DynVoice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GPSD.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020 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
@@ -31,13 +31,14 @@ const unsigned int BUFFER_LENGTH = 500U;
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, const std::string& name, const char* version, bool debug) :
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, const std::string& name, const char* version, bool location, bool debug) :
m_address(),
m_port(port),
m_id(NULL),
m_password(password),
m_name(name),
m_version(version),
m_location(location),
m_debug(debug),
m_socket(local),
m_status(WAITING_CONNECT),
@@ -233,13 +234,16 @@ bool CDMRNetwork::writeRadioPosition(const unsigned char* data, unsigned int len
if (m_status != RUNNING)
return false;
if (!m_location)
return false;
unsigned char buffer[50U];
::memcpy(buffer + 0U, "DMRG", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::memcpy(buffer + 8U, data + 8U, length - 8U);
::memcpy(buffer + 8U, data + 4U, length - 4U);
return write(buffer, length);
}
@@ -255,25 +259,28 @@ bool CDMRNetwork::writeTalkerAlias(const unsigned char* data, unsigned int lengt
::memcpy(buffer + 4U, m_id, 4U);
::memcpy(buffer + 8U, data + 8U, length - 8U);
::memcpy(buffer + 8U, data + 4U, length - 4U);
return write(buffer, length);
}
bool CDMRNetwork::writeHomePosition(const unsigned char* data, unsigned int length)
bool CDMRNetwork::writeHomePosition(float latitude, float longitude)
{
if (m_status != RUNNING)
return false;
unsigned char buffer[50U];
if (!m_location)
return false;
char buffer[50U];
::memcpy(buffer + 0U, "RPTG", 4U);
::memcpy(buffer + 4U, m_id, 4U);
::memcpy(buffer + 8U, data + 8U, length - 8U);
::sprintf(buffer + 8U, "%08f%09f", latitude, longitude);
return write(buffer, length);
return write((unsigned char*)buffer, 25U);
}
bool CDMRNetwork::isConnected() const
@@ -497,6 +504,9 @@ bool CDMRNetwork::writeConfig()
::memset(buffer + 222U, ' ', 40U);
::memcpy(buffer + 222U, software, ::strlen(software));
if (!m_location)
::memcpy(buffer + 30U, "0.00000000.000000", 17U);
return write((unsigned char*)buffer, m_configLen + 8U);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020 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
@@ -30,7 +30,7 @@
class CDMRNetwork
{
public:
CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, const std::string& name, const char* version, bool debug);
CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, const std::string& name, const char* version, bool location, bool debug);
~CDMRNetwork();
void setOptions(const std::string& options);
@@ -47,7 +47,7 @@ public:
bool writeTalkerAlias(const unsigned char* data, unsigned int length);
bool writeHomePosition(const unsigned char* data, unsigned int length);
bool writeHomePosition(float latitude, float longitude);
bool wantsBeacon();
@@ -64,6 +64,7 @@ private:
std::string m_password;
std::string m_name;
const char* m_version;
bool m_location;
bool m_debug;
CUDPSocket m_socket;

110
GPSD.cpp Normal file
View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2018,2020 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 "GPSD.h"
#if defined(USE_GPSD)
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cmath>
CGPSD::CGPSD(const std::string& address, const std::string& port) :
m_gpsdAddress(address),
m_gpsdPort(port),
m_gpsdData(),
m_idTimer(1000U, 60U),
m_networks()
{
assert(!address.empty());
assert(!port.empty());
}
CGPSD::~CGPSD()
{
}
void CGPSD::addNetwork(CDMRNetwork* network)
{
assert(network != NULL);
m_networks.push_back(network);
}
bool CGPSD::open()
{
int ret = ::gps_open(m_gpsdAddress.c_str(), m_gpsdPort.c_str(), &m_gpsdData);
if (ret != 0) {
LogError("Error when opening access to gpsd - %d - %s", errno, ::gps_errstr(errno));
return false;
}
::gps_stream(&m_gpsdData, WATCH_ENABLE | WATCH_JSON, NULL);
LogMessage("Connected to GPSD");
m_idTimer.start();
return true;
}
void CGPSD::clock(unsigned int ms)
{
m_idTimer.clock(ms);
if (m_idTimer.hasExpired()) {
sendReport();
m_idTimer.start();
}
}
void CGPSD::close()
{
::gps_stream(&m_gpsdData, WATCH_DISABLE, NULL);
::gps_close(&m_gpsdData);
}
void CGPSD::sendReport()
{
if (!::gps_waiting(&m_gpsdData, 0))
return;
#if GPSD_API_MAJOR_VERSION >= 7
if (::gps_read(&m_gpsdData, NULL, 0) <= 0)
return;
#else
if (::gps_read(&m_gpsdData) <= 0)
return;
#endif
if (m_gpsdData.status != STATUS_FIX)
return;
bool latlonSet = (m_gpsdData.set & LATLON_SET) == LATLON_SET;
if (!latlonSet)
return;
float latitude = float(m_gpsdData.fix.latitude);
float longitude = float(m_gpsdData.fix.longitude);
for (std::vector<CDMRNetwork*>::const_iterator it = m_networks.begin(); it != m_networks.end(); ++it)
(*it)->writeHomePosition(latitude, longitude);
}
#endif

57
GPSD.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2018,2020 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 GPSD_H
#define GPSD_H
#if defined(USE_GPSD)
#include "DMRNetwork.h"
#include "Timer.h"
#include <string>
#include <vector>
#include <gps.h>
class CGPSD {
public:
CGPSD(const std::string& address, const std::string& port);
~CGPSD();
void addNetwork(CDMRNetwork* network);
bool open();
void clock(unsigned int ms);
void close();
private:
std::string m_gpsdAddress;
std::string m_gpsdPort;
struct gps_data_t m_gpsdData;
CTimer m_idTimer;
std::vector<CDMRNetwork*> m_networks;
void sendReport();
};
#endif
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020 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,7 +19,6 @@
#include "MMDVMNetwork.h"
#include "StopWatch.h"
#include "SHA256.h"
#include "Utils.h"
#include "Log.h"
@@ -40,15 +39,12 @@ m_debug(debug),
m_socket(localAddress, localPort),
m_buffer(NULL),
m_rxData(1000U, "MMDVM Network"),
m_options(),
m_configData(NULL),
m_configLen(0U),
m_radioPositionData(NULL),
m_radioPositionLen(0U),
m_talkerAliasData(NULL),
m_talkerAliasLen(0U),
m_homePositionData(NULL),
m_homePositionLen(0U)
m_talkerAliasLen(0U)
{
assert(!rptAddress.empty());
assert(rptPort > 0U);
@@ -60,7 +56,6 @@ m_homePositionLen(0U)
m_radioPositionData = new unsigned char[50U];
m_talkerAliasData = new unsigned char[50U];
m_homePositionData = new unsigned char[50U];
CStopWatch stopWatch;
::srand(stopWatch.start());
@@ -73,15 +68,9 @@ CMMDVMNetwork::~CMMDVMNetwork()
delete[] m_configData;
delete[] m_radioPositionData;
delete[] m_talkerAliasData;
delete[] m_homePositionData;
}
std::string CMMDVMNetwork::getOptions() const
{
return m_options;
}
unsigned int CMMDVMNetwork::getConfig(unsigned char* config) const
unsigned int CMMDVMNetwork::getShortConfig(unsigned char* config) const
{
if (m_configData == 0U)
return 0U;
@@ -248,39 +237,15 @@ bool CMMDVMNetwork::readTalkerAlias(unsigned char* data, unsigned int& length)
return true;
}
bool CMMDVMNetwork::readHomePosition(unsigned char* data, unsigned int& length)
{
if (m_homePositionLen == 0U)
return false;
::memcpy(data, m_homePositionData, m_homePositionLen);
length = m_homePositionLen;
m_homePositionLen = 0U;
return true;
}
bool CMMDVMNetwork::writeBeacon()
{
unsigned char buffer[20U];
::memcpy(buffer + 0U, "RPTSBKN", 7U);
::memcpy(buffer + 7U, m_netId, 4U);
return m_socket.write(buffer, 11U, m_rptAddress, m_rptPort);
return m_socket.write((unsigned char*)"DMRB", 4U, m_rptAddress, m_rptPort);
}
void CMMDVMNetwork::close()
{
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
LogMessage("MMDVM Network, Closing");
::memcpy(buffer + 0U, "MSTCL", 5U);
::memcpy(buffer + 5U, m_netId, 4U);
m_socket.write(buffer, HOMEBREW_DATA_PACKET_LENGTH, m_rptAddress, m_rptPort);
m_socket.close();
}
@@ -289,21 +254,18 @@ void CMMDVMNetwork::clock(unsigned int ms)
in_addr address;
unsigned int port;
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, port);
if (length < 0) {
LogError("MMDVM Network, Socket has failed, reopening");
close();
open();
if (length <= 0)
return;
if (m_rptAddress.s_addr != address.s_addr || m_rptPort != port) {
LogMessage("Packet received from an invalid source, %08X != %08X and/or %u != %u", m_rptAddress.s_addr, address.s_addr, m_rptPort, port);
return;
}
// if (m_debug && length > 0)
// CUtils::dump(1U, "Network Received", m_buffer, length);
if (length > 0 && m_rptAddress.s_addr == address.s_addr && m_rptPort == port) {
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
if (m_debug)
CUtils::dump(1U, "Network Received", m_buffer, length);
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
unsigned char len = length;
m_rxData.addData(&len, 1U);
m_rxData.addData(m_buffer, len);
@@ -313,50 +275,15 @@ void CMMDVMNetwork::clock(unsigned int ms)
} else if (::memcmp(m_buffer, "DMRA", 4U) == 0) {
::memcpy(m_talkerAliasData, m_buffer, length);
m_talkerAliasLen = length;
} else if (::memcmp(m_buffer, "RPTG", 4U) == 0) {
::memcpy(m_homePositionData, m_buffer, length);
m_homePositionLen = length;
} else if (::memcmp(m_buffer, "RPTL", 4U) == 0) {
} else if (::memcmp(m_buffer, "DMRC", 4U) == 0) {
m_id = (m_buffer[4U] << 24) | (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
::memcpy(m_netId, m_buffer + 4U, 4U);
unsigned char ack[10U];
::memcpy(ack + 0U, "RPTACK", 6U);
uint32_t salt = 1U;
::memcpy(ack + 6U, &salt, sizeof(uint32_t));
m_socket.write(ack, 10U, m_rptAddress, m_rptPort);
} else if (::memcmp(m_buffer, "RPTK", 4U) == 0) {
unsigned char ack[10U];
::memcpy(ack + 0U, "RPTACK", 6U);
::memcpy(ack + 6U, m_netId, 4U);
m_socket.write(ack, 10U, m_rptAddress, m_rptPort);
} else if (::memcmp(m_buffer, "RPTCL", 5U) == 0) {
::LogMessage("MMDVM Network, The connected MMDVM is closing down");
} else if (::memcmp(m_buffer, "RPTC", 4U) == 0) {
m_configLen = length - 8U;
m_configData = new unsigned char[m_configLen];
::memcpy(m_configData, m_buffer + 8U, m_configLen);
unsigned char ack[10U];
::memcpy(ack + 0U, "RPTACK", 6U);
::memcpy(ack + 6U, m_netId, 4U);
m_socket.write(ack, 10U, m_rptAddress, m_rptPort);
} else if (::memcmp(m_buffer, "RPTO", 4U) == 0) {
m_options = std::string((char*)(m_buffer + 8U), length - 8U);
unsigned char ack[10U];
::memcpy(ack + 0U, "RPTACK", 6U);
::memcpy(ack + 6U, m_netId, 4U);
m_socket.write(ack, 10U, m_rptAddress, m_rptPort);
} else if (::memcmp(m_buffer, "RPTPING", 7U) == 0) {
unsigned char pong[11U];
::memcpy(pong + 0U, "MSTPONG", 7U);
::memcpy(pong + 7U, m_netId, 4U);
m_socket.write(pong, 11U, m_rptAddress, m_rptPort);
m_socket.write((unsigned char*)"DMRP", 4U, m_rptAddress, m_rptPort);
} else {
CUtils::dump("Unknown packet from the master", m_buffer, length);
}
CUtils::dump("Unknown packet from the MMDVM", m_buffer, length);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018,2020 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,7 +19,6 @@
#if !defined(MMDVMNetwork_H)
#define MMDVMNetwork_H
#include "RepeaterProtocol.h"
#include "UDPSocket.h"
#include "Timer.h"
#include "RingBuffer.h"
@@ -28,35 +27,31 @@
#include <string>
#include <cstdint>
class CMMDVMNetwork : public IRepeaterProtocol
class CMMDVMNetwork
{
public:
CMMDVMNetwork(const std::string& rptAddress, unsigned int rptPort, const std::string& localAddress, unsigned int localPort, bool debug);
virtual ~CMMDVMNetwork();
~CMMDVMNetwork();
virtual std::string getOptions() const;
unsigned int getShortConfig(unsigned char* config) const;
virtual unsigned int getConfig(unsigned char* config) const;
unsigned int getId() const;
virtual unsigned int getId() const;
bool open();
virtual bool open();
bool read(CDMRData& data);
virtual bool read(CDMRData& data);
bool write(const CDMRData& data);
virtual bool write(const CDMRData& data);
bool readRadioPosition(unsigned char* data, unsigned int& length);
virtual bool readRadioPosition(unsigned char* data, unsigned int& length);
bool readTalkerAlias(unsigned char* data, unsigned int& length);
virtual bool readTalkerAlias(unsigned char* data, unsigned int& length);
bool writeBeacon();
virtual bool readHomePosition(unsigned char* data, unsigned int& length);
void clock(unsigned int ms);
virtual bool writeBeacon();
virtual void clock(unsigned int ms);
virtual void close();
void close();
private:
in_addr m_rptAddress;
@@ -67,15 +62,12 @@ private:
CUDPSocket m_socket;
unsigned char* m_buffer;
CRingBuffer<unsigned char> m_rxData;
std::string m_options;
unsigned char* m_configData;
unsigned int m_configLen;
unsigned char* m_radioPositionData;
unsigned int m_radioPositionLen;
unsigned char* m_talkerAliasData;
unsigned int m_talkerAliasLen;
unsigned char* m_homePositionData;
unsigned int m_homePositionLen;
};
#endif

View File

@@ -1,13 +1,20 @@
CC = gcc
CXX = g++
# Use the following CFLAGS and LIBS if you don't want to use gpsd.
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lpthread
# Use the following CFLAGS and LIBS if you do want to use gpsd.
#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread
#LIBS = -lpthread -lgps
LDFLAGS = -g
OBJECTS = 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 Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.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
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 RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o \
Thread.o Timer.o UDPSocket.o Utils.o XLXVoice.o
all: DMRGateway

View File

@@ -1,23 +0,0 @@
/*
* Copyright (C) 2017 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 "RepeaterProtocol.h"
IRepeaterProtocol::~IRepeaterProtocol()
{
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright (C) 2017,2018 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.
*/
#if !defined(RepeaterProtocol_H)
#define RepeaterProtocol_H
#include "DMRData.h"
#include <string>
class IRepeaterProtocol {
public:
virtual ~IRepeaterProtocol() = 0;
virtual std::string getOptions() const = 0;
virtual unsigned int getConfig(unsigned char* config) const = 0;
virtual unsigned int getId() const = 0;
virtual bool open() = 0;
virtual bool read(CDMRData& data) = 0;
virtual bool write(const CDMRData& data) = 0;
virtual bool readRadioPosition(unsigned char* data, unsigned int& length) = 0;
virtual bool readTalkerAlias(unsigned char* data, unsigned int& length) = 0;
virtual bool readHomePosition(unsigned char* data, unsigned int& length) = 0;
virtual void clock(unsigned int ms) = 0;
virtual bool writeBeacon() = 0;
virtual void close() = 0;
private:
};
#endif

View File

@@ -75,9 +75,9 @@ PROCESS_RESULT CRewriteType::process(CDMRData& data, bool trace)
else
LogDebug("Rule Trace,\tRewriteType from \"%s\" Slot=%u Dst=TG%u-%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd);
if (m_toIdStart == m_toIdEnd)
LogDebug("Rule Trace,\tRewriteType to \"\%s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_toSlot, m_toIdStart);
LogDebug("Rule Trace,\tRewriteType to \"%s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_toSlot, m_toIdStart);
else
LogDebug("Rule Trace,\tRewriteType to \"\%s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdEnd);
LogDebug("Rule Trace,\tRewriteType to \"%s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdEnd);
}
return RESULT_MATCHED;

View File

@@ -19,6 +19,6 @@
#if !defined(VERSION_H)
#define VERSION_H
const char* VERSION = "20200421";
const char* VERSION = "20200826";
#endif