1
0
Fork 0

First version of the mobile GPS client code.

ycs232-kbc
Jonathan Naylor 6 years ago
parent f3e99d570d
commit 0446deefad

@ -36,7 +36,10 @@ m_latitude(0.0F),
m_longitude(0.0F), m_longitude(0.0F),
m_height(0), m_height(0),
m_desc(), m_desc(),
m_suffix(suffix) m_suffix(suffix),
m_mobileGPSAddress(),
m_mobileGPSPort(0U),
m_socket(NULL)
{ {
assert(!callsign.empty()); assert(!callsign.empty());
assert(!password.empty()); assert(!password.empty());
@ -65,9 +68,33 @@ void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, fl
m_desc = desc; m_desc = desc;
} }
void CAPRSWriter::setMobileGPS(const std::string& address, unsigned int port)
{
assert(!address.empty());
assert(port > 0U);
m_mobileGPSAddress = CUDPSocket::lookup(address);
m_mobileGPSPort = port;
m_socket = new CUDPSocket;
}
bool CAPRSWriter::open() bool CAPRSWriter::open()
{ {
if (m_socket != NULL) {
bool ret = m_socket->open();
if (!ret) {
delete m_socket;
m_socket = NULL;
return false;
}
// Poll the GPS every minute
m_idTimer.setTimeout(60U);
}
m_idTimer.start(); m_idTimer.start();
return m_thread->start(); return m_thread->start();
} }
@ -135,18 +162,39 @@ void CAPRSWriter::clock(unsigned int ms)
{ {
m_idTimer.clock(ms); m_idTimer.clock(ms);
if (m_socket != NULL) {
if (m_idTimer.hasExpired()) {
pollGPS();
m_idTimer.start();
}
sendIdFrameMobile();
} else {
if (m_idTimer.hasExpired()) { if (m_idTimer.hasExpired()) {
sendIdFrames(); sendIdFrameFixed();
m_idTimer.start(); m_idTimer.start();
} }
}
} }
void CAPRSWriter::close() void CAPRSWriter::close()
{ {
if (m_socket != NULL) {
m_socket->close();
delete m_socket;
}
m_thread->stop(); m_thread->stop();
} }
void CAPRSWriter::sendIdFrames() bool CAPRSWriter::pollGPS()
{
assert(m_socket != NULL);
return m_socket->write((unsigned char*)"YSFGateway", 10U, m_mobileGPSAddress, m_mobileGPSPort);
}
void CAPRSWriter::sendIdFrameFixed()
{ {
if (!m_thread->isConnected()) if (!m_thread->isConnected())
return; return;
@ -211,3 +259,92 @@ void CAPRSWriter::sendIdFrames()
m_idTimer.start(); m_idTimer.start();
} }
void CAPRSWriter::sendIdFrameMobile()
{
// Grab GPS data if it's available
unsigned char buffer[200U];
in_addr address;
unsigned int port;
int ret = m_socket->read(buffer, 200U, address, port);
if (ret <= 0)
return;
if (!m_thread->isConnected())
return;
buffer[ret] = '\0';
// Parse the GPS data
char* p1 = ::strtok((char*)buffer, ","); // Latitude
char* p2 = ::strtok(NULL, ","); // Longitude
char* p3 = ::strtok(NULL, ","); // Altitude (m)
char* p4 = ::strtok(NULL, ","); // Speed (kms/h)
char* p5 = ::strtok(NULL, "\n"); // Bearing
if (p1 == NULL || p2 == NULL || p3 == NULL || p4 == NULL || p5 == NULL)
return;
float rawLatitude = ::atof(p1);
float rawLongitude = ::atof(p2);
float rawAltitude = ::atof(p3);
float rawSpeed = ::atof(p4);
float rawBearing = ::atof(p5);
char desc[200U];
if (m_txFrequency != 0U) {
float offset = float(int(m_rxFrequency) - int(m_txFrequency)) / 1000000.0F;
::sprintf(desc, "MMDVM Voice %.5LfMHz %c%.4lfMHz%s%s",
(long double)(m_txFrequency) / 1000000.0F,
offset < 0.0F ? '-' : '+',
::fabs(offset), m_desc.empty() ? "" : ", ", m_desc.c_str());
} else {
::sprintf(desc, "MMDVM Voice%s%s", m_desc.empty() ? "" : ", ", m_desc.c_str());
}
const char* band = "4m";
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(rawLatitude);
double tempLong = ::fabs(rawLongitude);
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];
::sprintf(lat, "%07.2lf", latitude);
char lon[20U];
::sprintf(lon, "%08.2lf", longitude);
std::string server = m_callsign;
size_t pos = server.find_first_of('-');
if (pos == std::string::npos)
server.append("-S");
else
server.append("S");
char output[500U];
::sprintf(output, "%s>APDG03,TCPIP*,qAC,%s:!%s%cD%s%c&%03.0f/%03.0f/A=%06.0f%s %s",
m_callsign.c_str(), server.c_str(),
lat, (rawLatitude < 0.0F) ? 'S' : 'N',
lon, (rawLongitude < 0.0F) ? 'W' : 'E',
rawBearing, rawSpeed * 0.539957F,
float(rawAltitude) * 3.28F, band, desc);
m_thread->write(output);
m_idTimer.start();
}

