From aa0ba6ec46e4c1fbdd36c9a10be0e63fd498d53e Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 3 Jun 2020 12:41:00 +0100 Subject: [PATCH] Add support for GPSD. --- YSFGateway/APRSWriter.cpp | 108 ++++++++++++++++++------------------ YSFGateway/APRSWriter.h | 37 ++++++------ YSFGateway/Conf.cpp | 32 +++++------ YSFGateway/Conf.h | 14 ++--- YSFGateway/Makefile | 6 +- YSFGateway/Makefile.Solaris | 20 ------- YSFGateway/Version.h | 2 +- YSFGateway/YSFGateway.cpp | 8 +-- YSFGateway/YSFGateway.ini | 4 +- 9 files changed, 108 insertions(+), 123 deletions(-) delete mode 100644 YSFGateway/Makefile.Solaris diff --git a/YSFGateway/APRSWriter.cpp b/YSFGateway/APRSWriter.cpp index 57fe38f..c53f51f 100644 --- a/YSFGateway/APRSWriter.cpp +++ b/YSFGateway/APRSWriter.cpp @@ -17,8 +17,8 @@ */ #include "APRSWriter.h" - #include "YSFDefines.h" +#include "Log.h" #include #include @@ -37,10 +37,13 @@ m_desc(), m_suffix(suffix), m_aprsAddress(), m_aprsPort(port), -m_aprsSocket(), -m_mobileGPSAddress(), -m_mobileGPSPort(0U), -m_mobileSocket(NULL) +m_aprsSocket() +#if !defined(_WIN32) && !defined(_WIN64) +,m_gpsdEnabled(false), +m_gpsdAddress(), +m_gpsdPort(0U), +m_gpsdData() +#endif { assert(!callsign.empty()); assert(!address.empty()); @@ -72,33 +75,38 @@ void CAPRSWriter::setStaticLocation(float latitude, float longitude, int height) m_height = height; } -void CAPRSWriter::setMobileLocation(const std::string& address, unsigned int port) +void CAPRSWriter::setGPSDLocation(const std::string& address, const std::string& port) { +#if !defined(_WIN32) && !defined(_WIN64) assert(!address.empty()); - assert(port > 0U); + assert(!port.empty()); - m_mobileGPSAddress = CUDPSocket::lookup(address); - m_mobileGPSPort = port; - - m_mobileSocket = new CUDPSocket; + m_gpsdEnabled = true; + m_gpsdAddress = address; + m_gpsdPort = port; +#endif } bool CAPRSWriter::open() { - if (m_mobileSocket != NULL) { - bool ret = m_mobileSocket->open(); - if (!ret) { - delete m_mobileSocket; - m_mobileSocket = NULL; +#if !defined(_WIN32) && !defined(_WIN64) + if (m_gpsdEnabled) { + int ret = ::gps_open(m_gpsdAddress.c_str(), m_gpsdPort.c_str(), &m_gpsdData); + if (ret != 0) { + LogError("Error when opening access to gpsd - %d - %s", errno, ::gps_errstr(errno)); return false; } + ::gps_stream(&m_gpsdData, WATCH_ENABLE | WATCH_JSON, NULL); + // Poll the GPS every minute m_idTimer.setTimeout(60U); } else { m_idTimer.setTimeout(20U * 60U); } - +#else + m_idTimer.setTimeout(20U * 60U); +#endif m_idTimer.start(); return m_aprsSocket.open(); @@ -169,36 +177,34 @@ void CAPRSWriter::clock(unsigned int ms) { m_idTimer.clock(ms); - if (m_mobileSocket != NULL) { +#if !defined(_WIN32) && !defined(_WIN64) + if (m_gpsdEnabled) { if (m_idTimer.hasExpired()) { - pollGPS(); + sendIdFrameMobile(); m_idTimer.start(); } - sendIdFrameMobile(); } else { +#endif if (m_idTimer.hasExpired()) { sendIdFrameFixed(); m_idTimer.start(); } +#if !defined(_WIN32) && !defined(_WIN64) } +#endif } void CAPRSWriter::close() { m_aprsSocket.close(); - if (m_mobileSocket != NULL) { - m_mobileSocket->close(); - delete m_mobileSocket; +#if !defined(_WIN32) && !defined(_WIN64) + if (m_gpsdEnabled) { + ::gps_stream(&m_gpsdData, WATCH_DISABLE, NULL); + ::gps_close(&m_gpsdData); } -} - -bool CAPRSWriter::pollGPS() -{ - assert(m_mobileSocket != NULL); - - return m_mobileSocket->write((unsigned char*)"YSFGateway", 10U, m_mobileGPSAddress, m_mobileGPSPort); +#endif } void CAPRSWriter::sendIdFrameFixed() @@ -264,29 +270,25 @@ void CAPRSWriter::sendIdFrameFixed() void CAPRSWriter::sendIdFrameMobile() { - // Grab GPS data if it's available - unsigned char buffer[200U]; - in_addr address; - unsigned int port; - int ret = m_mobileSocket->read(buffer, 200U, address, port); - if (ret <= 0) + if (!m_gpsdEnabled) return; - buffer[ret] = '\0'; + if (!::gps_waiting(&m_gpsdData, 0)) + return; - // Parse the GPS data - char* pLatitude = ::strtok((char*)buffer, ",\n"); // Latitude - char* pLongitude = ::strtok(NULL, ",\n"); // Longitude - char* pAltitude = ::strtok(NULL, ",\n"); // Altitude (m) - char* pVelocity = ::strtok(NULL, ",\n"); // Velocity (kms/h) - char* pBearing = ::strtok(NULL, "\n"); // Bearing + bool latlonSet = (m_gpsdData.set & LATLON_SET) == LATLON_SET; + bool altitudeSet = (m_gpsdData.set & ALTITUDE_SET) == ALTITUDE_SET; + bool velocitySet = (m_gpsdData.set & SPEED_SET) == SPEED_SET; + bool bearingSet = (m_gpsdData.set & TRACK_SET) == TRACK_SET; - if (pLatitude == NULL || pLongitude == NULL || pAltitude == NULL) + if (!latlonSet) return; - float rawLatitude = float(::atof(pLatitude)); - float rawLongitude = float(::atof(pLongitude)); - float rawAltitude = float(::atof(pAltitude)); + float rawLatitude = float(m_gpsdData.fix.latitude); + float rawLongitude = float(m_gpsdData.fix.longitude); + float rawAltitude = float(m_gpsdData.fix.altMSL); + float rawVelocity = float(m_gpsdData.fix.speed); + float rawBearing = float(m_gpsdData.fix.track); char desc[200U]; if (m_txFrequency != 0U) { @@ -339,14 +341,14 @@ void CAPRSWriter::sendIdFrameMobile() lat, (rawLatitude < 0.0F) ? 'S' : 'N', lon, (rawLongitude < 0.0F) ? 'W' : 'E'); - if (pBearing != NULL && pVelocity != NULL) { - float rawBearing = float(::atof(pBearing)); - float rawVelocity = float(::atof(pVelocity)); - + if (bearingSet && velocitySet) ::sprintf(output + ::strlen(output), "%03.0f/%03.0f", rawBearing, rawVelocity * 0.539957F); - } - ::sprintf(output + ::strlen(output), "/A=%06.0f%s %s\r\n", float(rawAltitude) * 3.28F, band, desc); + if (altitudeSet) + ::sprintf(output + ::strlen(output), "/A=%06.0f", float(rawAltitude) * 3.28F); + + ::sprintf(output + ::strlen(output), "%s %s\r\n", band, desc); m_aprsSocket.write((unsigned char*)output, (unsigned int)::strlen(output), m_aprsAddress, m_aprsPort); } + diff --git a/YSFGateway/APRSWriter.h b/YSFGateway/APRSWriter.h index 89d454f..9a0d17d 100644 --- a/YSFGateway/APRSWriter.h +++ b/YSFGateway/APRSWriter.h @@ -33,6 +33,7 @@ #include #include #include +#include #else #include #endif @@ -48,7 +49,7 @@ public: void setStaticLocation(float latitude, float longitude, int height); - void setMobileLocation(const std::string& address, unsigned int port); + void setGPSDLocation(const std::string& address, const std::string& port); void write(const unsigned char* source, const char* type, unsigned char radio, float latitude, float longitude); @@ -57,23 +58,25 @@ public: void close(); private: - 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; + 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; +#if !defined(_WIN32) && !defined(_WIN64) + bool m_gpsdEnabled; + std::string m_gpsdAddress; + std::string m_gpsdPort; + struct gps_data_t m_gpsdData; +#endif - bool pollGPS(); void sendIdFrameFixed(); void sendIdFrameMobile(); }; diff --git a/YSFGateway/Conf.cpp b/YSFGateway/Conf.cpp index 1660158..d87704d 100644 --- a/YSFGateway/Conf.cpp +++ b/YSFGateway/Conf.cpp @@ -35,7 +35,7 @@ enum SECTION { SECTION_NETWORK, SECTION_YSF_NETWORK, SECTION_FCS_NETWORK, - SECTION_MOBILE_GPS, + SECTION_GPSD, SECTION_REMOTE_COMMANDS }; @@ -87,9 +87,9 @@ m_ysfNetworkYSF2P25Port(0U), m_fcsNetworkEnabled(false), m_fcsNetworkFile(), m_fcsNetworkPort(0U), -m_mobileGPSEnabled(false), -m_mobileGPSAddress(), -m_mobileGPSPort(0U), +m_gpsdEnabled(false), +m_gpsdAddress(), +m_gpsdPort(), m_remoteCommandsEnabled(false), m_remoteCommandsPort(6073U) { @@ -129,8 +129,8 @@ 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 if (::strncmp(buffer, "[GPSD]", 6U) == 0) + section = SECTION_GPSD; else if (::strncmp(buffer, "[Remote Commands]", 17U) == 0) section = SECTION_REMOTE_COMMANDS; else @@ -249,13 +249,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) { + } else if (section == SECTION_GPSD) { if (::strcmp(key, "Enable") == 0) - m_mobileGPSEnabled = ::atoi(value) == 1; + m_gpsdEnabled = ::atoi(value) == 1; else if (::strcmp(key, "Address") == 0) - m_mobileGPSAddress = value; + m_gpsdAddress = value; else if (::strcmp(key, "Port") == 0) - m_mobileGPSPort = (unsigned int)::atoi(value); + m_gpsdPort = value; } else if (section == SECTION_REMOTE_COMMANDS) { if (::strcmp(key, "Enable") == 0) m_remoteCommandsEnabled = ::atoi(value) == 1; @@ -500,19 +500,19 @@ unsigned int CConf::getFCSNetworkPort() const return m_fcsNetworkPort; } -bool CConf::getMobileGPSEnabled() const +bool CConf::getGPSDEnabled() const { - return m_mobileGPSEnabled; + return m_gpsdEnabled; } -std::string CConf::getMobileGPSAddress() const +std::string CConf::getGPSDAddress() const { - return m_mobileGPSAddress; + return m_gpsdAddress; } -unsigned int CConf::getMobileGPSPort() const +std::string CConf::getGPSDPort() const { - return m_mobileGPSPort; + return m_gpsdPort; } bool CConf::getRemoteCommandsEnabled() const diff --git a/YSFGateway/Conf.h b/YSFGateway/Conf.h index 4bab37b..ea2a611 100644 --- a/YSFGateway/Conf.h +++ b/YSFGateway/Conf.h @@ -89,10 +89,10 @@ public: std::string getFCSNetworkFile() const; unsigned int getFCSNetworkPort() const; - // The Mobile GPS section - bool getMobileGPSEnabled() const; - std::string getMobileGPSAddress() const; - unsigned int getMobileGPSPort() const; + // The GPSD section + bool getGPSDEnabled() const; + std::string getGPSDAddress() const; + std::string getGPSDPort() const; // The Remote Commands section bool getRemoteCommandsEnabled() const; @@ -153,9 +153,9 @@ private: std::string m_fcsNetworkFile; unsigned int m_fcsNetworkPort; - bool m_mobileGPSEnabled; - std::string m_mobileGPSAddress; - unsigned int m_mobileGPSPort; + bool m_gpsdEnabled; + std::string m_gpsdAddress; + std::string m_gpsdPort; bool m_remoteCommandsEnabled; unsigned int m_remoteCommandsPort; diff --git a/YSFGateway/Makefile b/YSFGateway/Makefile index 816e6c7..8d37ea0 100644 --- a/YSFGateway/Makefile +++ b/YSFGateway/Makefile @@ -1,11 +1,11 @@ CC = gcc CXX = g++ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -LIBS = -lm -lpthread +LIBS = -lm -lpthread -lgps LDFLAGS = -g 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 + UDPSocket.o Utils.o WiresX.o YSFConvolution.o YSFFICH.o YSFGateway.o YSFNetwork.o YSFPayload.o YSFReflectors.o all: YSFGateway @@ -17,4 +17,4 @@ YSFGateway: $(OBJECTS) clean: $(RM) YSFGateway *.o *.d *.bak *~ - \ No newline at end of file + diff --git a/YSFGateway/Makefile.Solaris b/YSFGateway/Makefile.Solaris deleted file mode 100644 index dc644e3..0000000 --- a/YSFGateway/Makefile.Solaris +++ /dev/null @@ -1,20 +0,0 @@ -CC = gcc -CXX = g++ -CFLAGS = -g -O3 -Wall -std=c++0x -pthread -LIBS = -lm -lpthread -lsocket -LDFLAGS = -g - -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 - -YSFGateway: $(OBJECTS) - $(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o YSFGateway - -%.o: %.cpp - $(CXX) $(CFLAGS) -c -o $@ $< - -clean: - $(RM) YSFGateway *.o *.d *.bak *~ - \ No newline at end of file diff --git a/YSFGateway/Version.h b/YSFGateway/Version.h index 5dd3a24..5c5824f 100644 --- a/YSFGateway/Version.h +++ b/YSFGateway/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200601"; +const char* VERSION = "20200603"; #endif diff --git a/YSFGateway/YSFGateway.cpp b/YSFGateway/YSFGateway.cpp index afb7a1f..2847638 100644 --- a/YSFGateway/YSFGateway.cpp +++ b/YSFGateway/YSFGateway.cpp @@ -466,12 +466,12 @@ void CYSFGateway::createGPS() m_writer->setInfo(txFrequency, rxFrequency, desc); - bool enabled = m_conf.getMobileGPSEnabled(); + bool enabled = m_conf.getGPSDEnabled(); if (enabled) { - std::string address = m_conf.getMobileGPSAddress(); - unsigned int port = m_conf.getMobileGPSPort(); + std::string address = m_conf.getGPSDAddress(); + std::string port = m_conf.getGPSDPort(); - m_writer->setMobileLocation(address, port); + m_writer->setGPSDLocation(address, port); } else { float latitude = m_conf.getLatitude(); float longitude = m_conf.getLongitude(); diff --git a/YSFGateway/YSFGateway.ini b/YSFGateway/YSFGateway.ini index 515d882..21e6815 100644 --- a/YSFGateway/YSFGateway.ini +++ b/YSFGateway/YSFGateway.ini @@ -61,10 +61,10 @@ Enable=1 Rooms=./FCSRooms.txt Port=42001 -[Mobile GPS] +[GPSD] Enable=0 Address=127.0.0.1 -Port=7834 +Port=2947 [Remote Commands] Enable=0