Merge branch 'feature/APRSStatus#8' into develop fixes #8

pull/11/head
Geoffrey Merck 4 years ago
commit 50b6edd002

@ -32,7 +32,8 @@ m_longitude(longitude),
m_agl(agl), m_agl(agl),
m_timer(1000U, 10U), m_timer(1000U, 10U),
m_first(true), m_first(true),
m_collector(NULL) m_collector(NULL),
m_linkStatus()
{ {
boost::trim(m_callsign); boost::trim(m_callsign);
@ -89,6 +90,11 @@ CAPRSCollector* CAPRSEntry::getCollector() const
return m_collector; return m_collector;
} }
CAPRSEntryStatus& CAPRSEntry::getStatus()
{
return m_linkStatus;
}
void CAPRSEntry::reset() void CAPRSEntry::reset()
{ {
m_first = true; m_first = true;
@ -98,6 +104,7 @@ void CAPRSEntry::reset()
void CAPRSEntry::clock(unsigned int ms) void CAPRSEntry::clock(unsigned int ms)
{ {
m_linkStatus.clock(ms);
m_timer.clock(ms); m_timer.clock(ms);
} }

@ -22,7 +22,9 @@
#include <string> #include <string>
#include "APRSCollector.h" #include "APRSCollector.h"
#include "APRSEntryStatus.h"
#include "Timer.h" #include "Timer.h"
#include "Defs.h"
class CAPRSEntry { class CAPRSEntry {
public: public:
@ -38,6 +40,7 @@ public:
double getLongitude() const; double getLongitude() const;
double getAGL() const; double getAGL() const;
CAPRSCollector* getCollector() const; CAPRSCollector* getCollector() const;
CAPRSEntryStatus& getStatus();
// Transmission timer // Transmission timer
void reset(); void reset();
@ -56,4 +59,5 @@ private:
CTimer m_timer; CTimer m_timer;
bool m_first; bool m_first;
CAPRSCollector* m_collector; CAPRSCollector* m_collector;
CAPRSEntryStatus m_linkStatus;
}; };

@ -0,0 +1,54 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* 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 "APRSEntryStatus.h"
CAPRSEntryStatus::CAPRSEntryStatus() :
m_status(),
m_statusChanged(false),
m_timer(1000U)
{
m_timer.setTimeout(20U * 60U); //statuses go out every 20 minutes or every change
}
bool CAPRSEntryStatus::isOutOfDate()
{
bool ouOfDate = m_statusChanged || m_timer.hasExpired();
m_statusChanged = false;
return ouOfDate;
}
std::string CAPRSEntryStatus::getStatus() const
{
return m_status;
}
void CAPRSEntryStatus::setStatus(const std::string& linkstatus)
{
bool changed = m_status != linkstatus;
if(changed) {
m_status = linkstatus;
}
m_statusChanged = changed;
}
void CAPRSEntryStatus::clock(unsigned int ms)
{
m_timer.clock(ms);
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* 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.
*/
#pragma once
#include <string>
#include "Timer.h"
class CAPRSEntryStatus
{
public:
CAPRSEntryStatus() ;
std::string getStatus() const;
bool isOutOfDate();
void setStatus(const std::string& destination);
void clock(unsigned int ms);
private:
std::string m_status;
bool m_statusChanged;
CTimer m_timer;
};

@ -127,7 +127,7 @@ bool CAPRSFixedIdFrameProvider::buildAPRSFramesInt(const std::string& gateway, c
frames.push_back(output); frames.push_back(output);
} }
setTimeout(20U * 60);//20 minutes, plenty enough for fixed setTimeout(20U * 60U);//20 minutes, plenty enough for fixed
return true; return true;
} }