@ -20,10 +20,24 @@
#define APRSWriter_H #define APRSWriter_H
#include "APRSWriterThread.h" #include "APRSWriterThread.h"
#include "UDPSocket.h"
#include "Timer.h" #include "Timer.h"
#include <string> #include <string>
#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 <arpa/inet.h>
#include <errno.h>
#else
#include <winsock.h>
#endif
class CAPRSWriter { class CAPRSWriter {
public: 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& password, const std::string& address, unsigned int port, const std::string& suffix);
@ -33,6 +47,8 @@ public:
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height, const std::string& desc); void setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height, const std::string& desc);
void setMobileGPS(const std::string& address, unsigned int port);
void write(const unsigned char* source, const char* type, unsigned char radio, float latitude, float longitude); void write(const unsigned char* source, const char* type, unsigned char radio, float latitude, float longitude);
void clock(unsigned int ms); void clock(unsigned int ms);
@ -51,8 +67,13 @@ private:
int m_height; int m_height;
std::string m_desc; std::string m_desc;
std::string m_suffix; std::string m_suffix;
in_addr m_mobileGPSAddress;
unsigned int m_mobileGPSPort;
CUDPSocket* m_socket;
void sendIdFrames(); bool pollGPS();
void sendIdFrameFixed();
void sendIdFrameMobile();
}; };
#endif #endif

@ -34,7 +34,8 @@ enum SECTION {
SECTION_APRS_FI, SECTION_APRS_FI,
SECTION_NETWORK, SECTION_NETWORK,
SECTION_YSF_NETWORK, SECTION_YSF_NETWORK,
SECTION_FCS_NETWORK SECTION_FCS_NETWORK,
SECTION_MOBILE_GPS
}; };
CConf::CConf(const std::string& file) : CConf::CConf(const std::string& file) :
@ -83,7 +84,10 @@ m_ysfNetworkYSF2P25Address("127.0.0.1"),
m_ysfNetworkYSF2P25Port(0U), m_ysfNetworkYSF2P25Port(0U),
m_fcsNetworkEnabled(false), m_fcsNetworkEnabled(false),
m_fcsNetworkFile(), m_fcsNetworkFile(),
m_fcsNetworkPort(0U) m_fcsNetworkPort(0U),
m_mobileGPSEnabled(false),
m_mobileGPSAddress(),
m_mobileGPSPort(0U)
{ {
} }
@ -121,6 +125,8 @@ bool CConf::read()
section = SECTION_YSF_NETWORK; section = SECTION_YSF_NETWORK;
else if (::strncmp(buffer, "[FCS Network]", 13U) == 0) else if (::strncmp(buffer, "[FCS Network]", 13U) == 0)
section = SECTION_FCS_NETWORK; section = SECTION_FCS_NETWORK;
else if (::strncmp(buffer, "[Mobile GPS]", 12U) == 0)
section = SECTION_MOBILE_GPS;
else else
section = SECTION_NONE; section = SECTION_NONE;
@ -235,6 +241,13 @@ bool CConf::read()
m_fcsNetworkFile = value; m_fcsNetworkFile = value;
else if (::strcmp(key, "Port") == 0) else if (::strcmp(key, "Port") == 0)
m_fcsNetworkPort = (unsigned int)::atoi(value); m_fcsNetworkPort = (unsigned int)::atoi(value);
} else if (section == SECTION_MOBILE_GPS) {
if (::strcmp(key, "Enable") == 0)
m_mobileGPSEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Address") == 0)
m_mobileGPSAddress = value;
else if (::strcmp(key, "Port") == 0)
m_mobileGPSPort = (unsigned int)::atoi(value);
} }
} }
@ -453,6 +466,7 @@ unsigned int CConf::getYSFNetworkYSF2P25Port() const
return m_ysfNetworkYSF2P25Port; return m_ysfNetworkYSF2P25Port;
} }
bool CConf::getFCSNetworkEnabled() const bool CConf::getFCSNetworkEnabled() const
{ {
return m_fcsNetworkEnabled; return m_fcsNetworkEnabled;
@ -467,3 +481,18 @@ unsigned int CConf::getFCSNetworkPort() const
{ {
return m_fcsNetworkPort; return m_fcsNetworkPort;
} }
bool CConf::getMobileGPSEnabled() const
{
return m_mobileGPSEnabled;
}
std::string CConf::getMobileGPSAddress() const
{
return m_mobileGPSAddress;
}
unsigned int CConf::getMobileGPSPort() const
{
return m_mobileGPSPort;
}

@ -88,6 +88,11 @@ public:
std::string getFCSNetworkFile() const; std::string getFCSNetworkFile() const;
unsigned int getFCSNetworkPort() const; unsigned int getFCSNetworkPort() const;
// The Mobile GPS section
bool getMobileGPSEnabled() const;
std::string getMobileGPSAddress() const;
unsigned int getMobileGPSPort() const;
private: private:
std::string m_file; std::string m_file;
std::string m_callsign; std::string m_callsign;
@ -141,6 +146,10 @@ private:
bool m_fcsNetworkEnabled; bool m_fcsNetworkEnabled;
std::string m_fcsNetworkFile; std::string m_fcsNetworkFile;
unsigned int m_fcsNetworkPort; unsigned int m_fcsNetworkPort;
bool m_mobileGPSEnabled;
std::string m_mobileGPSAddress;
unsigned int m_mobileGPSPort;
}; };
#endif #endif

