Convert to using the APRSGateway.
This commit is contained in:
parent
815165141c
commit
7759575bbb
16 changed files with 67 additions and 739 deletions
|
@ -10,6 +10,6 @@ The Gateway and Reflector have ini files that contain the parameters for running
|
|||
|
||||
The MMDVM .ini file should have the IP address and port number of the client in the [System Fusion Network] settings.
|
||||
|
||||
They build on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2017 on x86 and x64.
|
||||
They build on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2019 on x86 and x64.
|
||||
|
||||
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& password, const std::string& address, unsigned int port, const std::string& suffix) :
|
||||
m_thread(NULL),
|
||||
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix) :
|
||||
m_idTimer(1000U),
|
||||
m_callsign(callsign),
|
||||
m_txFrequency(0U),
|
||||
|
@ -36,12 +35,14 @@ m_longitude(0.0F),
|
|||
m_height(0),
|
||||
m_desc(),
|
||||
m_suffix(suffix),
|
||||
m_aprsAddress(),
|
||||
m_aprsPort(port),
|
||||
m_aprsSocket(),
|
||||
m_mobileGPSAddress(),
|
||||
m_mobileGPSPort(0U),
|
||||
m_socket(NULL)
|
||||
m_mobileSocket(NULL)
|
||||
{
|
||||
assert(!callsign.empty());
|
||||
assert(!password.empty());
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
|
||||
|
@ -50,7 +51,7 @@ m_socket(NULL)
|
|||
m_callsign.append(rptSuffix.substr(0U, 1U));
|
||||
}
|
||||
|
||||
m_thread = new CAPRSWriterThread(m_callsign, password, address, port);
|
||||
m_aprsAddress = CUDPSocket::lookup(address);
|
||||
}
|
||||
|
||||
CAPRSWriter::~CAPRSWriter()
|
||||
|
@ -79,16 +80,16 @@ void CAPRSWriter::setMobileLocation(const std::string& address, unsigned int por
|
|||
m_mobileGPSAddress = CUDPSocket::lookup(address);
|
||||
m_mobileGPSPort = port;
|
||||
|
||||
m_socket = new CUDPSocket;
|
||||
m_mobileSocket = new CUDPSocket;
|
||||
}
|
||||
|
||||
bool CAPRSWriter::open()
|
||||
{
|
||||
if (m_socket != NULL) {
|
||||
bool ret = m_socket->open();
|
||||
if (m_mobileSocket != NULL) {
|
||||
bool ret = m_mobileSocket->open();
|
||||
if (!ret) {
|
||||
delete m_socket;
|
||||
m_socket = NULL;
|
||||
delete m_mobileSocket;
|
||||
m_mobileSocket = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -100,7 +101,7 @@ bool CAPRSWriter::open()
|
|||
|
||||
m_idTimer.start();
|
||||
|
||||
return m_thread->start();
|
||||
return m_aprsSocket.open();
|
||||
}
|
||||
|
||||
void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned char radio, float fLatitude, float fLongitude)
|
||||
|
@ -155,22 +156,20 @@ void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned
|
|||
}
|
||||
|
||||
char output[300U];
|
||||
::sprintf(output, "%s>APDPRS,C4FM*,qAR,%s:!%s%c/%s%c%c %s via MMDVM",
|
||||
::sprintf(output, "%s>APDPRS,C4FM*,qAR,%s:!%s%c/%s%c%c %s via MMDVM\r\n",
|
||||
callsign, m_callsign.c_str(),
|
||||
lat, (fLatitude < 0.0F) ? 'S' : 'N',
|
||||
lon, (fLongitude < 0.0F) ? 'W' : 'E',
|
||||
symbol, type);
|
||||
|
||||
m_thread->write(output);
|
||||
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
|
||||
}
|
||||
|
||||
void CAPRSWriter::clock(unsigned int ms)
|
||||
{
|
||||
m_idTimer.clock(ms);
|
||||
|
||||
m_thread->clock(ms);
|
||||
|
||||
if (m_socket != NULL) {
|
||||
if (m_mobileSocket != NULL) {
|
||||
if (m_idTimer.hasExpired()) {
|
||||
pollGPS();
|
||||
m_idTimer.start();
|
||||
|
@ -187,26 +186,23 @@ void CAPRSWriter::clock(unsigned int ms)
|
|||
|
||||
void CAPRSWriter::close()
|
||||
{
|
||||
if (m_socket != NULL) {
|
||||
m_socket->close();
|
||||
delete m_socket;
|
||||
}
|
||||
m_aprsSocket.close();
|
||||
|
||||
m_thread->stop();
|
||||
if (m_mobileSocket != NULL) {
|
||||
m_mobileSocket->close();
|
||||
delete m_mobileSocket;
|
||||
}
|
||||
}
|
||||
|
||||
bool CAPRSWriter::pollGPS()
|
||||
{
|
||||
assert(m_socket != NULL);
|
||||
assert(m_mobileSocket != NULL);
|
||||
|
||||
return m_socket->write((unsigned char*)"YSFGateway", 10U, m_mobileGPSAddress, m_mobileGPSPort);
|
||||
return m_mobileSocket->write((unsigned char*)"YSFGateway", 10U, m_mobileGPSAddress, m_mobileGPSPort);
|
||||
}
|
||||
|
||||
void CAPRSWriter::sendIdFrameFixed()
|
||||
{
|
||||
if (!m_thread->isConnected())
|
||||
return;
|
||||
|
||||
// Default values aren't passed on
|
||||
if (m_latitude == 0.0F && m_longitude == 0.0F)
|
||||
return;
|
||||
|
@ -257,13 +253,13 @@ void CAPRSWriter::sendIdFrameFixed()
|
|||
server.append("S");
|
||||
|
||||
char output[500U];
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s",
|
||||
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&/A=%06.0f%s %s\r\n",
|
||||
m_callsign.c_str(), server.c_str(),
|
||||
lat, (m_latitude < 0.0F) ? 'S' : 'N',
|
||||
lon, (m_longitude < 0.0F) ? 'W' : 'E',
|
||||
float(m_height) * 3.28F, band, desc);
|
||||
|
||||
m_thread->write(output);
|
||||
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
|
||||
}
|
||||
|
||||
void CAPRSWriter::sendIdFrameMobile()
|
||||
|
@ -272,13 +268,10 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
unsigned char buffer[200U];
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int ret = m_socket->read(buffer, 200U, address, port);
|
||||
int ret = m_mobileSocket->read(buffer, 200U, address, port);
|
||||
if (ret <= 0)
|
||||
return;
|
||||
|
||||
if (!m_thread->isConnected())
|
||||
return;
|
||||
|
||||
buffer[ret] = '\0';
|
||||
|
||||
// Parse the GPS data
|
||||
|
@ -353,7 +346,7 @@ void CAPRSWriter::sendIdFrameMobile()
|
|||
::sprintf(output + ::strlen(output), "%03.0f/%03.0f", rawBearing, rawVelocity * 0.539957F);
|
||||
}
|
||||
|
||||
::sprintf(output + ::strlen(output), "/A=%06.0f%s %s", float(rawAltitude) * 3.28F, band, desc);
|
||||
::sprintf(output + ::strlen(output), "/A=%06.0f%s %s\r\n", float(rawAltitude) * 3.28F, band, desc);
|
||||
|
||||
m_thread->write(output);
|
||||
m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2010,2011,2012,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2010,2011,2012,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 @@
|
|||
#ifndef APRSWriter_H
|
||||
#define APRSWriter_H
|
||||
|
||||
#include "APRSWriterThread.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
|
@ -40,7 +39,7 @@
|
|||
|
||||
class CAPRSWriter {
|
||||
public:
|
||||
CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& password, const std::string& address, unsigned int port, const std::string& suffix);
|
||||
CAPRSWriter(const std::string& callsign, const std::string& rptSuffix, const std::string& address, unsigned int port, const std::string& suffix);
|
||||
~CAPRSWriter();
|
||||
|
||||
bool open();
|
||||
|
@ -58,19 +57,21 @@ public:
|
|||
void close();
|
||||
|
||||
private:
|
||||
CAPRSWriterThread* m_thread;
|
||||
CTimer m_idTimer;
|
||||
std::string m_callsign;
|
||||
unsigned int m_txFrequency;
|
||||
unsigned int m_rxFrequency;
|
||||
float m_latitude;
|
||||
float m_longitude;
|
||||
int m_height;
|
||||
std::string m_desc;
|
||||
std::string m_suffix;
|
||||
in_addr m_mobileGPSAddress;
|
||||
unsigned int m_mobileGPSPort;
|
||||
CUDPSocket* m_socket;
|
||||
CTimer m_idTimer;
|
||||
std::string m_callsign;
|
||||
unsigned int m_txFrequency;
|
||||
unsigned int m_rxFrequency;
|
||||
float m_latitude;
|
||||
float m_longitude;
|
||||
int m_height;
|
||||
std::string m_desc;
|
||||
std::string m_suffix;
|
||||
in_addr m_aprsAddress;
|
||||
unsigned int m_aprsPort;
|
||||
CUDPSocket m_aprsSocket;
|
||||
in_addr m_mobileGPSAddress;
|
||||
unsigned int m_mobileGPSPort;
|
||||
CUDPSocket* m_mobileSocket;
|
||||
|
||||
bool pollGPS();
|
||||
void sendIdFrameFixed();
|
||||
|
|
|
@ -1,279 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2014,2016,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 "APRSWriterThread.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
// #define DUMP_TX
|
||||
|
||||
const unsigned int CALLSIGN_LENGTH = 8U;
|
||||
|
||||
const unsigned int APRS_TIMEOUT = 10U;
|
||||
|
||||
CAPRSWriterThread::CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port) :
|
||||
CThread(),
|
||||
m_username(callsign),
|
||||
m_password(password),
|
||||
m_socket(address, port),
|
||||
m_queue(20U, "APRS Queue"),
|
||||
m_exit(false),
|
||||
m_connected(false),
|
||||
m_reconnectTimer(1000U),
|
||||
m_tries(1U),
|
||||
m_APRSReadCallback(NULL),
|
||||
m_filter(),
|
||||
m_clientName("YSFGateway")
|
||||
{
|
||||
assert(!callsign.empty());
|
||||
assert(!password.empty());
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
|
||||
m_username.resize(CALLSIGN_LENGTH, ' ');
|
||||
m_username.erase(std::find_if(m_username.rbegin(), m_username.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), m_username.end());
|
||||
std::transform(m_username.begin(), m_username.end(), m_username.begin(), ::toupper);
|
||||
}
|
||||
|
||||
CAPRSWriterThread::CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port, const std::string& filter, const std::string& clientName) :
|
||||
CThread(),
|
||||
m_username(callsign),
|
||||
m_password(password),
|
||||
m_socket(address, port),
|
||||
m_queue(20U, "APRS Queue"),
|
||||
m_exit(false),
|
||||
m_connected(false),
|
||||
m_reconnectTimer(1000U),
|
||||
m_tries(1U),
|
||||
m_APRSReadCallback(NULL),
|
||||
m_filter(filter),
|
||||
m_clientName(clientName)
|
||||
{
|
||||
assert(!callsign.empty());
|
||||
assert(!password.empty());
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
|
||||
m_username.resize(CALLSIGN_LENGTH, ' ');
|
||||
m_username.erase(std::find_if(m_username.rbegin(), m_username.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), m_username.end());
|
||||
std::transform(m_username.begin(), m_username.end(), m_username.begin(), ::toupper);
|
||||
}
|
||||
|
||||
CAPRSWriterThread::~CAPRSWriterThread()
|
||||
{
|
||||
m_username.clear();
|
||||
}
|
||||
|
||||
bool CAPRSWriterThread::start()
|
||||
{
|
||||
run();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAPRSWriterThread::entry()
|
||||
{
|
||||
LogMessage("Starting the APRS Writer thread");
|
||||
|
||||
m_connected = connect();
|
||||
if (!m_connected) {
|
||||
LogError("Connect attempt to the APRS server has failed");
|
||||
startReconnectionTimer();
|
||||
}
|
||||
|
||||
try {
|
||||
while (!m_exit) {
|
||||
if (!m_connected) {
|
||||
if (m_reconnectTimer.isRunning() && m_reconnectTimer.hasExpired()) {
|
||||
m_reconnectTimer.stop();
|
||||
|
||||
m_connected = connect();
|
||||
if (!m_connected) {
|
||||
LogError("Reconnect attempt to the APRS server has failed");
|
||||
startReconnectionTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_connected) {
|
||||
m_tries = 0U;
|
||||
|
||||
if (!m_queue.isEmpty()){
|
||||
char* p = NULL;
|
||||
m_queue.getData(&p, 1U);
|
||||
|
||||
LogMessage("APRS ==> %s", p);
|
||||
|
||||
::strcat(p, "\r\n");
|
||||
|
||||
bool ret = m_socket.write((unsigned char*)p, (unsigned int)::strlen(p));
|
||||
if (!ret) {
|
||||
m_connected = false;
|
||||
m_socket.close();
|
||||
LogError("Connection to the APRS thread has failed");
|
||||
startReconnectionTimer();
|
||||
}
|
||||
|
||||
delete[] p;
|
||||
}
|
||||
{
|
||||
std::string line;
|
||||
int length = m_socket.readLine(line, APRS_TIMEOUT);
|
||||
|
||||
if (length < 0) {
|
||||
m_connected = false;
|
||||
m_socket.close();
|
||||
LogError("Error when reading from the APRS server");
|
||||
startReconnectionTimer();
|
||||
}
|
||||
|
||||
if(length > 0 && line.at(0U) != '#'//check if we have something and if that something is an APRS frame
|
||||
&& m_APRSReadCallback != NULL)//do we have someone wanting an APRS Frame?
|
||||
{
|
||||
//wxLogMessage(wxT("Received APRS Frame : ") + line);
|
||||
m_APRSReadCallback(std::string(line));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (m_connected)
|
||||
m_socket.close();
|
||||
|
||||
while (!m_queue.isEmpty()) {
|
||||
char* p = NULL;
|
||||
m_queue.getData(&p, 1U);
|
||||
delete[] p;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LogError("Exception raised in the APRS Writer thread - \"%s\"", e.what());
|
||||
}
|
||||
catch (...) {
|
||||
LogError("Unknown exception raised in the APRS Writer thread");
|
||||
}
|
||||
|
||||
LogMessage("Stopping the APRS Writer thread");
|
||||
}
|
||||
|
||||
void CAPRSWriterThread::setReadAPRSCallback(ReadAPRSFrameCallback cb)
|
||||
{
|
||||
m_APRSReadCallback = cb;
|
||||
}
|
||||
|
||||
void CAPRSWriterThread::write(const char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (!m_connected)
|
||||
return;
|
||||
|
||||
unsigned int len = (unsigned int)::strlen(data);
|
||||
|
||||
char* p = new char[len + 5U];
|
||||
::strcpy(p, data);
|
||||
|
||||
m_queue.addData(&p, 1U);
|
||||
}
|
||||
|
||||
bool CAPRSWriterThread::isConnected() const
|
||||
{
|
||||
return m_connected;
|
||||
}
|
||||
|
||||
void CAPRSWriterThread::stop()
|
||||
{
|
||||
m_exit = true;
|
||||
|
||||
wait();
|
||||
}
|
||||
|
||||
void CAPRSWriterThread::clock(unsigned int ms)
|
||||
{
|
||||
m_reconnectTimer.clock(ms);
|
||||
}
|
||||
|
||||
bool CAPRSWriterThread::connect()
|
||||
{
|
||||
bool ret = m_socket.open();
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
//wait for lgin banner
|
||||
int length;
|
||||
std::string serverResponse;
|
||||
length = m_socket.readLine(serverResponse, APRS_TIMEOUT);
|
||||
if (length == 0) {
|
||||
LogError("No reply from the APRS server after %u seconds", APRS_TIMEOUT);
|
||||
m_socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
LogMessage("Received login banner : %s", serverResponse.c_str());
|
||||
|
||||
std::string filter(m_filter);
|
||||
if (filter.length() > 0)
|
||||
filter.insert(0U, " filter ");
|
||||
|
||||
char connectString[200U];
|
||||
::sprintf(connectString, "user %s pass %s vers %s%s\n", m_username.c_str(), m_password.c_str(), (m_clientName.length() ? m_clientName : "YSFGateway").c_str(), filter.c_str());
|
||||
|
||||
ret = m_socket.writeLine(std::string(connectString));
|
||||
if (!ret) {
|
||||
m_socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
length = m_socket.readLine(serverResponse, APRS_TIMEOUT);
|
||||
if (length == 0) {
|
||||
LogError("No reply from the APRS server after %u seconds", APRS_TIMEOUT);
|
||||
m_socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length < 0) {
|
||||
LogError("Error when reading from the APRS server");
|
||||
m_socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
LogMessage("Response from APRS server: %s", serverResponse.c_str());
|
||||
|
||||
LogMessage("Connected to the APRS server");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAPRSWriterThread::startReconnectionTimer()
|
||||
{
|
||||
// Clamp at a ten minutes reconnect time
|
||||
m_tries++;
|
||||
if (m_tries > 10U)
|
||||
m_tries = 10U;
|
||||
|
||||
m_reconnectTimer.setTimeout(m_tries * 60U);
|
||||
m_reconnectTimer.start();
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010,2011,2012,2016,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 APRSWriterThread_H
|
||||
#define APRSWriterThread_H
|
||||
|
||||
#include "TCPSocket.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "Timer.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef void (*ReadAPRSFrameCallback)(const std::string&);
|
||||
|
||||
class CAPRSWriterThread : public CThread {
|
||||
public:
|
||||
CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port);
|
||||
CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port, const std::string& filter, const std::string& clientName);
|
||||
virtual ~CAPRSWriterThread();
|
||||
|
||||
virtual bool start();
|
||||
|
||||
virtual bool isConnected() const;
|
||||
|
||||
virtual void write(const char* data);
|
||||
|
||||
virtual void entry();
|
||||
|
||||
virtual void stop();
|
||||
|
||||
void setReadAPRSCallback(ReadAPRSFrameCallback cb);
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
std::string m_username;
|
||||
std::string m_password;
|
||||
CTCPSocket m_socket;
|
||||
CRingBuffer<char*> m_queue;
|
||||
bool m_exit;
|
||||
bool m_connected;
|
||||
CTimer m_reconnectTimer;
|
||||
unsigned int m_tries;
|
||||
ReadAPRSFrameCallback m_APRSReadCallback;
|
||||
std::string m_filter;
|
||||
std::string m_clientName;
|
||||
|
||||
bool connect();
|
||||
void startReconnectionTimer();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -31,7 +31,7 @@ enum SECTION {
|
|||
SECTION_GENERAL,
|
||||
SECTION_INFO,
|
||||
SECTION_LOG,
|
||||
SECTION_APRS_FI,
|
||||
SECTION_APRS,
|
||||
SECTION_NETWORK,
|
||||
SECTION_YSF_NETWORK,
|
||||
SECTION_FCS_NETWORK,
|
||||
|
@ -64,9 +64,8 @@ m_logFileLevel(0U),
|
|||
m_logFilePath(),
|
||||
m_logFileRoot(),
|
||||
m_aprsEnabled(false),
|
||||
m_aprsServer(),
|
||||
m_aprsAddress(),
|
||||
m_aprsPort(0U),
|
||||
m_aprsPassword(),
|
||||
m_aprsSuffix(),
|
||||
m_aprsDescription(),
|
||||
m_networkStartup(),
|
||||
|
@ -122,8 +121,8 @@ bool CConf::read()
|
|||
section = SECTION_INFO;
|
||||
else if (::strncmp(buffer, "[Log]", 5U) == 0)
|
||||
section = SECTION_LOG;
|
||||
else if (::strncmp(buffer, "[aprs.fi]", 9U) == 0)
|
||||
section = SECTION_APRS_FI;
|
||||
else if (::strncmp(buffer, "[APRS]", 6U) == 0)
|
||||
section = SECTION_APRS;
|
||||
else if (::strncmp(buffer, "[Network]", 9U) == 0)
|
||||
section = SECTION_NETWORK;
|
||||
else if (::strncmp(buffer, "[YSF Network]", 13U) == 0)
|
||||
|
@ -198,15 +197,13 @@ bool CConf::read()
|
|||
m_logFileLevel = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "DisplayLevel") == 0)
|
||||
m_logDisplayLevel = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_APRS_FI) {
|
||||
} else if (section == SECTION_APRS) {
|
||||
if (::strcmp(key, "Enable") == 0)
|
||||
m_aprsEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Server") == 0)
|
||||
m_aprsServer = value;
|
||||
else if (::strcmp(key, "Address") == 0)
|
||||
m_aprsAddress = value;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
m_aprsPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Password") == 0)
|
||||
m_aprsPassword = value;
|
||||
else if (::strcmp(key, "Suffix") == 0)
|
||||
m_aprsSuffix = value;
|
||||
else if (::strcmp(key, "Description") == 0)
|
||||
|
@ -387,9 +384,9 @@ bool CConf::getAPRSEnabled() const
|
|||
return m_aprsEnabled;
|
||||
}
|
||||
|
||||
std::string CConf::getAPRSServer() const
|
||||
std::string CConf::getAPRSAddress() const
|
||||
{
|
||||
return m_aprsServer;
|
||||
return m_aprsAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getAPRSPort() const
|
||||
|
@ -397,11 +394,6 @@ unsigned int CConf::getAPRSPort() const
|
|||
return m_aprsPort;
|
||||
}
|
||||
|
||||
std::string CConf::getAPRSPassword() const
|
||||
{
|
||||
return m_aprsPassword;
|
||||
}
|
||||
|
||||
std::string CConf::getAPRSSuffix() const
|
||||
{
|
||||
return m_aprsSuffix;
|
||||
|
|
|
@ -57,11 +57,10 @@ public:
|
|||
std::string getLogFilePath() const;
|
||||
std::string getLogFileRoot() const;
|
||||
|
||||
// The aprs.fi section
|
||||
// The APRS section
|
||||
bool getAPRSEnabled() const;
|
||||
std::string getAPRSServer() const;
|
||||
std::string getAPRSAddress() const;
|
||||
unsigned int getAPRSPort() const;
|
||||
std::string getAPRSPassword() const;
|
||||
std::string getAPRSSuffix() const;
|
||||
std::string getAPRSDescription() const;
|
||||
|
||||
|
@ -127,9 +126,8 @@ private:
|
|||
std::string m_logFileRoot;
|
||||
|
||||
bool m_aprsEnabled;
|
||||
std::string m_aprsServer;
|
||||
std::string m_aprsAddress;
|
||||
unsigned int m_aprsPort;
|
||||
std::string m_aprsPassword;
|
||||
std::string m_aprsSuffix;
|
||||
std::string m_aprsDescription;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
|||
LIBS = -lm -lpthread
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \
|
||||
OBJECTS = APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o Thread.o Timer.o \
|
||||
UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFNetwork.o YSFPayload.o YSFReflectors.o
|
||||
|
||||
all: YSFGateway
|
||||
|
|
|
@ -4,7 +4,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
|||
LIBS = -lm -lpthread -lsocket
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \
|
||||
OBJECTS = APRSWriter.o Conf.o CRC.o DTMF.o FCSNetwork.o Golay24128.o GPS.o Log.o StopWatch.o Sync.o Thread.o Timer.o \
|
||||
UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFNetwork.o YSFPayload.o YSFReflectors.o
|
||||
|
||||
all: YSFGateway
|
||||
|
|
|
@ -1,232 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2013,2016 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 "TCPSocket.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
typedef int ssize_t;
|
||||
#else
|
||||
#include <cerrno>
|
||||
#endif
|
||||
|
||||
CTCPSocket::CTCPSocket(const std::string& address, unsigned int port) :
|
||||
m_address(address),
|
||||
m_port(port),
|
||||
m_fd(-1)
|
||||
{
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
WSAData data;
|
||||
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (wsaRet != 0)
|
||||
LogError("Error from WSAStartup");
|
||||
#endif
|
||||
}
|
||||
|
||||
CTCPSocket::~CTCPSocket()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CTCPSocket::open()
|
||||
{
|
||||
if (m_fd != -1)
|
||||
return true;
|
||||
|
||||
if (m_address.empty() || m_port == 0U)
|
||||
return false;
|
||||
|
||||
m_fd = ::socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (m_fd < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot create the TCP client socket, err=%d", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot create the TCP client socket, err=%d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
::memset(&addr, 0x00, sizeof(struct sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(m_port);
|
||||
addr.sin_addr = CUDPSocket::lookup(m_address);
|
||||
|
||||
if (addr.sin_addr.s_addr == INADDR_NONE) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::connect(m_fd, (sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot connect the TCP client socket, err=%d", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot connect the TCP client socket, err=%d", errno);
|
||||
#endif
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
int noDelay = 1;
|
||||
if (::setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&noDelay, sizeof(noDelay)) == -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Cannot set the TCP client socket option, err=%d", ::GetLastError());
|
||||
#else
|
||||
LogError("Cannot set the TCP client socket option, err=%d", errno);
|
||||
#endif
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CTCPSocket::read(unsigned char* buffer, unsigned int length, unsigned int secs, unsigned int msecs)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd != -1);
|
||||
|
||||
// Check that the recv() won't block
|
||||
fd_set readFds;
|
||||
FD_ZERO(&readFds);
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
FD_SET((unsigned int)m_fd, &readFds);
|
||||
#else
|
||||
FD_SET(m_fd, &readFds);
|
||||
#endif
|
||||
|
||||
// Return after timeout
|
||||
timeval tv;
|
||||
tv.tv_sec = secs;
|
||||
tv.tv_usec = msecs * 1000;
|
||||
|
||||
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
|
||||
if (ret < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from TCP client select, err=%d", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from TCP client select, err=%d", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (!FD_ISSET((unsigned int)m_fd, &readFds))
|
||||
return 0;
|
||||
#else
|
||||
if (!FD_ISSET(m_fd, &readFds))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
ssize_t len = ::recv(m_fd, (char*)buffer, length, 0);
|
||||
if (len == 0) {
|
||||
return -2;
|
||||
} else if (len < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from recv, err=%d", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from recv, err=%d", errno);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int CTCPSocket::readLine(std::string& line, unsigned int secs)
|
||||
{
|
||||
// Maybe there is a better way to do this like reading blocks, pushing them for later calls
|
||||
// Nevermind, we'll read one char at a time for the time being.
|
||||
int resultCode;
|
||||
int len = 0;
|
||||
|
||||
line.clear();
|
||||
|
||||
char c[2U];
|
||||
c[1U] = 0x00U;
|
||||
|
||||
do
|
||||
{
|
||||
resultCode = read((unsigned char*)c, 1U, secs);
|
||||
if (resultCode == 1){
|
||||
line.append(c);
|
||||
len++;
|
||||
}
|
||||
} while (c[0U] != '\n' && resultCode == 1);
|
||||
|
||||
return resultCode <= 0 ? resultCode : len;
|
||||
}
|
||||
|
||||
bool CTCPSocket::write(const unsigned char* buffer, unsigned int length)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(length > 0U);
|
||||
assert(m_fd != -1);
|
||||
|
||||
ssize_t ret = ::send(m_fd, (char *)buffer, length, 0);
|
||||
if (ret != ssize_t(length)) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LogError("Error returned from send, err=%d", ::GetLastError());
|
||||
#else
|
||||
LogError("Error returned from send, err=%d", errno);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTCPSocket::writeLine(const std::string& line)
|
||||
{
|
||||
std::string lineCopy(line);
|
||||
if (lineCopy.length() > 0 && lineCopy.at(lineCopy.length() - 1) != '\n')
|
||||
lineCopy.append("\n");
|
||||
|
||||
//stupidly write one char after the other
|
||||
size_t len = lineCopy.length();
|
||||
bool result = true;
|
||||
for (size_t i = 0U; i < len && result; i++){
|
||||
unsigned char c = lineCopy.at(i);
|
||||
result = write(&c , 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CTCPSocket::close()
|
||||
{
|
||||
if (m_fd != -1) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::closesocket(m_fd);
|
||||
#else
|
||||
::close(m_fd);
|
||||
#endif
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010,2011,2012,2013,2016 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 TCPSocket_H
|
||||
#define TCPSocket_H
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
class CTCPSocket {
|
||||
public:
|
||||
CTCPSocket(const std::string& address, unsigned int port);
|
||||
~CTCPSocket();
|
||||
|
||||
bool open();
|
||||
|
||||
int read(unsigned char* buffer, unsigned int length, unsigned int secs, unsigned int msecs = 0U);
|
||||
int readLine(std::string& line, unsigned int secs);
|
||||
bool write(const unsigned char* buffer, unsigned int length);
|
||||
bool writeLine(const std::string& line);
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
std::string m_address;
|
||||
unsigned short m_port;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -19,6 +19,6 @@
|
|||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20200405";
|
||||
const char* VERSION = "20200601";
|
||||
|
||||
#endif
|
||||
|
|
|
@ -454,12 +454,11 @@ void CYSFGateway::createGPS()
|
|||
if (!m_conf.getAPRSEnabled())
|
||||
return;
|
||||
|
||||
std::string hostname = m_conf.getAPRSServer();
|
||||
unsigned int port = m_conf.getAPRSPort();
|
||||
std::string password = m_conf.getAPRSPassword();
|
||||
std::string suffix = m_conf.getAPRSSuffix();
|
||||
std::string address = m_conf.getAPRSAddress();
|
||||
unsigned int port = m_conf.getAPRSPort();
|
||||
std::string suffix = m_conf.getAPRSSuffix();
|
||||
|
||||
m_writer = new CAPRSWriter(m_callsign, m_suffix, password, hostname, port, suffix);
|
||||
m_writer = new CAPRSWriter(m_callsign, m_suffix, address, port, suffix);
|
||||
|
||||
unsigned int txFrequency = m_conf.getTxFrequency();
|
||||
unsigned int rxFrequency = m_conf.getRxFrequency();
|
||||
|
|
|
@ -28,12 +28,10 @@ FileLevel=1
|
|||
FilePath=.
|
||||
FileRoot=YSFGateway
|
||||
|
||||
[aprs.fi]
|
||||
[APRS]
|
||||
Enable=0
|
||||
# Server=noam.aprs2.net
|
||||
Server=euro.aprs2.net
|
||||
Port=14580
|
||||
Password=9999
|
||||
Address=127.0.0.1
|
||||
Port=8673
|
||||
Description=APRS Description
|
||||
Suffix=Y
|
||||
|
||||
|
|
|
@ -147,7 +147,6 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="APRSWriter.h" />
|
||||
<ClInclude Include="APRSWriterThread.h" />
|
||||
<ClInclude Include="Conf.h" />
|
||||
<ClInclude Include="CRC.h" />
|
||||
<ClInclude Include="DTMF.h" />
|
||||
|
@ -158,7 +157,6 @@
|
|||
<ClInclude Include="RingBuffer.h" />
|
||||
<ClInclude Include="StopWatch.h" />
|
||||
<ClInclude Include="Sync.h" />
|
||||
<ClInclude Include="TCPSocket.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="UDPSocket.h" />
|
||||
|
@ -175,7 +173,6 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="APRSWriter.cpp" />
|
||||
<ClCompile Include="APRSWriterThread.cpp" />
|
||||
<ClCompile Include="Conf.cpp" />
|
||||
<ClCompile Include="CRC.cpp" />
|
||||
<ClCompile Include="DTMF.cpp" />
|
||||
|
@ -185,7 +182,6 @@
|
|||
<ClCompile Include="Log.cpp" />
|
||||
<ClCompile Include="StopWatch.cpp" />
|
||||
<ClCompile Include="Sync.cpp" />
|
||||
<ClCompile Include="TCPSocket.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="UDPSocket.cpp" />
|
||||
|
|
|
@ -59,12 +59,6 @@
|
|||
<ClInclude Include="WiresX.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TCPSocket.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="APRSWriterThread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -130,12 +124,6 @@
|
|||
<ClCompile Include="WiresX.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TCPSocket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="APRSWriterThread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Thread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
Loading…
Reference in a new issue