mirror of
https://github.com/g4klx/DMRGateway.git
synced 2026-02-07 07:54:22 +01:00
commit
b6ab94109d
|
|
@ -43,6 +43,12 @@ CAPRSHelper::~CAPRSHelper()
|
|||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
void CAPRSHelper::setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height)
|
||||
{
|
||||
m_writer.setInfo(rxFrequency, rxFrequency, latitude, longitude, height);
|
||||
}
|
||||
|
||||
|
||||
bool CAPRSHelper::open()
|
||||
{
|
||||
return m_writer.open();
|
||||
|
|
@ -70,7 +76,12 @@ void CAPRSHelper::send(std::string callsign, float latitude, float longitude, in
|
|||
//::sprintf(m_buffer[4U], 0x28U);
|
||||
m_writer.write(source, type, 0x28U, latitude, longitude, altitude);
|
||||
}
|
||||
|
||||
|
||||
void CAPRSHelper::clock(unsigned int ms)
|
||||
{
|
||||
m_writer.clock(ms);
|
||||
}
|
||||
|
||||
void CAPRSHelper::close()
|
||||
{
|
||||
m_writer.close();
|
||||
|
|
|
|||
|
|
@ -28,10 +28,16 @@ public:
|
|||
CAPRSHelper(const std::string& callsign, const std::string& suffix, const std::string& password, const std::string& address, unsigned int port);
|
||||
~CAPRSHelper();
|
||||
|
||||
void setInfo(unsigned int txFrequency, unsigned int rxFrequency, float latitude, float longitude, int height);
|
||||
|
||||
bool open();
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
void send(std::string callsign, float latitude, float longitude, int altitude);
|
||||
|
||||
void reset();
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include "APRSWriter.h"
|
||||
|
||||
#include "DMRDefines.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
|
@ -41,7 +43,7 @@ m_height(0)
|
|||
|
||||
if (!suffix.empty()) {
|
||||
m_callsign.append("-");
|
||||
m_callsign.append(suffix.substr(0U, 2U));
|
||||
m_callsign.append(suffix.substr(0U, 1U));
|
||||
}
|
||||
|
||||
m_thread = new CAPRSWriterThread(m_callsign, password, address, port);
|
||||
|
|
@ -62,6 +64,7 @@ void CAPRSWriter::setInfo(unsigned int txFrequency, unsigned int rxFrequency, fl
|
|||
|
||||
bool CAPRSWriter::open()
|
||||
{
|
||||
m_idTimer.start();
|
||||
return m_thread->start();
|
||||
}
|
||||
|
||||
|
|
@ -71,8 +74,8 @@ void CAPRSWriter::write(const unsigned char* source, const char* type, unsigned
|
|||
assert(type != NULL);
|
||||
|
||||
char callsign[11U];
|
||||
::memcpy(callsign, source, 10U);
|
||||
callsign[10U] = 0x00U;
|
||||
::memcpy(callsign, source, DMR_CALLSIGN_LENGTH);
|
||||
callsign[DMR_CALLSIGN_LENGTH] = 0x00U;
|
||||
|
||||
size_t n = ::strspn(callsign, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
|
||||
callsign[n] = 0x00U;
|
||||
|
|
@ -147,8 +150,8 @@ void CAPRSWriter::sendIdFrames()
|
|||
char desc[100U];
|
||||
if (m_txFrequency != 0U) {
|
||||
float offset = float(int(m_rxFrequency) - int(m_txFrequency)) / 1000000.0F;
|
||||
::sprintf(desc, "MMDVM Voice %.5lfMHz %c%.4lfMHz",
|
||||
float(m_txFrequency) / 1000000.0F,
|
||||
::sprintf(desc, "MMDVM Voice %.5LfMHz %c%.4lfMHz",
|
||||
(long double)(m_txFrequency) / 1000000.0L,
|
||||
offset < 0.0F ? '-' : '+',
|
||||
::fabs(offset));
|
||||
} else {
|
||||
|
|
@ -177,10 +180,11 @@ void CAPRSWriter::sendIdFrames()
|
|||
longitude = (tempLong - longitude) * 60.0 + longitude * 100.0;
|
||||
|
||||
char lat[20U];
|
||||
::sprintf(lat, "%04.2lf", latitude);
|
||||
::sprintf(lat, "%07.2lf", latitude);
|
||||
|
||||
char lon[20U];
|
||||
::sprintf(lon, "%05.2lf", longitude);
|
||||
|
||||
::sprintf(lon, "%08.2lf", longitude);
|
||||
|
||||
std::string server = m_callsign;
|
||||
size_t pos = server.find_first_of('-');
|
||||
|
|
@ -197,6 +201,5 @@ void CAPRSWriter::sendIdFrames()
|
|||
float(m_height) * 3.28F, band, desc);
|
||||
|
||||
m_thread->write(output);
|
||||
|
||||
m_idTimer.start();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ const unsigned int DMR_EMBEDDED_SIGNALLING_LENGTH_BYTES = 4U;
|
|||
const unsigned int DMR_AMBE_LENGTH_BITS = 108U * 2U;
|
||||
const unsigned int DMR_AMBE_LENGTH_BYTES = 27U;
|
||||
|
||||
const unsigned int DMR_CALLSIGN_LENGTH = 10U;
|
||||
|
||||
const unsigned char BS_SOURCED_AUDIO_SYNC[] = {0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U};
|
||||
const unsigned char BS_SOURCED_DATA_SYNC[] = {0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U};
|
||||
|
||||
|
|
|
|||
|
|
@ -270,7 +270,6 @@ int CDMRGateway::run()
|
|||
LogMessage("DMRGateway-%s is starting", VERSION);
|
||||
LogMessage("Built %s %s (GitID #%.7s)", __TIME__, __DATE__, gitversion);
|
||||
|
||||
CDMRGateway::createAPRSHelper();
|
||||
|
||||
// For DMR we try to map IDs to callsigns
|
||||
std::string lookupFile = m_conf.getDMRIdLookupFile();
|
||||
|
|
@ -310,6 +309,8 @@ int CDMRGateway::run()
|
|||
|
||||
LogMessage("MMDVM has connected");
|
||||
|
||||
CDMRGateway::createAPRSHelper();
|
||||
|
||||
if (m_conf.getDMRNetwork1Enabled()) {
|
||||
ret = createDMRNetwork1();
|
||||
if (!ret)
|
||||
|
|
@ -427,7 +428,12 @@ int CDMRGateway::run()
|
|||
|
||||
bool ret = m_repeater->read(data);
|
||||
if (ret) {
|
||||
extractGPSData(data);
|
||||
// Check if NMEA Data coming
|
||||
checkForGPSData(data);
|
||||
|
||||
// Do we have GPS data?
|
||||
if (isGPSData(data))
|
||||
extractGPSData(data);
|
||||
|
||||
unsigned int slotNo = data.getSlotNo();
|
||||
unsigned int srcId = data.getSrcId();
|
||||
|
|
@ -712,6 +718,9 @@ int CDMRGateway::run()
|
|||
if (voice2 != NULL)
|
||||
voice2->clock(ms);
|
||||
|
||||
if (m_aprsHelper != NULL)
|
||||
m_aprsHelper->clock(ms);
|
||||
|
||||
for (unsigned int i = 1U; i < 3U; i++) {
|
||||
timer[i]->clock(ms);
|
||||
if (timer[i]->isRunning() && timer[i]->hasExpired()) {
|
||||
|
|
@ -1037,7 +1046,6 @@ bool CDMRGateway::createXLXNetwork1()
|
|||
|
||||
unsigned char config[400U];
|
||||
unsigned int len = m_repeater->getConfig(config);
|
||||
|
||||
m_xlxNetwork1->setConfig(config, len);
|
||||
|
||||
bool ret = m_xlxNetwork1->open();
|
||||
|
|
@ -1182,19 +1190,96 @@ void CDMRGateway::createAPRSHelper()
|
|||
if (!m_conf.getAPRSEnabled())
|
||||
return;
|
||||
|
||||
unsigned char config[400U];
|
||||
unsigned int len = m_repeater->getConfig(config);
|
||||
|
||||
if (len == 0U)
|
||||
return;
|
||||
|
||||
std::string hostname = m_conf.getAPRSServer();
|
||||
unsigned int port = m_conf.getAPRSPort();
|
||||
std::string password = m_conf.getAPRSPassword();
|
||||
|
||||
m_aprsHelper = new CAPRSHelper(m_callsign, m_suffix, password, hostname, port);
|
||||
|
||||
|
||||
char myRxFreq[10];
|
||||
snprintf(myRxFreq, 10, "%s", config + 8);
|
||||
unsigned int rxFrequency = atoi(myRxFreq);
|
||||
|
||||
char myTxFreq[10];
|
||||
snprintf(myTxFreq, 10, "%s", config + 17);
|
||||
unsigned int txFrequency = atoi(myTxFreq);
|
||||
|
||||
char myLat[9];
|
||||
snprintf(myLat, 9, "%s", config + 30);
|
||||
float latitude = atof(myLat);
|
||||
|
||||
char myLon[10];
|
||||
snprintf(myLon, 10, "%s", config + 38);
|
||||
float longitude = atof(myLon);
|
||||
|
||||
char myHeight[4];
|
||||
snprintf(myHeight, 4, "%s", config + 47 );
|
||||
int height = atoi(myHeight);
|
||||
|
||||
bool ret = m_aprsHelper->open();
|
||||
if (!ret) {
|
||||
delete m_aprsHelper;
|
||||
m_aprsHelper = NULL;
|
||||
}
|
||||
|
||||
m_aprsHelper->setInfo(txFrequency, rxFrequency, latitude, longitude, height);
|
||||
}
|
||||
|
||||
void CDMRGateway::checkForGPSData(const CDMRData& data)
|
||||
{
|
||||
unsigned int slotNo = data.getSlotNo();
|
||||
unsigned char type = data.getDataType();
|
||||
|
||||
if (type == DT_DATA_HEADER) {
|
||||
CBPTC19696 bptc;
|
||||
unsigned char buffer[DMR_FRAME_LENGTH_BYTES];
|
||||
|
||||
data.getData(buffer);
|
||||
|
||||
unsigned char payload[12U];
|
||||
bptc.decode(buffer, payload);
|
||||
if ( ((payload[1U] & 0x05U) == 0x05U) && ((payload[8U] & 0x03U) == 0x00U) )
|
||||
{
|
||||
LogDebug("UDT/NMEA Frame, Slot %d, 1 Appended data block outstanding", slotNo);
|
||||
// Store Source and destination ID's per slot
|
||||
if (slotNo == 1)
|
||||
{
|
||||
m_lastSlot1HadNMEA = true;
|
||||
LogDebug("Recording that Slot1 has NMEA Data outstanding");
|
||||
}
|
||||
if (slotNo == 2){
|
||||
m_lastSlot2HadNMEA = true;
|
||||
LogDebug("Recording that Slot2 has NMEA Data outstanding");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CDMRGateway::isGPSData(const CDMRData& data)
|
||||
{
|
||||
unsigned char type = data.getDataType();
|
||||
|
||||
if (type == DT_RATE_12_DATA) {
|
||||
if (m_lastSlot1HadNMEA == true){
|
||||
m_lastSlot1HadNMEA = false;
|
||||
return true;
|
||||
} else if (m_lastSlot2HadNMEA == true)
|
||||
{
|
||||
m_lastSlot2HadNMEA = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CDMRGateway::extractGPSData(const CDMRData& data)
|
||||
{
|
||||
unsigned int slotNo = data.getSlotNo();
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ private:
|
|||
std::vector<IRewrite*> m_dmr2NetRewrites;
|
||||
std::vector<IRewrite*> m_dmr2RFRewrites;
|
||||
CDMRLookup* m_lookup;
|
||||
bool m_lastSlot1HadNMEA;
|
||||
bool m_lastSlot2HadNMEA;
|
||||
|
||||
bool createMMDVM();
|
||||
bool createDMRNetwork1();
|
||||
|
|
@ -79,7 +81,10 @@ private:
|
|||
bool createXLXNetwork1();
|
||||
bool createXLXNetwork2();
|
||||
void writeXLXLink(unsigned int srcId, unsigned int dstId, CDMRNetwork* network);
|
||||
void checkForGPSData(const CDMRData& data);
|
||||
void extractGPSData(const CDMRData& data);
|
||||
bool isGPSData(const CDMRData& data);
|
||||
|
||||
void createAPRSHelper();
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue