1
0
Fork 0

Add aprs.fi gateway.

ycs232-kbc
Jonathan Naylor 8 years ago
parent e2ee965375
commit d432297f24

@ -0,0 +1,276 @@
/*
* Copyright (C) 2010-2014,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 "APRSWriter.h"
#include "YSFDefines.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <ctime>
CAPRSWriter::CAPRSWriter(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port) :
m_thread(NULL),
m_enabled(false),
m_idTimer(1000U, 20U * 60U), // 20 minutes
m_callsign(),
m_txFrequency(0U),
m_rxFrequency(0U),
m_latitude(0.0F),
m_longitude(0.0F),
m_height(0),
m_band()
{
assert(!callsign.empty());
assert(!password.empty());
assert(!address.empty());
assert(port > 0U);
m_thread = new CAPRSWriterThread(callsign, password, address, port);
}
CAPRSWriter::~CAPRSWriter()
{
}
void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height)
{
m_txFrequency = txFrequency;
m_rxFrequency = rxFrequency;
m_latitude = latitude;
m_longitude = longitude;
m_height = height;
if (txFrequency >= 1200000000U)
m_band = "A";
else if (txFrequency >= 420000000U)
m_band = "B";
else if (txFrequency >= 144000000U)
m_band = "C";
else if (txFrequency >= 50000000U)
m_band = "D";
else if (txFrequency >= 28000000U)
m_band = "D";
}
bool CAPRSWriter::open()
{
return m_thread->start();
}
void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned char radio, float fLatitude, float fLongitude)
{
assert(source != NULL);
assert(type != NULL);
char callsign[11U];
::memcpy(callsign, source, YSF_CALLSIGN_LENGTH);
callsign[YSF_CALLSIGN_LENGTH] = 0x00U;
char* p = ::strchr(callsign, ' ');
if (p != NULL)
*p = 0x00U;
p = ::strchr(callsign, '/');
if (p != NULL)
*p = 0x00U;
double tempLat = ::fabs(fLatitude);
double tempLong = ::fabs(fLongitude);
double latitude = ::floor(tempLat);
double longitude = ::floor(tempLong);
latitude = (tempLat - latitude) * 60.0 + latitude * 100.0;
longitude = (tempLong - longitude) * 60.0 + longitude * 100.0;
char lat[20U];
if (latitude >= 1000.0F)
::sprintf(lat, "%.2lf", latitude);
else if (latitude >= 100.0F)
::sprintf(lat, "0%.2lf", latitude);
else if (latitude >= 10.0F)
::sprintf(lat, "00%.2lf", latitude);
else
::sprintf(lat, "000%.2lf", latitude);
char lon[20U];
if (longitude >= 10000.0F)
::sprintf(lon, "%.2lf", longitude);
else if (longitude >= 1000.0F)
::sprintf(lon, "0%.2lf", longitude);
else if (longitude >= 100.0F)
::sprintf(lon, "00%.2lf", longitude);
else if (longitude >= 10.0F)
::sprintf(lon, "000%.2lf", longitude);
else
::sprintf(lon, "0000%.2lf", longitude);
// Convert commas to periods in the latitude, longitude and frequencies
p = ::strchr(lat, ',');
if (p != NULL)
*p = '.';
p = ::strchr(lon, ',');
if (p != NULL)
*p = '.';
char symbol;
switch (radio) {
case 0x24U:
case 0x28U:
symbol = '[';
break;
case 0x25U:
case 0x29U:
symbol = '>';
break;
case 0x26U:
symbol = 'r';
break;
default:
symbol = '-';
break;
}
char output[300U];
::sprintf(output, "%s>APDPRS,C4FM*,qAR,%s-%s:!%s%c/%s%c%c %s via MMDVM",
callsign, m_callsign.c_str(), m_band.c_str(),
lat, (fLatitude < 0.0F) ? 'S' : 'N',
lon, (fLongitude < 0.0F) ? 'W' : 'E',
symbol, type);
m_thread->write(output);
}
void CAPRSWriter::clock(unsigned int ms)
{
m_idTimer.clock(ms);
if (m_idTimer.hasExpired()) {
sendIdFrames();
m_idTimer.start();
}
}
void CAPRSWriter::close()
{
m_thread->stop();
}
void CAPRSWriter::sendIdFrames()
{
if (!m_thread->isConnected())
return;
time_t now;
::time(&now);
struct tm* tm = ::gmtime(&now);
// Default values aren't passed on
if (m_latitude == 0.0F && m_longitude == 0.0F)
return;
char desc[100U];
if (m_txFrequency != 0U) {
float offset = float(int(m_rxFrequency) - int(m_txFrequency)) / 1000000.0F;
::sprintf(desc, "MMDVM Voice %.5lfMHz %c%.4lfMHz",
float(m_txFrequency) / 1000000.0F,
offset < 0.0F ? '-' : '+',
::fabs(offset));
} else {
::strcpy(desc, "MMDVM Voice");
}
char* band;
if (m_txFrequency >= 1200000000U)
band = "1.2";
else if (m_txFrequency >= 420000000U)
band = "440";
else if (m_txFrequency >= 144000000U)
band = "2m";
else if (m_txFrequency >= 50000000U)
band = "6m";
else if (m_txFrequency >= 28000000U)
band = "10m";
double tempLat = ::fabs(m_latitude);
double tempLong = ::fabs(m_longitude);
double latitude = ::floor(tempLat);
double longitude = ::floor(tempLong);
latitude = (tempLat - latitude) * 60.0 + latitude * 100.0;
longitude = (tempLong - longitude) * 60.0 + longitude * 100.0;
char lat[20U];
if (latitude >= 1000.0F)
::sprintf(lat, "%.2lf", latitude);
else if (latitude >= 100.0F)
::sprintf(lat, "0%.2lf", latitude);
else if (latitude >= 10.0F)
::sprintf(lat, "00%.2lf", latitude);
else
::sprintf(lat, "000%.2lf", latitude);
char lon[20U];
if (longitude >= 10000.0F)
::sprintf(lon, "%.2lf", longitude);
else if (longitude >= 1000.0F)
::sprintf(lon, "0%.2lf", longitude);
else if (longitude >= 100.0F)
::sprintf(lon, "00%.2lf", longitude);
else if (longitude >= 10.0F)
::sprintf(lon, "000%.2lf", longitude);
else
::sprintf(lon, "0000%.2lf", longitude);
// Convert commas to periods in the latitude, longitude and frequencies
char* p = ::strchr(lat, ',');
if (p != NULL)
*p = '.';
p = ::strchr(lon, ',');
if (p != NULL)
*p = '.';
p = ::strchr(desc, ',');
if (p != NULL)
*p = '.';
char output[500U];
::sprintf(output, "%s-S>APDG03,TCPIP*,qAC,%s-NDS:;%-7s%-2s*%02d%02d%02dz%s%cD%s%ca/A=%06.0f%s %s",
m_callsign.c_str(), m_callsign.c_str(), m_callsign.c_str(), m_band.c_str(),
tm->tm_mday, tm->tm_hour, tm->tm_min,
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);
::sprintf(output, "%s-%s>APDG04,TCPIP*,qAC,%s-%sS:!%s%cD%s%c&/A=%06.0f%s %s",
m_callsign.c_str(), m_band.c_str(), m_callsign.c_str(), m_band.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_idTimer.start();
}

@ -0,0 +1,57 @@
/*
* Copyright (C) 2010,2011,2012,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 APRSWriter_H
#define APRSWriter_H
#include "APRSWriterThread.h"
#include "Timer.h"
#include <string>
class CAPRSWriter {
public:
CAPRSWriter(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port);
~CAPRSWriter();
bool open();
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height);
void write(const unsigned char* source, const char* type, unsigned char radio, float latitude, float longitude);
void clock(unsigned int ms);
void close();
private:
CAPRSWriterThread* m_thread;
bool m_enabled;
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_band;
void sendIdFrames();
};
#endif

@ -33,12 +33,12 @@ 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, const std::string& hostname, unsigned int port) :
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_ssid(callsign),
m_socket(hostname, port, address),
m_socket(address, port),
m_queue(20U, "APRS Queue"),
m_exit(false),
m_connected(false),
@ -48,7 +48,7 @@ m_clientName("YSFGateway")
{
assert(!callsign.empty());
assert(!password.empty());
assert(!hostname.empty());
assert(!address.empty());
assert(port > 0U);
m_username.resize(CALLSIGN_LENGTH, ' ');
@ -58,12 +58,12 @@ m_clientName("YSFGateway")
m_ssid = m_ssid.substr(CALLSIGN_LENGTH - 1U, 1);
}
CAPRSWriterThread::CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, const std::string& hostname, unsigned int port, const std::string& filter, const std::string& clientName) :
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_ssid(callsign),
m_socket(hostname, port, address),
m_socket(address, port),
m_queue(20U, "APRS Queue"),
m_exit(false),
m_connected(false),
@ -73,7 +73,7 @@ m_clientName(clientName)
{
assert(!callsign.empty());
assert(!password.empty());
assert(!hostname.empty());
assert(!address.empty());
assert(port > 0U);
m_username.resize(CALLSIGN_LENGTH, ' ');

@ -29,8 +29,8 @@ typedef void (*ReadAPRSFrameCallback)(const std::string&);
class CAPRSWriterThread : public CThread {
public:
CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, const std::string& hostname, unsigned int port);
CAPRSWriterThread(const std::string& callsign, const std::string& password, const std::string& address, const std::string& hostname, unsigned int port, const std::string& filter, const std::string& clientName);
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();

@ -30,15 +30,16 @@ const unsigned char NULL_GPS[] = {0x47U, 0x63U};
const unsigned char SHRT_GPS[] = {0x22U, 0x62U};
const unsigned char LONG_GPS[] = {0x47U, 0x64U};
CGPS::CGPS(const std::string& hostname, unsigned int port, const std::string& password) :
m_hostname(hostname),
m_port(port),
m_password(password),
CGPS::CGPS(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port) :
m_writer(callsign, password, address, port),
m_buffer(NULL),
m_dt1(false),
m_dt2(false),
m_sent(false)
{
assert(!callsign.empty());
assert(!password.empty());
assert(!address.empty());
assert(port > 0U);
m_buffer = new unsigned char[20U];
@ -49,6 +50,16 @@ CGPS::~CGPS()
delete[] m_buffer;
}
void CGPS::setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height)
{
m_writer.setInfo(rxFrequency, rxFrequency, latitude, longitude, height);
}
bool CGPS::open()
{
return m_writer.open();
}
void CGPS::data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn)
{
if (m_sent)
@ -252,12 +263,19 @@ void CGPS::transmitGPS(const unsigned char* source)
break;
}
LogMessage("GPS Position of radio=%s lat=%f long=%f", radio, latitude, longitude);
LogMessage("GPS Position from %10.10s of radio=%s lat=%f long=%f", source, radio, latitude, longitude);
m_writer.write(source, radio, m_buffer[4U], latitude, longitude);
m_sent = true;
}
void CGPS::clock(unsigned int ms)
{
m_writer.clock(ms);
}
void CGPS::close()
{
m_writer.close();
}

@ -19,23 +19,29 @@
#if !defined(GPS_H)
#define GPS_H
#include "APRSWriter.h"
#include <string>
class CGPS {
public:
CGPS(const std::string& hostname, unsigned int port, const std::string& password);
CGPS(const std::string& callsign, const std::string& password, const std::string& address, unsigned int port);
~CGPS();
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height);
bool open();
void data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn);
void clock(unsigned int ms);
void reset();
void close();
private:
std::string m_hostname;
unsigned int m_port;
std::string m_password;
CAPRSWriter m_writer;
unsigned char* m_buffer;
bool m_dt1;
bool m_dt2;

@ -4,8 +4,8 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lpthread
LDFLAGS = -g
OBJECTS = APRSWriterThread.o Conf.o CRC.o Golay24128.o GPS.o Hosts.o Log.o Network.o Reflectors.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o UDPSocket.o Utils.o \
WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFPayload.o
OBJECTS = APRSWriterThread.o APRSWriter.o Conf.o CRC.o Golay24128.o GPS.o Hosts.o Log.o Network.o Reflectors.o StopWatch.o Sync.o TCPSocket.o Thread.o Timer.o \
UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFPayload.o
all: YSFGateway

@ -30,10 +30,9 @@ typedef int ssize_t;
#include <cerrno>
#endif
CTCPSocket::CTCPSocket(const std::string& address, unsigned int port, const std::string& localAddress) :
CTCPSocket::CTCPSocket(const std::string& address, unsigned int port) :
m_address(address),
m_port(port),
m_localAddress(localAddress),
m_fd(-1)
{
assert(!address.empty());
@ -47,36 +46,6 @@ m_fd(-1)
#endif
}
CTCPSocket::CTCPSocket(int fd) :
m_address(),
m_port(0U),
m_localAddress(),
m_fd(fd)
{
assert(fd >= 0);
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError("Error from WSAStartup");
#endif
}
CTCPSocket::CTCPSocket() :
m_address(),
m_port(0U),
m_localAddress(),
m_fd(-1)
{
#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)
@ -84,15 +53,6 @@ CTCPSocket::~CTCPSocket()
#endif
}
bool CTCPSocket::open(const std::string& address, unsigned int port, const std::string& localAddress)
{
m_address = address;
m_port = port;
m_localAddress = localAddress;
return open();
}
bool CTCPSocket::open()
{
if (m_fd != -1)
@ -111,33 +71,6 @@ bool CTCPSocket::open()
return false;
}
if (!m_localAddress.empty()) {
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = 0U;
#if defined(_WIN32) || defined(_WIN64)
addr.sin_addr.s_addr = ::inet_addr(m_localAddress.c_str());
#else
addr.sin_addr.s_addr = ::inet_addr(m_localAddress.c_str());
#endif
if (addr.sin_addr.s_addr == INADDR_NONE) {
LogError("The address is invalid - %s", m_localAddress.c_str());
close();
return false;
}
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError("Cannot bind the TCP client address, err=%d", ::GetLastError());
#else
LogError("Cannot bind the TCP client address, err=%d", errno);
#endif
close();
return false;
}
}
struct sockaddr_in addr;
::memset(&addr, 0x00, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;

@ -37,12 +37,9 @@
class CTCPSocket {
public:
CTCPSocket(const std::string& address, unsigned int port, const std::string& localAddress);
CTCPSocket(int fd);
CTCPSocket();
CTCPSocket(const std::string& address, unsigned int port);
~CTCPSocket();
bool open(const std::string& address, unsigned int port, const std::string& localAddress);
bool open();
int read(unsigned char* buffer, unsigned int length, unsigned int secs, unsigned int msecs = 0U);
@ -55,7 +52,6 @@ public:
private:
std::string m_address;
unsigned short m_port;
std::string m_localAddress;
int m_fd;
};

@ -74,6 +74,7 @@ int main(int argc, char** argv)
}
CYSFGateway::CYSFGateway(const std::string& configFile) :
m_callsign(),
m_conf(configFile),
m_gps(NULL),
m_wiresX(NULL),
@ -159,7 +160,7 @@ int CYSFGateway::run()
}
#endif
std::string callsign = m_conf.getCallsign();
m_callsign = m_conf.getCallsign();
bool debug = m_conf.getNetworkDebug();
in_addr rptAddress = CUDPSocket::lookup(m_conf.getRptAddress());
@ -190,7 +191,7 @@ int CYSFGateway::run()
std::string fileName = m_conf.getNetworkHosts();
unsigned int port = m_conf.getNetworkStatusPort();
m_wiresX = new CWiresX(callsign, &rptNetwork, fileName, port);
m_wiresX = new CWiresX(m_callsign, &rptNetwork, fileName, port);
std::string name = m_conf.getName();
unsigned int txFrequency = m_conf.getTxFrequency();
@ -294,7 +295,11 @@ int CYSFGateway::run()
rptNetwork.close();
m_netNetwork->close();
delete m_gps;
if (m_gps != NULL) {
m_gps->close();
delete m_gps;
}
delete m_netNetwork;
delete m_wiresX;
@ -312,5 +317,19 @@ void CYSFGateway::createGPS()
unsigned int port = m_conf.getAPRSPort();
std::string password = m_conf.getAPRSPassword();
m_gps = new CGPS(hostname, port, password);
m_gps = new CGPS(m_callsign, password, hostname, port);
unsigned int txFrequency = m_conf.getTxFrequency();
unsigned int rxFrequency = m_conf.getRxFrequency();
float latitude = m_conf.getLatitude();
float longitude = m_conf.getLongitude();
int height = m_conf.getHeight();
m_gps->setInfo(txFrequency, rxFrequency, latitude, longitude, height);
bool ret = m_gps->open();
if (!ret) {
delete m_gps;
m_gps = NULL;
}
}

@ -35,12 +35,13 @@ public:
int run();
private:
CConf m_conf;
CGPS* m_gps;
CWiresX* m_wiresX;
CNetwork* m_netNetwork;
bool m_linked;
bool m_exclude;
std::string m_callsign;
CConf m_conf;
CGPS* m_gps;
CWiresX* m_wiresX;
CNetwork* m_netNetwork;
bool m_linked;
bool m_exclude;
void createGPS();
};

@ -146,6 +146,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="APRSWriter.h" />
<ClInclude Include="APRSWriterThread.h" />
<ClInclude Include="Conf.h" />
<ClInclude Include="CRC.h" />
@ -172,6 +173,7 @@
<ClInclude Include="YSFPayload.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="APRSWriter.cpp" />
<ClCompile Include="APRSWriterThread.cpp" />
<ClCompile Include="Conf.cpp" />
<ClCompile Include="CRC.cpp" />

@ -83,6 +83,9 @@
<ClInclude Include="Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="APRSWriter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Network.cpp">
@ -148,5 +151,8 @@
<ClCompile Include="Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="APRSWriter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
Loading…
Cancel
Save