Add the FCS protocol and the beginnings of the control for it.
This commit is contained in:
parent
9dc484ea64
commit
a52d831ba5
7 changed files with 149 additions and 82 deletions
|
@ -40,6 +40,7 @@ CConf::CConf(const std::string& file) :
|
|||
m_file(file),
|
||||
m_callsign(),
|
||||
m_suffix(),
|
||||
m_id(0U),
|
||||
m_rptAddress(),
|
||||
m_rptPort(0U),
|
||||
m_myAddress(),
|
||||
|
@ -50,6 +51,7 @@ m_txFrequency(0U),
|
|||
m_power(0U),
|
||||
m_latitude(0.0F),
|
||||
m_longitude(0.0F),
|
||||
m_locator(),
|
||||
m_height(0),
|
||||
m_name(),
|
||||
m_description(),
|
||||
|
@ -134,7 +136,9 @@ bool CConf::read()
|
|||
for (unsigned int i = 0U; value[i] != 0; i++)
|
||||
value[i] = ::toupper(value[i]);
|
||||
m_suffix = value;
|
||||
} else if (::strcmp(key, "RptAddress") == 0)
|
||||
} else if (::strcmp(key, "Id") == 0)
|
||||
m_id = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "RptAddress") == 0)
|
||||
m_rptAddress = value;
|
||||
else if (::strcmp(key, "RptPort") == 0)
|
||||
m_rptPort = (unsigned int)::atoi(value);
|
||||
|
@ -155,6 +159,8 @@ bool CConf::read()
|
|||
m_latitude = float(::atof(value));
|
||||
else if (::strcmp(key, "Longitude") == 0)
|
||||
m_longitude = float(::atof(value));
|
||||
else if (::strcmp(key, "Locator") == 0)
|
||||
m_locator = value;
|
||||
else if (::strcmp(key, "Height") == 0)
|
||||
m_height = ::atoi(value);
|
||||
else if (::strcmp(key, "Name") == 0)
|
||||
|
@ -231,6 +237,11 @@ std::string CConf::getSuffix() const
|
|||
return m_suffix;
|
||||
}
|
||||
|
||||
unsigned int CConf::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
std::string CConf::getRptAddress() const
|
||||
{
|
||||
return m_rptAddress;
|
||||
|
@ -281,6 +292,11 @@ float CConf::getLongitude() const
|
|||
return m_longitude;
|
||||
}
|
||||
|
||||
std::string CConf::getLocator() const
|
||||
{
|
||||
return m_locator;
|
||||
}
|
||||
|
||||
int CConf::getHeight() const
|
||||
{
|
||||
return m_height;
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
// The General section
|
||||
std::string getCallsign() const;
|
||||
std::string getSuffix() const;
|
||||
unsigned int getId() const;
|
||||
std::string getRptAddress() const;
|
||||
unsigned int getRptPort() const;
|
||||
std::string getMyAddress() const;
|
||||
|
@ -45,6 +46,7 @@ public:
|
|||
unsigned int getPower() const;
|
||||
float getLatitude() const;
|
||||
float getLongitude() const;
|
||||
std::string getLocator() const;
|
||||
int getHeight() const;
|
||||
std::string getName() const;
|
||||
std::string getDescription() const;
|
||||
|
@ -85,6 +87,7 @@ private:
|
|||
std::string m_file;
|
||||
std::string m_callsign;
|
||||
std::string m_suffix;
|
||||
unsigned int m_id;
|
||||
std::string m_rptAddress;
|
||||
unsigned int m_rptPort;
|
||||
std::string m_myAddress;
|
||||
|
@ -96,6 +99,7 @@ private:
|
|||
unsigned int m_power;
|
||||
float m_latitude;
|
||||
float m_longitude;
|
||||
std::string m_locator;
|
||||
int m_height;
|
||||
std::string m_name;
|
||||
std::string m_description;
|
||||
|
|
|
@ -161,14 +161,21 @@ WX_STATUS CDTMF::decodeVDMode2Slice(const unsigned char* ambe, bool end)
|
|||
WX_STATUS CDTMF::validate() const
|
||||
{
|
||||
size_t length = m_command.length();
|
||||
if (length != 4U && length != 6U)
|
||||
if (length != 3U && length != 4U && length != 6U)
|
||||
return WXS_NONE;
|
||||
|
||||
char first = m_command.at(0U);
|
||||
if (first != '#' && first != 'A')
|
||||
return WXS_NONE;
|
||||
|
||||
if (length == 4U) {
|
||||
if (length == 3U) {
|
||||
for (unsigned int i = 1U; i <= 3U; i++) {
|
||||
if (m_command.at(1U) < '0' || m_command.at(1U) > '9')
|
||||
return WXS_NONE;
|
||||
}
|
||||
|
||||
return WXS_CONNECT_FCS;
|
||||
} else if (length == 4U) {
|
||||
for (unsigned int i = 1U; i <= 4U; i++) {
|
||||
if (m_command.at(1U) < '0' || m_command.at(1U) > '9')
|
||||
return WXS_NONE;
|
||||
|
|
|
@ -25,59 +25,31 @@
|
|||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const char* FCS_VERSION = "MMDVM v.01";
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CFCSNetwork::CFCSNetwork(const std::string& address, unsigned int port, const std::string& callsign, bool debug) :
|
||||
m_socket(address, port),
|
||||
m_debug(debug),
|
||||
m_address(),
|
||||
m_port(0U),
|
||||
m_poll(NULL),
|
||||
m_unlink(NULL),
|
||||
m_buffer(1000U, "FCS Network Buffer")
|
||||
{
|
||||
m_poll = new unsigned char[14U];
|
||||
::memcpy(m_poll + 0U, "YSFP", 4U);
|
||||
|
||||
m_unlink = new unsigned char[14U];
|
||||
::memcpy(m_unlink + 0U, "YSFU", 4U);
|
||||
|
||||
std::string node = callsign;
|
||||
node.resize(YSF_CALLSIGN_LENGTH, ' ');
|
||||
|
||||
for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) {
|
||||
m_poll[i + 4U] = node.at(i);
|
||||
m_unlink[i + 4U] = node.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
CFCSNetwork::CFCSNetwork(unsigned int port, const std::string& callsign, bool debug) :
|
||||
CFCSNetwork::CFCSNetwork(unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug) :
|
||||
m_socket(port),
|
||||
m_debug(debug),
|
||||
m_address(),
|
||||
m_port(0U),
|
||||
m_poll(NULL),
|
||||
m_unlink(NULL),
|
||||
m_info(NULL),
|
||||
m_callsign(callsign),
|
||||
m_reflector(),
|
||||
m_buffer(1000U, "FCS Network Buffer")
|
||||
{
|
||||
m_poll = new unsigned char[14U];
|
||||
::memcpy(m_poll + 0U, "YSFP", 4U);
|
||||
m_info = new unsigned char[100U];
|
||||
::memset(m_info, ' ', 100U);
|
||||
|
||||
m_unlink = new unsigned char[14U];
|
||||
::memcpy(m_unlink + 0U, "YSFU", 4U);
|
||||
m_callsign.resize(6U, ' ');
|
||||
|
||||
std::string node = callsign;
|
||||
node.resize(YSF_CALLSIGN_LENGTH, ' ');
|
||||
|
||||
for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) {
|
||||
m_poll[i + 4U] = node.at(i);
|
||||
m_unlink[i + 4U] = node.at(i);
|
||||
}
|
||||
::sprintf((char*)m_info, "%9u%9u%-6.6s%-12.12s%7u", rxFrequency, txFrequency, locator.c_str(), FCS_VERSION, id);
|
||||
}
|
||||
|
||||
CFCSNetwork::~CFCSNetwork()
|
||||
{
|
||||
delete[] m_poll;
|
||||
delete[] m_info;
|
||||
}
|
||||
|
||||
bool CFCSNetwork::open()
|
||||
|
@ -106,18 +78,35 @@ bool CFCSNetwork::write(const unsigned char* data)
|
|||
if (m_port == 0U)
|
||||
return true;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "FCS Network Data Sent", data, 155U);
|
||||
unsigned char buffer[130U];
|
||||
::memset(buffer + 0U, ' ', 130U);
|
||||
::memcpy(buffer + 0U, data + 35U, 120U);
|
||||
::memcpy(buffer + 121U, m_reflector.c_str(), 8U);
|
||||
|
||||
return m_socket.write(data, 155U, m_address, m_port);
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "FCS Network Data Sent", buffer, 130U);
|
||||
|
||||
return m_socket.write(buffer, 130U, m_address, m_port);
|
||||
}
|
||||
|
||||
bool CFCSNetwork::writePoll()
|
||||
bool CFCSNetwork::writeLink(const std::string& reflector)
|
||||
{
|
||||
if (m_port == 0U)
|
||||
return true;
|
||||
|
||||
return m_socket.write(m_poll, 14U, m_address, m_port);
|
||||
m_reflector = reflector;
|
||||
m_reflector.resize(8U, ' ');
|
||||
|
||||
unsigned char buffer[25U];
|
||||
::memset(buffer + 0U, ' ', 25U);
|
||||
::memcpy(buffer + 0U, "PING", 4U);
|
||||
::memcpy(buffer + 4U, m_callsign.c_str(), 6U);
|
||||
::memcpy(buffer + 10U, m_reflector.c_str(), 6U);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "FCS Network Data Sent", buffer, 25U);
|
||||
|
||||
return m_socket.write(buffer, 25U, m_address, m_port);
|
||||
}
|
||||
|
||||
bool CFCSNetwork::writeUnlink()
|
||||
|
@ -125,7 +114,7 @@ bool CFCSNetwork::writeUnlink()
|
|||
if (m_port == 0U)
|
||||
return true;
|
||||
|
||||
return m_socket.write(m_unlink, 14U, m_address, m_port);
|
||||
return m_socket.write((unsigned char*)"CLOSE ", 11U, m_address, m_port);
|
||||
}
|
||||
|
||||
void CFCSNetwork::clock(unsigned int ms)
|
||||
|
@ -147,10 +136,11 @@ void CFCSNetwork::clock(unsigned int ms)
|
|||
if (m_debug)
|
||||
CUtils::dump(1U, "FCS Network Data Received", buffer, length);
|
||||
|
||||
unsigned char len = length;
|
||||
m_buffer.addData(&len, 1U);
|
||||
if (length == 7 || length == 10)
|
||||
writeInfo();
|
||||
|
||||
m_buffer.addData(buffer, length);
|
||||
if (length == 130)
|
||||
m_buffer.addData(buffer, 130U);
|
||||
}
|
||||
|
||||
unsigned int CFCSNetwork::read(unsigned char* data)
|
||||
|
@ -160,12 +150,9 @@ unsigned int CFCSNetwork::read(unsigned char* data)
|
|||
if (m_buffer.isEmpty())
|
||||
return 0U;
|
||||
|
||||
unsigned char len = 0U;
|
||||
m_buffer.getData(&len, 1U);
|
||||
m_buffer.getData(data, 130U);
|
||||
|
||||
m_buffer.getData(data, len);
|
||||
|
||||
return len;
|
||||
return 155U;
|
||||
}
|
||||
|
||||
void CFCSNetwork::close()
|
||||
|
@ -174,3 +161,14 @@ void CFCSNetwork::close()
|
|||
|
||||
LogMessage("Closing FCS network connection");
|
||||
}
|
||||
|
||||
void CFCSNetwork::writeInfo()
|
||||
{
|
||||
if (m_port == 0U)
|
||||
return;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "FCS Network Data Sent", m_info, 100U);
|
||||
|
||||
m_socket.write(m_info, 100U, m_address, m_port);
|
||||
}
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
|
||||
class CFCSNetwork {
|
||||
public:
|
||||
CFCSNetwork(const std::string& address, unsigned int port, const std::string& callsign, bool debug);
|
||||
CFCSNetwork(unsigned int port, const std::string& callsign, bool debug);
|
||||
CFCSNetwork(unsigned int port, const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, const std::string& locator, unsigned int id, bool debug);
|
||||
~CFCSNetwork();
|
||||
|
||||
bool open();
|
||||
|
@ -39,7 +38,8 @@ public:
|
|||
|
||||
bool write(const unsigned char* data);
|
||||
|
||||
bool writePoll();
|
||||
bool writeLink(const std::string& reflector);
|
||||
|
||||
bool writeUnlink();
|
||||
|
||||
unsigned int read(unsigned char* data);
|
||||
|
@ -53,9 +53,12 @@ private:
|
|||
bool m_debug;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
unsigned char* m_poll;
|
||||
unsigned char* m_unlink;
|
||||
unsigned char* m_info;
|
||||
std::string m_callsign;
|
||||
std::string m_reflector;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
|
||||
void writeInfo();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -198,9 +198,14 @@ int CYSFGateway::run()
|
|||
return 1;
|
||||
}
|
||||
|
||||
unsigned int txFrequency = m_conf.getTxFrequency();
|
||||
unsigned int rxFrequency = m_conf.getRxFrequency();
|
||||
std::string locator = m_conf.getLocator();
|
||||
unsigned int id = m_conf.getId();
|
||||
|
||||
unsigned int fcsPort = m_conf.getFCSNetworkPort();
|
||||
|
||||
m_fcsNetwork = new CFCSNetwork(fcsPort, m_callsign, debug);
|
||||
m_fcsNetwork = new CFCSNetwork(fcsPort, m_callsign, rxFrequency, txFrequency, locator, id, debug);
|
||||
ret = m_fcsNetwork->open();
|
||||
if (!ret) {
|
||||
::LogError("Cannot open the FCS reflector network port");
|
||||
|
@ -222,8 +227,6 @@ int CYSFGateway::run()
|
|||
m_wiresX = new CWiresX(m_callsign, m_suffix, &rptNetwork, fileName, reloadTime);
|
||||
|
||||
std::string name = m_conf.getName();
|
||||
unsigned int txFrequency = m_conf.getTxFrequency();
|
||||
unsigned int rxFrequency = m_conf.getRxFrequency();
|
||||
|
||||
m_wiresX->setInfo(name, txFrequency, rxFrequency);
|
||||
|
||||
|
@ -300,9 +303,10 @@ int CYSFGateway::run()
|
|||
}
|
||||
|
||||
if (fcsNetworkEnabled && m_linkType == LINK_FCS && !m_exclude) {
|
||||
m_fcsNetwork->write(buffer);
|
||||
if (::memcmp(buffer + 0U, "YSFD", 4U) == 0)
|
||||
if (::memcmp(buffer + 0U, "YSFD", 4U) == 0) {
|
||||
m_fcsNetwork->write(buffer);
|
||||
m_inactivityTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
if ((buffer[34U] & 0x01U) == 0x01U) {
|
||||
|
@ -325,10 +329,7 @@ int CYSFGateway::run()
|
|||
|
||||
while (m_fcsNetwork->read(buffer) > 0U) {
|
||||
if (fcsNetworkEnabled && m_linkType == LINK_FCS) {
|
||||
// Only pass through YSF data packets
|
||||
if (::memcmp(buffer + 0U, "YSFD", 4U) == 0)
|
||||
rptNetwork.write(buffer);
|
||||
|
||||
rptNetwork.write(buffer);
|
||||
m_lostTimer.start();
|
||||
}
|
||||
}
|
||||
|
@ -468,9 +469,17 @@ void CYSFGateway::processWiresX(const unsigned char* buffer, unsigned char fi, u
|
|||
WX_STATUS status = m_wiresX->process(buffer + 35U, buffer + 14U, fi, dt, fn, ft);
|
||||
switch (status) {
|
||||
case WXS_CONNECT_YSF: {
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
if (m_linkType == LINK_YSF) {
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
}
|
||||
if (m_linkType == LINK_FCS) {
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->clearDestination();
|
||||
}
|
||||
|
||||
CYSFReflector* reflector = m_wiresX->getReflector();
|
||||
LogMessage("Connect to %5.5s - \"%s\" has been requested by %10.10s", reflector->m_id.c_str(), reflector->m_name.c_str(), buffer + 14U);
|
||||
|
@ -488,18 +497,33 @@ void CYSFGateway::processWiresX(const unsigned char* buffer, unsigned char fi, u
|
|||
}
|
||||
break;
|
||||
case WXS_DISCONNECT:
|
||||
LogMessage("Disconnect has been requested by %10.10s", buffer + 14U);
|
||||
if (m_linkType == LINK_YSF) {
|
||||
LogMessage("Disconnect has been requested by %10.10s", buffer + 14U);
|
||||
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->clearDestination();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->writeUnlink();
|
||||
m_ysfNetwork->clearDestination();
|
||||
|
||||
m_inactivityTimer.stop();
|
||||
m_lostTimer.stop();
|
||||
m_ysfPollTimer.stop();
|
||||
m_inactivityTimer.stop();
|
||||
m_lostTimer.stop();
|
||||
m_ysfPollTimer.stop();
|
||||
|
||||
m_linkType = LINK_NONE;
|
||||
m_linkType = LINK_NONE;
|
||||
}
|
||||
if (m_linkType == LINK_FCS) {
|
||||
LogMessage("Disconnect has been requested by %10.10s", buffer + 14U);
|
||||
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->clearDestination();
|
||||
|
||||
m_inactivityTimer.stop();
|
||||
m_lostTimer.stop();
|
||||
|
||||
m_linkType = LINK_NONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -566,6 +590,19 @@ void CYSFGateway::processDTMF(const unsigned char* buffer, unsigned char dt)
|
|||
|
||||
m_linkType = LINK_NONE;
|
||||
}
|
||||
if (m_linkType == LINK_FCS) {
|
||||
LogMessage("Disconnect via DTMF has been requested by %10.10s", buffer + 14U);
|
||||
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->writeUnlink();
|
||||
m_fcsNetwork->clearDestination();
|
||||
|
||||
m_inactivityTimer.stop();
|
||||
m_lostTimer.stop();
|
||||
|
||||
m_linkType = LINK_NONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
Callsign=G9BF
|
||||
Suffix=RPT
|
||||
# Suffix=ND
|
||||
Id=1234567
|
||||
RptAddress=127.0.0.1
|
||||
RptPort=3200
|
||||
LocalAddress=127.0.0.1
|
||||
|
@ -14,6 +15,7 @@ TXFrequency=439475000
|
|||
Power=1
|
||||
Latitude=0.0
|
||||
Longitude=0.0
|
||||
Locator=IO90TT
|
||||
Height=0
|
||||
Name=Nowhere
|
||||
Description=Multi-Mode Repeater
|
||||
|
|
Loading…
Reference in a new issue