@ -31,15 +31,12 @@ const unsigned char NULL_GPS[] = {0x47U, 0x63U};
const unsigned char SHRT_GPS[] = {0x22U, 0x62U}; const unsigned char SHRT_GPS[] = {0x22U, 0x62U};
const unsigned char LONG_GPS[] = {0x47U, 0x64U}; const unsigned char LONG_GPS[] = {0x47U, 0x64U};
CGPS::CGPS(const std::string& callsign, const std::string& rptSuffix, const std::string& password, const std::string& address, unsigned int port, const std::string suffix) : CGPS::CGPS(CAPRSWriter* writer) :
m_writer(callsign, rptSuffix, password, address, port, suffix), m_writer(writer),
m_buffer(NULL), m_buffer(NULL),
m_sent(false) m_sent(false)
{ {
assert(!callsign.empty()); assert(writer != NULL);
assert(!password.empty());
assert(!address.empty());
assert(port > 0U);
m_buffer = new unsigned char[300U]; m_buffer = new unsigned char[300U];
} }
@ -49,16 +46,6 @@ CGPS::~CGPS()
delete[] m_buffer; delete[] m_buffer;
} }
void CGPS::setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height, const std::string& desc)
{
m_writer.setInfo(txFrequency, rxFrequency, latitude, longitude, height, desc);
}
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, unsigned char ft) void CGPS::data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft)
{ {
if (m_sent) if (m_sent)
@ -150,6 +137,8 @@ void CGPS::reset()
void CGPS::transmitGPS(const unsigned char* source) void CGPS::transmitGPS(const unsigned char* source)
{ {
assert(m_writer != NULL);
// We don't know who its from! // We don't know who its from!
if (::memcmp(source, " ", YSF_CALLSIGN_LENGTH) == 0) if (::memcmp(source, " ", YSF_CALLSIGN_LENGTH) == 0)
return; return;
@ -275,17 +264,7 @@ void CGPS::transmitGPS(const unsigned char* source)
LogMessage("GPS Position from %10.10s of radio=%s lat=%f long=%f", source, 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_writer->write(source, radio, m_buffer[4U], latitude, longitude);
m_sent = true; m_sent = true;
} }
void CGPS::clock(unsigned int ms)
{
m_writer.clock(ms);
}
void CGPS::close()
{
m_writer.close();
}

@ -25,23 +25,15 @@
class CGPS { class CGPS {
public: public:
CGPS(const std::string& callsign, const std::string& rptSuffix, const std::string& password, const std::string& address, unsigned int port, const std::string suffix); CGPS(CAPRSWriter* writer);
~CGPS(); ~CGPS();
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height, const std::string& desc);
bool open();
void data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft); void data(const unsigned char* source, const unsigned char* data, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft);
void clock(unsigned int ms);
void reset(); void reset();
void close();
private: private:
CAPRSWriter m_writer; CAPRSWriter* m_writer;
unsigned char* m_buffer; unsigned char* m_buffer;
bool m_sent; bool m_sent;

@ -78,6 +78,7 @@ CYSFGateway::CYSFGateway(const std::string& configFile) :
m_callsign(), m_callsign(),
m_suffix(), m_suffix(),
m_conf(configFile), m_conf(configFile),
m_writer(NULL),
m_gps(NULL), m_gps(NULL),
m_reflectors(NULL), m_reflectors(NULL),
m_wiresX(NULL), m_wiresX(NULL),
@ -328,8 +329,8 @@ int CYSFGateway::run()
m_ysfNetwork->clock(ms); m_ysfNetwork->clock(ms);
if (m_fcsNetwork != NULL) if (m_fcsNetwork != NULL)
m_fcsNetwork->clock(ms); m_fcsNetwork->clock(ms);
if (m_gps != NULL) if (m_writer != NULL)
m_gps->clock(ms); m_writer->clock(ms);
m_wiresX->clock(ms); m_wiresX->clock(ms);
m_inactivityTimer.clock(ms); m_inactivityTimer.clock(ms);
@ -401,7 +402,8 @@ int CYSFGateway::run()
rptNetwork.close(); rptNetwork.close();
if (m_gps != NULL) { if (m_gps != NULL) {
m_gps->close(); m_writer->close();
delete m_writer;
delete m_gps; delete m_gps;
} }
@ -433,7 +435,7 @@ void CYSFGateway::createGPS()
std::string suffix = m_conf.getAPRSSuffix(); std::string suffix = m_conf.getAPRSSuffix();
std::string desc = m_conf.getAPRSDescription(); std::string desc = m_conf.getAPRSDescription();
m_gps = new CGPS(m_callsign, m_suffix, password, hostname, port, suffix); m_writer = new CAPRSWriter(m_callsign, m_suffix, password, hostname, port, suffix);
unsigned int txFrequency = m_conf.getTxFrequency(); unsigned int txFrequency = m_conf.getTxFrequency();
unsigned int rxFrequency = m_conf.getRxFrequency(); unsigned int rxFrequency = m_conf.getRxFrequency();
@ -441,13 +443,24 @@ void CYSFGateway::createGPS()
float longitude = m_conf.getLongitude(); float longitude = m_conf.getLongitude();
int height = m_conf.getHeight(); int height = m_conf.getHeight();
m_gps->setInfo(txFrequency, rxFrequency, latitude, longitude, height, desc); m_writer->setInfo(txFrequency, rxFrequency, latitude, longitude, height, desc);
bool enabled = m_conf.getMobileGPSEnabled();
if (enabled) {
std::string address = m_conf.getMobileGPSAddress();
unsigned int port = m_conf.getMobileGPSPort();
m_writer->setMobileGPS(address, port);
}
bool ret = m_gps->open(); bool ret = m_writer->open();
if (!ret) { if (!ret) {
delete m_gps; delete m_writer;
m_gps = NULL; m_writer = NULL;
return;
} }
m_gps = new CGPS(m_writer);
} }
void CYSFGateway::createWiresX(CYSFNetwork* rptNetwork) void CYSFGateway::createWiresX(CYSFNetwork* rptNetwork)

@ -22,6 +22,7 @@
#include "YSFNetwork.h" #include "YSFNetwork.h"
#include "YSFReflectors.h" #include "YSFReflectors.h"
#include "FCSNetwork.h" #include "FCSNetwork.h"
#include "APRSWriter.h"
#include "WiresX.h" #include "WiresX.h"
#include "Timer.h" #include "Timer.h"
#include "Conf.h" #include "Conf.h"
@ -48,6 +49,7 @@ private:
std::string m_callsign; std::string m_callsign;
std::string m_suffix; std::string m_suffix;
CConf m_conf; CConf m_conf;
CAPRSWriter* m_writer;
CGPS* m_gps; CGPS* m_gps;
CYSFReflectors* m_reflectors; CYSFReflectors* m_reflectors;
CWiresX* m_wiresX; CWiresX* m_wiresX;

@ -60,3 +60,8 @@ YSF2P25Port=42015
Enable=1 Enable=1
Rooms=./FCSRooms.txt Rooms=./FCSRooms.txt
Port=42001 Port=42001
[Mobile GPS]
Enable=0
Address=127.0.0.1
Port=7834

Loading…
Cancel
Save