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_timer(1000U, 10U),
m_first(true),
m_collector(NULL)
m_collector(NULL),
m_linkStatus()
{
boost::trim(m_callsign);
@ -89,6 +90,11 @@ CAPRSCollector* CAPRSEntry::getCollector() const
return m_collector;
}
CAPRSEntryStatus& CAPRSEntry::getStatus()
{
return m_linkStatus;
}
void CAPRSEntry::reset()
{
m_first = true;
@ -98,6 +104,7 @@ void CAPRSEntry::reset()
void CAPRSEntry::clock(unsigned int ms)
{
m_linkStatus.clock(ms);
m_timer.clock(ms);
}

@ -22,7 +22,9 @@
#include <string>
#include "APRSCollector.h"
#include "APRSEntryStatus.h"
#include "Timer.h"
#include "Defs.h"
class CAPRSEntry {
public:
@ -38,6 +40,7 @@ public:
double getLongitude() const;
double getAGL() const;
CAPRSCollector* getCollector() const;
CAPRSEntryStatus& getStatus();
// Transmission timer
void reset();
@ -56,4 +59,5 @@ private:
CTimer m_timer;
bool m_first;
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);
}
setTimeout(20U * 60);//20 minutes, plenty enough for fixed
setTimeout(20U * 60U);//20 minutes, plenty enough for fixed
return true;
}

@ -34,7 +34,8 @@ m_thread(NULL),
m_gateway(),
m_address(),
m_port(0U),
m_array()
m_array(),
m_idFrameProvider(nullptr)
{
assert(!hostname.empty());
assert(port > 0U);
@ -157,28 +158,70 @@ void CAPRSWriter::writeData(const std::string& callsign, const CAMBEData& data)
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)
{
m_thread->clock(ms);
if(m_idFrameProvider != nullptr) {
m_idFrameProvider->clock(ms);
if(m_idFrameProvider->wantsToSend()) {
sendIdFrames();
}
}
if(m_idFrameProvider->wantsToSend() && 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());
}
}
}
for (auto it : m_array) {
if(it.second != NULL) {
it.second->clock(ms);
if(it.second->getStatus().isOutOfDate())
sendStatusFrame(it.second);
}
}
}
for (auto it = m_array.begin(); it != m_array.end(); ++it) {
if(it->second != NULL)
it->second->clock(ms);
void CAPRSWriter::sendStatusFrame(CAPRSEntry * entry)
{
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 writeStatus(const std::string& callsign, const std::string status);
bool isConnected() const;
void clock(unsigned int ms);
@ -65,7 +67,8 @@ private:
std::unordered_map<std::string,CAPRSEntry *> m_array;
CAPRSIdFrameProvider * m_idFrameProvider;
void sendIdFramesMobile();
void sendIdFrames();
void sendStatusFrame(CAPRSEntry * entrry);
};
#endif

@ -9,7 +9,7 @@
- [3.3. Get latest development version version](#33-get-latest-development-version-version)
- [3.4. Prerequisites and dependencies](#34-prerequisites-and-dependencies)
- [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.7. Configuring](#37-configuring)
- [4. Contributing](#4-contributing)
@ -19,18 +19,19 @@
- [5.2. Version 0.3](#52-version-03)
- [5.3. Version 0.2](#53-version-02)
- [5.4. Version 0.1](#54-version-01)
- [6. Future](#6-future)
# 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.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.
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
- 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)
@ -41,10 +42,10 @@ All the features found in ircddbGateway are supposed to be working. I have mixed
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.
- 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.
- DRats : No opinion on this one, I am not using it.
- CallSign Server : this is a legacy from the dead project xreflector.net, I will most probably drop 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 for good.
# 3. Building and installing
## 3.1. Initial setup
@ -80,7 +81,7 @@ Regular building
```
make
```
#### Build With GPSD Support
#### 3.5.0.1. Build With GPSD Support
```
make USE_GPS=1
```
@ -104,10 +105,13 @@ sudo systemctl stop dstargateway.service
```
# 4. Contributing
## 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.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))
- [Improvement] Bring back GPSD support (https://github.com/F4FXL/DStarGateway/issues/6)
- [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))
- Code sanitization
## 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;
break;
#endif
case G2_ECHO:
m_echo->end();
break;
@ -2564,6 +2563,9 @@ void CRepeaterHandler::writeLinkingTo(const std::string &callsign)
m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text);
triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS
m_ccsHandler->setReflector();
#endif
@ -2616,6 +2618,9 @@ void CRepeaterHandler::writeLinkedTo(const std::string &callsign)
m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text);
triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS
m_ccsHandler->setReflector(callsign);
#endif
@ -2668,6 +2673,9 @@ void CRepeaterHandler::writeNotLinked()
m_infoAudio->setStatus(m_linkStatus, m_linkRepeater, text);
triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS
m_ccsHandler->setReflector();
#endif
@ -2736,6 +2744,9 @@ void CRepeaterHandler::writeIsBusy(const std::string& callsign)
m_infoAudio->setTempStatus(m_linkStatus, m_linkRepeater, tempText);
triggerInfo();
if(m_aprsWriter != nullptr)
m_aprsWriter->writeStatus(m_rptCallsign, text);
#ifdef USE_CCS
m_ccsHandler->setReflector();
#endif

Loading…
Cancel
Save

Powered by TurnKey Linux.