First version of the mobile GPS client code.
This commit is contained in:
parent
f3e99d570d
commit
0446deefad
9 changed files with 244 additions and 57 deletions
|
@ -36,7 +36,10 @@ m_latitude(0.0F),
|
|||
m_longitude(0.0F),
|
||||
m_height(0),
|
||||
m_desc(),
|
||||
m_suffix(suffix)
|
||||
m_suffix(suffix),
|
||||
m_mobileGPSAddress(),
|
||||
m_mobileGPSPort(0U),
|
||||
m_socket(NULL)
|
||||
{
|
||||
assert(!callsign.empty());
|
||||
assert(!password.empty());
|
||||
|
@ -65,9 +68,33 @@ void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, fl
|
|||
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()
|
||||
{
|
||||
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();
|
||||
|
||||
return m_thread->start();
|
||||
}
|
||||
|
||||
|
@ -135,18 +162,39 @@ void CAPRSWriter::clock(unsigned int ms)
|
|||
{
|
||||
m_idTimer.clock(ms);
|
||||
|
||||
if (m_idTimer.hasExpired()) {
|
||||
sendIdFrames();
|
||||
m_idTimer.start();
|
||||
if (m_socket != NULL) {
|
||||
if (m_idTimer.hasExpired()) {
|
||||
pollGPS();
|
||||
m_idTimer.start();
|
||||
}
|
||||
|
||||
sendIdFrameMobile();
|
||||
} else {
|
||||
if (m_idTimer.hasExpired()) {
|
||||
sendIdFrameFixed();
|
||||
m_idTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAPRSWriter::close()
|
||||
{
|
||||
if (m_socket != NULL) {
|
||||
m_socket->close();
|
||||
delete m_socket;
|
||||
}
|
||||
|
||||
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())
|
||||
return;
|
||||
|
@ -211,3 +259,92 @@ void CAPRSWriter::sendIdFrames()
|
|||
|
||||
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
|
||||
|
||||
#include "APRSWriterThread.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#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 {
|
||||
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);
|
||||
|
@ -33,6 +47,8 @@ public:
|
|||
|
||||
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 clock(unsigned int ms);
|
||||
|
@ -51,8 +67,13 @@ private:
|
|||
int m_height;
|
||||
std::string m_desc;
|
||||
std::string m_suffix;
|
||||
in_addr m_mobileGPSAddress;
|
||||
unsigned int m_mobileGPSPort;
|
||||
CUDPSocket* m_socket;
|
||||
|
||||
void sendIdFrames();
|
||||
bool pollGPS();
|
||||
void sendIdFrameFixed();
|
||||
void sendIdFrameMobile();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,8 @@ enum SECTION {
|
|||
SECTION_APRS_FI,
|
||||
SECTION_NETWORK,
|
||||
SECTION_YSF_NETWORK,
|
||||
SECTION_FCS_NETWORK
|
||||
SECTION_FCS_NETWORK,
|
||||
SECTION_MOBILE_GPS
|
||||
};
|
||||
|
||||
CConf::CConf(const std::string& file) :
|
||||
|
@ -83,7 +84,10 @@ m_ysfNetworkYSF2P25Address("127.0.0.1"),
|
|||
m_ysfNetworkYSF2P25Port(0U),
|
||||
m_fcsNetworkEnabled(false),
|
||||
m_fcsNetworkFile(),
|
||||
m_fcsNetworkPort(0U)
|
||||
m_fcsNetworkPort(0U),
|
||||
m_mobileGPSEnabled(false),
|
||||
m_mobileGPSAddress(),
|
||||
m_mobileGPSPort(0U)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -121,13 +125,15 @@ bool CConf::read()
|
|||
section = SECTION_YSF_NETWORK;
|
||||
else if (::strncmp(buffer, "[FCS Network]", 13U) == 0)
|
||||
section = SECTION_FCS_NETWORK;
|
||||
else if (::strncmp(buffer, "[Mobile GPS]", 12U) == 0)
|
||||
section = SECTION_MOBILE_GPS;
|
||||
else
|
||||
section = SECTION_NONE;
|
||||
section = SECTION_NONE;
|
||||
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
char* key = ::strtok(buffer, " \t=\r\n");
|
||||
char* key = ::strtok(buffer, " \t=\r\n");
|
||||
if (key == NULL)
|
||||
continue;
|
||||
|
||||
|
@ -235,6 +241,13 @@ bool CConf::read()
|
|||
m_fcsNetworkFile = value;
|
||||
else if (::strcmp(key, "Port") == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
bool CConf::getFCSNetworkEnabled() const
|
||||
{
|
||||
return m_fcsNetworkEnabled;
|
||||
|
@ -467,3 +481,18 @@ unsigned int CConf::getFCSNetworkPort() const
|
|||
{
|
||||
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;
|
||||
unsigned int getFCSNetworkPort() const;
|
||||
|
||||
// The Mobile GPS section
|
||||
bool getMobileGPSEnabled() const;
|
||||
std::string getMobileGPSAddress() const;
|
||||
unsigned int getMobileGPSPort() const;
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
std::string m_callsign;
|
||||
|
@ -141,6 +146,10 @@ private:
|
|||
bool m_fcsNetworkEnabled;
|
||||
std::string m_fcsNetworkFile;
|
||||
unsigned int m_fcsNetworkPort;
|
||||
|
||||
bool m_mobileGPSEnabled;
|
||||
std::string m_mobileGPSAddress;
|
||||
unsigned int m_mobileGPSPort;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,15 +31,12 @@ 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& callsign, const std::string& rptSuffix, const std::string& password, const std::string& address, unsigned int port, const std::string suffix) :
|
||||
m_writer(callsign, rptSuffix, password, address, port, suffix),
|
||||
CGPS::CGPS(CAPRSWriter* writer) :
|
||||
m_writer(writer),
|
||||
m_buffer(NULL),
|
||||
m_sent(false)
|
||||
{
|
||||
assert(!callsign.empty());
|
||||
assert(!password.empty());
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
assert(writer != NULL);
|
||||
|
||||
m_buffer = new unsigned char[300U];
|
||||
}
|
||||
|
@ -49,16 +46,6 @@ CGPS::~CGPS()
|
|||
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)
|
||||
{
|
||||
if (m_sent)
|
||||
|
@ -150,6 +137,8 @@ void CGPS::reset()
|
|||
|
||||
void CGPS::transmitGPS(const unsigned char* source)
|
||||
{
|
||||
assert(m_writer != NULL);
|
||||
|
||||
// We don't know who its from!
|
||||
if (::memcmp(source, " ", YSF_CALLSIGN_LENGTH) == 0)
|
||||
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);
|
||||
|
||||
m_writer.write(source, radio, m_buffer[4U], 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();
|
||||
}
|
||||
|
|
|
@ -25,23 +25,15 @@
|
|||
|
||||
class CGPS {
|
||||
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();
|
||||
|
||||
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 clock(unsigned int ms);
|
||||
|
||||
void reset();
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
CAPRSWriter m_writer;
|
||||
CAPRSWriter* m_writer;
|
||||
unsigned char* m_buffer;
|
||||
bool m_sent;
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ CYSFGateway::CYSFGateway(const std::string& configFile) :
|
|||
m_callsign(),
|
||||
m_suffix(),
|
||||
m_conf(configFile),
|
||||
m_writer(NULL),
|
||||
m_gps(NULL),
|
||||
m_reflectors(NULL),
|
||||
m_wiresX(NULL),
|
||||
|
@ -328,8 +329,8 @@ int CYSFGateway::run()
|
|||
m_ysfNetwork->clock(ms);
|
||||
if (m_fcsNetwork != NULL)
|
||||
m_fcsNetwork->clock(ms);
|
||||
if (m_gps != NULL)
|
||||
m_gps->clock(ms);
|
||||
if (m_writer != NULL)
|
||||
m_writer->clock(ms);
|
||||
m_wiresX->clock(ms);
|
||||
|
||||
m_inactivityTimer.clock(ms);
|
||||
|
@ -401,7 +402,8 @@ int CYSFGateway::run()
|
|||
rptNetwork.close();
|
||||
|
||||
if (m_gps != NULL) {
|
||||
m_gps->close();
|
||||
m_writer->close();
|
||||
delete m_writer;
|
||||
delete m_gps;
|
||||
}
|
||||
|
||||
|
@ -433,7 +435,7 @@ void CYSFGateway::createGPS()
|
|||
std::string suffix = m_conf.getAPRSSuffix();
|
||||
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 rxFrequency = m_conf.getRxFrequency();
|
||||
|
@ -441,13 +443,24 @@ void CYSFGateway::createGPS()
|
|||
float longitude = m_conf.getLongitude();
|
||||
int height = m_conf.getHeight();
|
||||
|
||||
m_gps->setInfo(txFrequency, rxFrequency, latitude, longitude, height, desc);
|
||||
m_writer->setInfo(txFrequency, rxFrequency, latitude, longitude, height, desc);
|
||||
|
||||
bool ret = m_gps->open();
|
||||
if (!ret) {
|
||||
delete m_gps;
|
||||
m_gps = NULL;
|
||||
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_writer->open();
|
||||
if (!ret) {
|
||||
delete m_writer;
|
||||
m_writer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_gps = new CGPS(m_writer);
|
||||
}
|
||||
|
||||
void CYSFGateway::createWiresX(CYSFNetwork* rptNetwork)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "YSFNetwork.h"
|
||||
#include "YSFReflectors.h"
|
||||
#include "FCSNetwork.h"
|
||||
#include "APRSWriter.h"
|
||||
#include "WiresX.h"
|
||||
#include "Timer.h"
|
||||
#include "Conf.h"
|
||||
|
@ -48,6 +49,7 @@ private:
|
|||
std::string m_callsign;
|
||||
std::string m_suffix;
|
||||
CConf m_conf;
|
||||
CAPRSWriter* m_writer;
|
||||
CGPS* m_gps;
|
||||
CYSFReflectors* m_reflectors;
|
||||
CWiresX* m_wiresX;
|
||||
|
|
|
@ -60,3 +60,8 @@ YSF2P25Port=42015
|
|||
Enable=1
|
||||
Rooms=./FCSRooms.txt
|
||||
Port=42001
|
||||
|
||||
[Mobile GPS]
|
||||
Enable=0
|
||||
Address=127.0.0.1
|
||||
Port=7834
|
||||
|
|
Loading…
Reference in a new issue