@ -34,7 +34,8 @@ m_thread(NULL),
m_gateway(), m_gateway(),
m_address(), m_address(),
m_port(0U), m_port(0U),
m_array() m_array(),
m_idFrameProvider(nullptr)
{ {
assert(!hostname.empty()); assert(!hostname.empty());
assert(port > 0U); assert(port > 0U);
@ -157,28 +158,70 @@ void CAPRSWriter::writeData(const std::string& callsign, const CAMBEData& data)
collector->reset(); collector->reset();
} }
void CAPRSWriter::writeStatus(const std::string& callsign, const std::string status)
{
CAPRSEntry* entry = m_array[callsign];
if (entry == NULL) {
CLog::logError("Cannot find the callsign \"%s\" in the APRS array", callsign.c_str());
return;
}
entry->getStatus().setStatus(status);
}
void CAPRSWriter::clock(unsigned int ms) void CAPRSWriter::clock(unsigned int ms)
{ {
m_thread->clock(ms); m_thread->clock(ms);
if(m_idFrameProvider != nullptr) { if(m_idFrameProvider != nullptr) {
m_idFrameProvider->clock(ms); m_idFrameProvider->clock(ms);
if(m_idFrameProvider->wantsToSend()) {
sendIdFrames();
}
}
if(m_idFrameProvider->wantsToSend() && m_thread->isConnected()) { for (auto it : m_array) {
for(auto entry : m_array) { if(it.second != NULL) {
std::vector<std::string> frames; it.second->clock(ms);
if(m_idFrameProvider->buildAPRSFrames(m_gateway, entry.second, frames)) { if(it.second->getStatus().isOutOfDate())
for(auto frame : frames) { sendStatusFrame(it.second);
m_thread->write(frame.c_str());
}
}
}
} }
} }
}
for (auto it = m_array.begin(); it != m_array.end(); ++it) { void CAPRSWriter::sendStatusFrame(CAPRSEntry * entry)
if(it->second != NULL) {
it->second->clock(ms); assert(entry != nullptr);
if(!m_thread->isConnected())
return;
auto linkStatus = entry->getStatus();
std::string body = boost::trim_copy(linkStatus.getStatus());
if(body[0] != '>')
body = '>' + body;
std::string output = CStringUtils::string_format("%s-%s>APD5T3,TCPIP*,qAC,%s-%sS:%s\r\n",
entry->getCallsign().c_str(), entry->getBand().c_str(), entry->getCallsign().c_str(), entry->getBand().c_str(),
body.c_str());
m_thread->write(output.c_str());
}
void CAPRSWriter::sendIdFrames()
{
if(m_thread->isConnected())
{
for(auto entry : m_array) {
std::vector<std::string> frames;
if(m_idFrameProvider->buildAPRSFrames(m_gateway, entry.second, frames)) {
for(auto frame : frames) {
m_thread->write(frame.c_str());
}
}
}
} }
} }

@ -51,6 +51,8 @@ public:
void writeData(const std::string& callsign, const CAMBEData& data); void writeData(const std::string& callsign, const CAMBEData& data);
void writeStatus(const std::string& callsign, const std::string status);
bool isConnected() const; bool isConnected() const;
void clock(unsigned int ms); void clock(unsigned int ms);
@ -65,7 +67,8 @@ private:
std::unordered_map<std::string,CAPRSEntry *> m_array; std::unordered_map<std::string,CAPRSEntry *> m_array;
CAPRSIdFrameProvider * m_idFrameProvider; CAPRSIdFrameProvider * m_idFrameProvider;
void sendIdFramesMobile(); void sendIdFrames();
void sendStatusFrame(CAPRSEntry * entrry);
}; };
#endif #endif

@ -9,7 +9,7 @@
- [3.3. Get latest development version version](#33-get-latest-development-version-version) - [3.3. Get latest development version version](#33-get-latest-development-version-version)
- [3.4. Prerequisites and dependencies](#34-prerequisites-and-dependencies) - [3.4. Prerequisites and dependencies](#34-prerequisites-and-dependencies)
- [3.5. Building](#35-building) - [3.5. Building](#35-building)
- [Build With GPSD Support](#build-with-gpsd-support) - [3.5.0.1. Build With GPSD Support](#3501-build-with-gpsd-support)
- [3.6. Installing](#36-installing) - [3.6. Installing](#36-installing)
- [3.7. Configuring](#37-configuring) - [3.7. Configuring](#37-configuring)
- [4. Contributing](#4-contributing) - [4. Contributing](#4-contributing)
@ -19,18 +19,19 @@
- [5.2. Version 0.3](#52-version-03) - [5.2. Version 0.3](#52-version-03)
- [5.3. Version 0.2](#53-version-02) - [5.3. Version 0.2](#53-version-02)
- [5.4. Version 0.1](#54-version-01) - [5.4. Version 0.1](#54-version-01)
- [6. Future](#6-future)
# 1. Introduction # 1. Introduction
This is a port of G4KLX Jonathan Naylor's [ircddbGateway](https://github.com/g4klx/ircDDBGateway). It is wxWidgets free and has minimal dependencies to boost (header libs only) and libcurl This is a port of G4KLX Jonathan Naylor's [ircddbGateway](https://github.com/g4klx/ircDDBGateway). It is wxWidgets free and has minimal dependencies to boost (header libs only) and libcurl. I plan to ad some features in the future
# 2. Current State # 2. Current State
## 2.1. Code sanity ## 2.1. Code sanity
The current code is working, yet ugly IMHO as it is a mix of C and C++ of various ages. The current code is working, yet ugly IMHO as it is a mix of C and C++ of various ages. I realised that G4KLx started programming this over a decade ago, when C++11 was not yet a thing !
The code has also been amended to no longer rely on compiler defines for paths like log or data. These can be set in configuration file. The code has also been amended to no longer rely on compiler defines for paths like log or data. These can be set in configuration file.
Quite a few classes are more or less copy/paste from each other some sanitization by using base classes or template classes would greatly improve code maintainibility. Quite a few classes are more or less copy/paste from each other some sanitization by using base classes or template classes would greatly improve code maintainibility. Maybe one day ;)
## 2.2. Code Credit ## 2.2. Code Credit
- Jonathan Naylor G4KLX (The original author of [ircddbGateway](https://github.com/g4klx/ircDDBGateway)) - Jonathan Naylor G4KLX (The original author of [ircddbGateway](https://github.com/g4klx/ircDDBGateway))
- Thomas A. Early N7TAE (Code taken from his [smart-group](https://github.com/n7tae/smart-group-server) software) - Thomas A. Early N7TAE (Code taken from his [smart-group](https://github.com/n7tae/smart-group-server) software)
@ -41,10 +42,10 @@ All the features found in ircddbGateway are supposed to be working. I have mixed
Features that where left out : Features that where left out :
- CCS: is still being used? I always considered this as trojan horse to push some DMR Agenda into DStar an more or les a burdain to use. Call sign routing is by far more flexible and superior. - CCS: is still being used? I always considered this as trojan horse to push some DMR Agenda into DStar an more or les a burdain to use. Call sign routing is by far more flexible and superior.
- Starnet: You might consider running [Smart Group Server XL](https://github.com/F4FXL/smart-group-server-xl) from a dedicated computer instead. - Starnet: You might consider running [Smart Group Server XL](https://github.com/F4FXL/smart-group-server-xl) from a dedicated computer instead.
- Announcement: same can be achieved using transmitd. - Announcement: same can be achieved using VoiceTransmit.
- APRSGateway capability: I would prefer to have some sort of TCP "APRS-IS proxy" program sitting between the program and the APRS server, thus keeping the ability to directly connect to APRS-IS or not, depending on the system owner wish. I run mostly DStar Only repeaters, having an additional program to maintain is unnecessary burden. - APRSGateway capability: I would prefer to have some sort of TCP "APRS-IS proxy" program sitting between the program and the APRS server, thus keeping the ability to directly connect to APRS-IS or not, depending on the system owner wish. I run mostly DStar Only repeaters, having an additional program to maintain is unnecessary burden.
- DRats : No opinion on this one, I am not using it. - DRats : Is on the to-do list see [#6](#6)
- CallSign Server : this is a legacy from the dead project xreflector.net, I will most probably drop it. - CallSign Server : this is a legacy from the dead project xreflector.net, I will most probably drop it for good.
# 3. Building and installing # 3. Building and installing
## 3.1. Initial setup ## 3.1. Initial setup
@ -80,7 +81,7 @@ Regular building
``` ```
make make
``` ```
#### Build With GPSD Support #### 3.5.0.1. Build With GPSD Support
``` ```
make USE_GPS=1 make USE_GPS=1
``` ```
@ -104,10 +105,13 @@ sudo systemctl stop dstargateway.service
``` ```
# 4. Contributing # 4. Contributing
## 4.1. Work Flow ## 4.1. Work Flow
I Use [Git flow](https://danielkummer.github.io/git-flow-cheatsheet/) as my workflow. PR are welcome and shall be done against the develop branch and follow the Git Flow branch naming rules. I Use [Git flow](https://danielkummer.github.io/git-flow-cheatsheet/) as my workflow. PR are welcome but pleasee observe following rules :
- You have tested your code thoroughly
- Compilation produces no warnings
- Code formating rules are observed (these are very lousy though)
# 5. Version History # 5. Version History
## 5.1. Version 0.4 ## 5.1. Version 0.4
- [Improvement] Add APRS status link feature ([#8](https://github.com/F4FXL/DStarGateway/issues/8))
- [Bugfix] Posotions received over radio were not sent to APRS-IS when GPDS connection failed. ([#7](https://github.com/F4FXL/DStarGateway/issues/7)) - [Bugfix] Posotions received over radio were not sent to APRS-IS when GPDS connection failed. ([#7](https://github.com/F4FXL/DStarGateway/issues/7))
- [Improvement] Bring back GPSD support (https://github.com/F4FXL/DStarGateway/issues/6) - [Improvement] Bring back GPSD support (https://github.com/F4FXL/DStarGateway/issues/6)
- [Improvement] Log enhancements ([#4])(https://github.com/F4FXL/DStarGateway/issues/4) - [Improvement] Log enhancements ([#4])(https://github.com/F4FXL/DStarGateway/issues/4)
@ -117,4 +121,16 @@ I Use [Git flow](https://danielkummer.github.io/git-flow-cheatsheet/) as my work
- [Bugfix] ircDDBFreeze when repeater not found ([#1](https://github.com/F4FXL/DStarGateway/issues/1)) - [Bugfix] ircDDBFreeze when repeater not found ([#1](https://github.com/F4FXL/DStarGateway/issues/1))
- Code sanitization - Code sanitization
## 5.4. Version 0.1 ## 5.4. Version 0.1
First working version First working version
# 6. Future
I started this during my 2021 seasons holiday. It took me almost 8 days to get to a workable version. Here are a couple of stuff I'd like to do :
- &#9746; Better NatTraversal
- No banging on every gateway: use ircDDB (or something else) as mitigation server to notify peer
- Support for all protocols (G2, DExtra, DCS, REF)
- A [branch](https://github.com/F4FXL/DStarGateway/tree/feature/NatTraversal) already exists for this
- &#9745; Send the connection status as to APRS as a status frame
- &#9746; Reinstantiate DRATS
- &#9746; Migrate all the "accessories" (VoiceTransmit, RemoteControl ...)
- &#9746; Automatic refresh of host files
- &#9746; Reduce ircDDB dependency, build something more P2P, maybe based on [Distributed Hashtable](https://github.com/DavidKeller/kademlia) ?
- Everything that might come handy to make dstar the most powerful system ever :)

@ -1594,7 +1594,6 @@ void CRepeaterHandler::clockInt(unsigned int ms)
m_starNet = NULL; m_starNet = NULL;
break; break;
#endif #endif
case G2_ECHO: case G2_ECHO:
m_echo->end(); m_echo->end();
break; break;
@ -2564,6 +2563,9 @@ void CRepeaterHandler::writeLinkingTo(const std::string &callsign)
m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text); m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text);
triggerInfo(); triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS #ifdef USE_CCS
m_ccsHandler->setReflector(); m_ccsHandler->setReflector();
#endif #endif
@ -2616,6 +2618,9 @@ void CRepeaterHandler::writeLinkedTo(const std::string &callsign)
m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text); m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text);
triggerInfo(); triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS #ifdef USE_CCS
m_ccsHandler->setReflector(callsign); m_ccsHandler->setReflector(callsign);
#endif #endif
@ -2668,6 +2673,9 @@ void CRepeaterHandler::writeNotLinked()
m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text); m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text);
triggerInfo(); triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS #ifdef USE_CCS
m_ccsHandler->setReflector(); m_ccsHandler->setReflector();
#endif #endif
@ -2736,6 +2744,9 @@ void CRepeaterHandler::writeIsBusy(const std::string& callsign)
m_infoAudio->setTempStatus(m_linkStatus, m_linkRepeater, tempText); m_infoAudio->setTempStatus(m_linkStatus, m_linkRepeater, tempText);
triggerInfo(); triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS #ifdef USE_CCS
m_ccsHandler->setReflector(); m_ccsHandler->setReflector();
#endif #endif

Loading…
Cancel
Save

Powered by TurnKey Linux.