From d14eed74089e72599cdb68358746f122823cb1a0 Mon Sep 17 00:00:00 2001 From: ernix66 Date: Sun, 12 Jan 2020 20:50:03 +0100 Subject: [PATCH 01/27] Update XLXHost.txt XLX311 and XLX320 new Server/IP-Address --- XLXHosts.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/XLXHosts.txt b/XLXHosts.txt index ed1db42..a8092d2 100644 --- a/XLXHosts.txt +++ b/XLXHosts.txt @@ -127,11 +127,12 @@ 302;144.217.241.23;4004 307;72.21.76.154;4004 310;52.11.207.121;4004 -311;46.41.0.214;4003 +311;91.204.44.37;4003 312;192.241.160.183;4004 313;34.213.108.164;4001 315;65.101.7.50;4004 317;44.48.8.15;4004 +320;91.204.44.27;4003 328;212.237.33.114;4004 329;114.181.139.32;4004 332;188.213.168.99;4004 From 00144321951bbeddd901129cec64705bb8f0befc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 14 Feb 2020 21:51:26 +0000 Subject: [PATCH 02/27] Update to VS2019. --- DMRGateway.vcxproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DMRGateway.vcxproj b/DMRGateway.vcxproj index 9108dcd..dac6f95 100644 --- a/DMRGateway.vcxproj +++ b/DMRGateway.vcxproj @@ -22,32 +22,32 @@ {862A3182-C71A-4B01-B58D-5F0725927A56} Win32Proj DMRGateway - 10.0.15063.0 + 10.0 Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode From 10e890bdd442c9a42b4b62f1696d7fb05e668669 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 1 Apr 2020 22:22:12 +0100 Subject: [PATCH 03/27] Begin the dynamic TG support. --- Conf.cpp | 107 ++++++++++++++++++++++++- Conf.h | 160 +++++++++++++++++++++---------------- DMRGateway.cpp | 61 +++++++++++++- DMRGateway.ini | 2 + DMRGateway.vcxproj | 4 + DMRGateway.vcxproj.filters | 12 +++ Makefile | 5 +- RewriteDynTGNet.cpp | 84 +++++++++++++++++++ RewriteDynTGNet.h | 46 +++++++++++ RewriteDynTGRF.cpp | 86 ++++++++++++++++++++ RewriteDynTGRF.h | 48 +++++++++++ 11 files changed, 539 insertions(+), 76 deletions(-) create mode 100644 RewriteDynTGNet.cpp create mode 100644 RewriteDynTGNet.h create mode 100644 RewriteDynTGRF.cpp create mode 100644 RewriteDynTGRF.h diff --git a/Conf.cpp b/Conf.cpp index b247556..e42264a 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX * * 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 @@ -82,6 +82,7 @@ m_dmrNetwork1TGRewrites(), m_dmrNetwork1PCRewrites(), m_dmrNetwork1TypeRewrites(), m_dmrNetwork1SrcRewrites(), +m_dmrNetwork1TGDynRewrites(), m_dmrNetwork1IdRewrites(), m_dmrNetwork1PassAllPC(), m_dmrNetwork1PassAllTG(), @@ -99,6 +100,7 @@ m_dmrNetwork2TGRewrites(), m_dmrNetwork2PCRewrites(), m_dmrNetwork2TypeRewrites(), m_dmrNetwork2SrcRewrites(), +m_dmrNetwork2TGDynRewrites(), m_dmrNetwork2IdRewrites(), m_dmrNetwork2PassAllPC(), m_dmrNetwork2PassAllTG(), @@ -116,6 +118,7 @@ m_dmrNetwork3TGRewrites(), m_dmrNetwork3PCRewrites(), m_dmrNetwork3TypeRewrites(), m_dmrNetwork3SrcRewrites(), +m_dmrNetwork3TGDynRewrites(), m_dmrNetwork3IdRewrites(), m_dmrNetwork3PassAllPC(), m_dmrNetwork3PassAllTG(), @@ -133,6 +136,7 @@ m_dmrNetwork4TGRewrites(), m_dmrNetwork4PCRewrites(), m_dmrNetwork4TypeRewrites(), m_dmrNetwork4SrcRewrites(), +m_dmrNetwork4TGDynRewrites(), m_dmrNetwork4IdRewrites(), m_dmrNetwork4PassAllPC(), m_dmrNetwork4PassAllTG(), @@ -150,6 +154,7 @@ m_dmrNetwork5TGRewrites(), m_dmrNetwork5PCRewrites(), m_dmrNetwork5TypeRewrites(), m_dmrNetwork5SrcRewrites(), +m_dmrNetwork5TGDynRewrites(), m_dmrNetwork5IdRewrites(), m_dmrNetwork5PassAllPC(), m_dmrNetwork5PassAllTG(), @@ -400,6 +405,21 @@ bool CConf::read() rewrite.m_range = ::atoi(p5); m_dmrNetwork1SrcRewrites.push_back(rewrite); } + } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + char* p1 = ::strtok(value, ", "); + char* p2 = ::strtok(NULL, ", "); + char* p3 = ::strtok(NULL, ", "); + char* p4 = ::strtok(NULL, " \r\n"); + char* p5 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + CTGDynRewriteStruct rewrite; + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_toTG = ::atoi(p4); + rewrite.m_range = ::atoi(p5); + m_dmrNetwork1TGDynRewrites.push_back(rewrite); + } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { char* rfId = ::strtok(value, ", "); char* netId = ::strtok(NULL, " \r\n"); @@ -495,6 +515,21 @@ bool CConf::read() rewrite.m_range = ::atoi(p5); m_dmrNetwork2SrcRewrites.push_back(rewrite); } + } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + char* p1 = ::strtok(value, ", "); + char* p2 = ::strtok(NULL, ", "); + char* p3 = ::strtok(NULL, ", "); + char* p4 = ::strtok(NULL, " \r\n"); + char* p5 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + CTGDynRewriteStruct rewrite; + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_toTG = ::atoi(p4); + rewrite.m_range = ::atoi(p5); + m_dmrNetwork2TGDynRewrites.push_back(rewrite); + } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { char* rfId = ::strtok(value, ", "); char* netId = ::strtok(NULL, " \r\n"); @@ -590,6 +625,21 @@ bool CConf::read() rewrite.m_range = ::atoi(p5); m_dmrNetwork3SrcRewrites.push_back(rewrite); } + } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + char* p1 = ::strtok(value, ", "); + char* p2 = ::strtok(NULL, ", "); + char* p3 = ::strtok(NULL, ", "); + char* p4 = ::strtok(NULL, " \r\n"); + char* p5 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + CTGDynRewriteStruct rewrite; + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_toTG = ::atoi(p4); + rewrite.m_range = ::atoi(p5); + m_dmrNetwork3TGDynRewrites.push_back(rewrite); + } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { char* rfId = ::strtok(value, ", "); char* netId = ::strtok(NULL, " \r\n"); @@ -685,6 +735,21 @@ bool CConf::read() rewrite.m_range = ::atoi(p5); m_dmrNetwork4SrcRewrites.push_back(rewrite); } + } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + char* p1 = ::strtok(value, ", "); + char* p2 = ::strtok(NULL, ", "); + char* p3 = ::strtok(NULL, ", "); + char* p4 = ::strtok(NULL, " \r\n"); + char* p5 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + CTGDynRewriteStruct rewrite; + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_toTG = ::atoi(p4); + rewrite.m_range = ::atoi(p5); + m_dmrNetwork4TGDynRewrites.push_back(rewrite); + } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { char* rfId = ::strtok(value, ", "); char* netId = ::strtok(NULL, " \r\n"); @@ -780,6 +845,21 @@ bool CConf::read() rewrite.m_range = ::atoi(p5); m_dmrNetwork5SrcRewrites.push_back(rewrite); } + } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + char* p1 = ::strtok(value, ", "); + char* p2 = ::strtok(NULL, ", "); + char* p3 = ::strtok(NULL, ", "); + char* p4 = ::strtok(NULL, " \r\n"); + char* p5 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + CTGDynRewriteStruct rewrite; + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_toTG = ::atoi(p4); + rewrite.m_range = ::atoi(p5); + m_dmrNetwork5TGDynRewrites.push_back(rewrite); + } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { char* rfId = ::strtok(value, ", "); char* netId = ::strtok(NULL, " \r\n"); @@ -1080,6 +1160,11 @@ std::vector CConf::getDMRNetwork1SrcRewrites() const return m_dmrNetwork1SrcRewrites; } +std::vector CConf::getDMRNetwork1TGDynRewrites() const +{ + return m_dmrNetwork1TGDynRewrites; +} + std::vector CConf::getDMRNetwork1IdRewrites() const { return m_dmrNetwork1IdRewrites; @@ -1168,6 +1253,11 @@ std::vector CConf::getDMRNetwork2SrcRewrites() const return m_dmrNetwork2SrcRewrites; } +std::vector CConf::getDMRNetwork2TGDynRewrites() const +{ + return m_dmrNetwork2TGDynRewrites; +} + std::vector CConf::getDMRNetwork2IdRewrites() const { return m_dmrNetwork2IdRewrites; @@ -1256,6 +1346,11 @@ std::vector CConf::getDMRNetwork3SrcRewrites() const return m_dmrNetwork3SrcRewrites; } +std::vector CConf::getDMRNetwork3TGDynRewrites() const +{ + return m_dmrNetwork3TGDynRewrites; +} + std::vector CConf::getDMRNetwork3IdRewrites() const { return m_dmrNetwork3IdRewrites; @@ -1344,6 +1439,11 @@ std::vector CConf::getDMRNetwork4SrcRewrites() const return m_dmrNetwork4SrcRewrites; } +std::vector CConf::getDMRNetwork4TGDynRewrites() const +{ + return m_dmrNetwork4TGDynRewrites; +} + std::vector CConf::getDMRNetwork4IdRewrites() const { return m_dmrNetwork4IdRewrites; @@ -1432,6 +1532,11 @@ std::vector CConf::getDMRNetwork5SrcRewrites() const return m_dmrNetwork5SrcRewrites; } +std::vector CConf::getDMRNetwork5TGDynRewrites() const +{ + return m_dmrNetwork5TGDynRewrites; +} + std::vector CConf::getDMRNetwork5IdRewrites() const { return m_dmrNetwork5IdRewrites; diff --git a/Conf.h b/Conf.h index cc0f617..1bbea8d 100644 --- a/Conf.h +++ b/Conf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2019,2020 by Jonathan Naylor G4KLX * * 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 @@ -53,6 +53,14 @@ struct CSrcRewriteStruct { unsigned int m_range; }; +struct CTGDynRewriteStruct { + unsigned int m_slot; + unsigned int m_fromTG; + unsigned int m_discTG; + unsigned int m_toTG; + unsigned int m_range; +}; + struct CIdRewriteStruct { unsigned int m_rfId; unsigned int m_netId; @@ -111,13 +119,14 @@ public: std::string getDMRNetwork1Options() const; bool getDMRNetwork1Location() const; bool getDMRNetwork1Debug() const; - std::vector getDMRNetwork1TGRewrites() const; - std::vector getDMRNetwork1PCRewrites() const; - std::vector getDMRNetwork1TypeRewrites() const; - std::vector getDMRNetwork1SrcRewrites() const; - std::vector getDMRNetwork1IdRewrites() const; - std::vector getDMRNetwork1PassAllPC() const; - std::vector getDMRNetwork1PassAllTG() const; + std::vector getDMRNetwork1TGRewrites() const; + std::vector getDMRNetwork1PCRewrites() const; + std::vector getDMRNetwork1TypeRewrites() const; + std::vector getDMRNetwork1SrcRewrites() const; + std::vector getDMRNetwork1TGDynRewrites() const; + std::vector getDMRNetwork1IdRewrites() const; + std::vector getDMRNetwork1PassAllPC() const; + std::vector getDMRNetwork1PassAllTG() const; // The DMR Network 2 section bool getDMRNetwork2Enabled() const; @@ -130,13 +139,14 @@ public: std::string getDMRNetwork2Options() const; bool getDMRNetwork2Location() const; bool getDMRNetwork2Debug() const; - std::vector getDMRNetwork2TGRewrites() const; - std::vector getDMRNetwork2PCRewrites() const; - std::vector getDMRNetwork2TypeRewrites() const; - std::vector getDMRNetwork2SrcRewrites() const; - std::vector getDMRNetwork2IdRewrites() const; - std::vector getDMRNetwork2PassAllPC() const; - std::vector getDMRNetwork2PassAllTG() const; + std::vector getDMRNetwork2TGRewrites() const; + std::vector getDMRNetwork2PCRewrites() const; + std::vector getDMRNetwork2TypeRewrites() const; + std::vector getDMRNetwork2SrcRewrites() const; + std::vector getDMRNetwork2TGDynRewrites() const; + std::vector getDMRNetwork2IdRewrites() const; + std::vector getDMRNetwork2PassAllPC() const; + std::vector getDMRNetwork2PassAllTG() const; // The DMR Network 3 section bool getDMRNetwork3Enabled() const; @@ -149,13 +159,14 @@ public: std::string getDMRNetwork3Options() const; bool getDMRNetwork3Location() const; bool getDMRNetwork3Debug() const; - std::vector getDMRNetwork3TGRewrites() const; - std::vector getDMRNetwork3PCRewrites() const; - std::vector getDMRNetwork3TypeRewrites() const; - std::vector getDMRNetwork3SrcRewrites() const; - std::vector getDMRNetwork3IdRewrites() const; - std::vector getDMRNetwork3PassAllPC() const; - std::vector getDMRNetwork3PassAllTG() const; + std::vector getDMRNetwork3TGRewrites() const; + std::vector getDMRNetwork3PCRewrites() const; + std::vector getDMRNetwork3TypeRewrites() const; + std::vector getDMRNetwork3SrcRewrites() const; + std::vector getDMRNetwork3TGDynRewrites() const; + std::vector getDMRNetwork3IdRewrites() const; + std::vector getDMRNetwork3PassAllPC() const; + std::vector getDMRNetwork3PassAllTG() const; // The DMR Network 4 section bool getDMRNetwork4Enabled() const; @@ -168,13 +179,14 @@ public: std::string getDMRNetwork4Options() const; bool getDMRNetwork4Location() const; bool getDMRNetwork4Debug() const; - std::vector getDMRNetwork4TGRewrites() const; - std::vector getDMRNetwork4PCRewrites() const; - std::vector getDMRNetwork4TypeRewrites() const; - std::vector getDMRNetwork4SrcRewrites() const; - std::vector getDMRNetwork4IdRewrites() const; - std::vector getDMRNetwork4PassAllPC() const; - std::vector getDMRNetwork4PassAllTG() const; + std::vector getDMRNetwork4TGRewrites() const; + std::vector getDMRNetwork4PCRewrites() const; + std::vector getDMRNetwork4TypeRewrites() const; + std::vector getDMRNetwork4SrcRewrites() const; + std::vector getDMRNetwork4TGDynRewrites() const; + std::vector getDMRNetwork4IdRewrites() const; + std::vector getDMRNetwork4PassAllPC() const; + std::vector getDMRNetwork4PassAllTG() const; // The DMR Network 5 section bool getDMRNetwork5Enabled() const; @@ -187,13 +199,14 @@ public: std::string getDMRNetwork5Options() const; bool getDMRNetwork5Location() const; bool getDMRNetwork5Debug() const; - std::vector getDMRNetwork5TGRewrites() const; - std::vector getDMRNetwork5PCRewrites() const; - std::vector getDMRNetwork5TypeRewrites() const; - std::vector getDMRNetwork5SrcRewrites() const; - std::vector getDMRNetwork5IdRewrites() const; - std::vector getDMRNetwork5PassAllPC() const; - std::vector getDMRNetwork5PassAllTG() const; + std::vector getDMRNetwork5TGRewrites() const; + std::vector getDMRNetwork5PCRewrites() const; + std::vector getDMRNetwork5TypeRewrites() const; + std::vector getDMRNetwork5SrcRewrites() const; + std::vector getDMRNetwork5TGDynRewrites() const; + std::vector getDMRNetwork5IdRewrites() const; + std::vector getDMRNetwork5PassAllPC() const; + std::vector getDMRNetwork5PassAllTG() const; // The XLX Network section bool getXLXNetworkEnabled() const; @@ -254,13 +267,14 @@ private: std::string m_dmrNetwork1Options; bool m_dmrNetwork1Location; bool m_dmrNetwork1Debug; - std::vector m_dmrNetwork1TGRewrites; - std::vector m_dmrNetwork1PCRewrites; - std::vector m_dmrNetwork1TypeRewrites; - std::vector m_dmrNetwork1SrcRewrites; - std::vector m_dmrNetwork1IdRewrites; - std::vector m_dmrNetwork1PassAllPC; - std::vector m_dmrNetwork1PassAllTG; + std::vector m_dmrNetwork1TGRewrites; + std::vector m_dmrNetwork1PCRewrites; + std::vector m_dmrNetwork1TypeRewrites; + std::vector m_dmrNetwork1SrcRewrites; + std::vector m_dmrNetwork1TGDynRewrites; + std::vector m_dmrNetwork1IdRewrites; + std::vector m_dmrNetwork1PassAllPC; + std::vector m_dmrNetwork1PassAllTG; bool m_dmrNetwork2Enabled; std::string m_dmrNetwork2Name; @@ -272,13 +286,14 @@ private: std::string m_dmrNetwork2Options; bool m_dmrNetwork2Location; bool m_dmrNetwork2Debug; - std::vector m_dmrNetwork2TGRewrites; - std::vector m_dmrNetwork2PCRewrites; - std::vector m_dmrNetwork2TypeRewrites; - std::vector m_dmrNetwork2SrcRewrites; - std::vector m_dmrNetwork2IdRewrites; - std::vector m_dmrNetwork2PassAllPC; - std::vector m_dmrNetwork2PassAllTG; + std::vector m_dmrNetwork2TGRewrites; + std::vector m_dmrNetwork2PCRewrites; + std::vector m_dmrNetwork2TypeRewrites; + std::vector m_dmrNetwork2SrcRewrites; + std::vector m_dmrNetwork2TGDynRewrites; + std::vector m_dmrNetwork2IdRewrites; + std::vector m_dmrNetwork2PassAllPC; + std::vector m_dmrNetwork2PassAllTG; bool m_dmrNetwork3Enabled; std::string m_dmrNetwork3Name; @@ -290,13 +305,14 @@ private: std::string m_dmrNetwork3Options; bool m_dmrNetwork3Location; bool m_dmrNetwork3Debug; - std::vector m_dmrNetwork3TGRewrites; - std::vector m_dmrNetwork3PCRewrites; - std::vector m_dmrNetwork3TypeRewrites; - std::vector m_dmrNetwork3SrcRewrites; - std::vector m_dmrNetwork3IdRewrites; - std::vector m_dmrNetwork3PassAllPC; - std::vector m_dmrNetwork3PassAllTG; + std::vector m_dmrNetwork3TGRewrites; + std::vector m_dmrNetwork3PCRewrites; + std::vector m_dmrNetwork3TypeRewrites; + std::vector m_dmrNetwork3SrcRewrites; + std::vector m_dmrNetwork3TGDynRewrites; + std::vector m_dmrNetwork3IdRewrites; + std::vector m_dmrNetwork3PassAllPC; + std::vector m_dmrNetwork3PassAllTG; bool m_dmrNetwork4Enabled; std::string m_dmrNetwork4Name; @@ -308,13 +324,14 @@ private: std::string m_dmrNetwork4Options; bool m_dmrNetwork4Location; bool m_dmrNetwork4Debug; - std::vector m_dmrNetwork4TGRewrites; - std::vector m_dmrNetwork4PCRewrites; - std::vector m_dmrNetwork4TypeRewrites; - std::vector m_dmrNetwork4SrcRewrites; - std::vector m_dmrNetwork4IdRewrites; - std::vector m_dmrNetwork4PassAllPC; - std::vector m_dmrNetwork4PassAllTG; + std::vector m_dmrNetwork4TGRewrites; + std::vector m_dmrNetwork4PCRewrites; + std::vector m_dmrNetwork4TypeRewrites; + std::vector m_dmrNetwork4SrcRewrites; + std::vector m_dmrNetwork4TGDynRewrites; + std::vector m_dmrNetwork4IdRewrites; + std::vector m_dmrNetwork4PassAllPC; + std::vector m_dmrNetwork4PassAllTG; bool m_dmrNetwork5Enabled; std::string m_dmrNetwork5Name; @@ -326,13 +343,14 @@ private: std::string m_dmrNetwork5Options; bool m_dmrNetwork5Location; bool m_dmrNetwork5Debug; - std::vector m_dmrNetwork5TGRewrites; - std::vector m_dmrNetwork5PCRewrites; - std::vector m_dmrNetwork5TypeRewrites; - std::vector m_dmrNetwork5SrcRewrites; - std::vector m_dmrNetwork5IdRewrites; - std::vector m_dmrNetwork5PassAllPC; - std::vector m_dmrNetwork5PassAllTG; + std::vector m_dmrNetwork5TGRewrites; + std::vector m_dmrNetwork5PCRewrites; + std::vector m_dmrNetwork5TypeRewrites; + std::vector m_dmrNetwork5SrcRewrites; + std::vector m_dmrNetwork5TGDynRewrites; + std::vector m_dmrNetwork5IdRewrites; + std::vector m_dmrNetwork5PassAllPC; + std::vector m_dmrNetwork5PassAllTG; bool m_xlxNetworkEnabled; unsigned int m_xlxNetworkId; diff --git a/DMRGateway.cpp b/DMRGateway.cpp index dce4d57..a7a8bd9 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX * * 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 @@ -24,6 +24,8 @@ #include "RewritePC.h" #include "RewriteSrcId.h" #include "RewriteDstId.h" +#include "RewriteDynTGNet.h" +#include "RewriteDynTGRF.h" #include "PassAllPC.h" #include "PassAllTG.h" #include "DMRFullLC.h" @@ -71,7 +73,7 @@ static void sigHandler(int signum) const char* HEADER1 = "This software is for use on amateur radio networks only,"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER3 = "commercial networks is strictly prohibited."; -const char* HEADER4 = "Copyright(C) 2017 by Jonathan Naylor, G4KLX and others"; +const char* HEADER4 = "Copyright(C) 2017-2020 by Jonathan Naylor, G4KLX and others"; int main(int argc, char** argv) { @@ -1333,6 +1335,17 @@ bool CDMRGateway::createDMRNetwork1() m_dmr1NetRewrites.push_back(rewrite); } + std::vector dynRewrites = m_conf.getDMRNetwork1TGDynRewrites(); + for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + + m_dmr1RFRewrites.push_back(rfRewriteDynTG); + m_dmr1NetRewrites.push_back(netRewriteDynTG); + } + std::vector idRewrites = m_conf.getDMRNetwork1IdRewrites(); for (std::vector::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) { LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId); @@ -1471,6 +1484,17 @@ bool CDMRGateway::createDMRNetwork2() m_dmr2NetRewrites.push_back(rewrite); } + std::vector dynRewrites = m_conf.getDMRNetwork2TGDynRewrites(); + for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + + m_dmr2RFRewrites.push_back(rfRewriteDynTG); + m_dmr2NetRewrites.push_back(netRewriteDynTG); + } + std::vector idRewrites = m_conf.getDMRNetwork2IdRewrites(); for (std::vector::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) { LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId); @@ -1609,6 +1633,17 @@ bool CDMRGateway::createDMRNetwork3() m_dmr3NetRewrites.push_back(rewrite); } + std::vector dynRewrites = m_conf.getDMRNetwork3TGDynRewrites(); + for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + + m_dmr3RFRewrites.push_back(rfRewriteDynTG); + m_dmr3NetRewrites.push_back(netRewriteDynTG); + } + std::vector idRewrites = m_conf.getDMRNetwork3IdRewrites(); for (std::vector::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) { LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId); @@ -1747,6 +1782,17 @@ bool CDMRGateway::createDMRNetwork4() m_dmr4NetRewrites.push_back(rewrite); } + std::vector dynRewrites = m_conf.getDMRNetwork4TGDynRewrites(); + for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + + m_dmr4RFRewrites.push_back(rfRewriteDynTG); + m_dmr4NetRewrites.push_back(netRewriteDynTG); + } + std::vector idRewrites = m_conf.getDMRNetwork4IdRewrites(); for (std::vector::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) { LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId); @@ -1885,6 +1931,17 @@ bool CDMRGateway::createDMRNetwork5() m_dmr5NetRewrites.push_back(rewrite); } + std::vector dynRewrites = m_conf.getDMRNetwork5TGDynRewrites(); + for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + + m_dmr5RFRewrites.push_back(rfRewriteDynTG); + m_dmr5NetRewrites.push_back(netRewriteDynTG); + } + std::vector idRewrites = m_conf.getDMRNetwork5IdRewrites(); for (std::vector::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) { LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId); diff --git a/DMRGateway.ini b/DMRGateway.ini index 8601468..da20960 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -70,6 +70,8 @@ TypeRewrite=1,9990,1,9990 SrcRewrite=1,9990,1,9990,1 # Reflector status returns SrcRewrite=2,4000,2,9,1001 +# Dynamic rewriting of slot 2 TGs 23500-23599 to TG9 to emulate reflector behaviour +TGDynRewrite=2,23500,4000,9,100 # Pass all of the other private traffic on slot 1 and slot 2 PassAllPC=1 PassAllPC=2 diff --git a/DMRGateway.vcxproj b/DMRGateway.vcxproj index dac6f95..10d9f01 100644 --- a/DMRGateway.vcxproj +++ b/DMRGateway.vcxproj @@ -177,6 +177,8 @@ + + @@ -219,6 +221,8 @@ + + diff --git a/DMRGateway.vcxproj.filters b/DMRGateway.vcxproj.filters index 126a6ab..ccb2799 100644 --- a/DMRGateway.vcxproj.filters +++ b/DMRGateway.vcxproj.filters @@ -134,6 +134,12 @@ Header Files + + Header Files + + + Header Files + @@ -250,5 +256,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index a2614c9..3919aaf 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,9 @@ LIBS = -lpthread LDFLAGS = -g OBJECTS = BPTC19696.o Conf.o CRC.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREmbeddedData.o DMREMB.o DMRFullLC.o DMRGateway.o DMRLC.o DMRNetwork.o DMRSlotType.o \ - Golay2087.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.o Rewrite.o RewriteDstId.o RewritePC.o RewriteSrc.o \ - RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o Utils.o Voice.o + Golay2087.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o \ + RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o \ + Utils.o Voice.o all: DMRGateway diff --git a/RewriteDynTGNet.cpp b/RewriteDynTGNet.cpp new file mode 100644 index 0000000..3e4f99c --- /dev/null +++ b/RewriteDynTGNet.cpp @@ -0,0 +1,84 @@ +/* +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX +* +* 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 "RewriteDynTGNet.h" + +#include "DMRDefines.h" +#include "Log.h" + +#include +#include + +CRewriteDynTGNet::CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range) : +CRewrite(), +m_name(name), +m_slot(slot), +m_fromTGStart(fromTG), +m_fromTGEnd(fromTG + range - 1U), +m_toTG(toTG), +m_discTG(discTG), +m_currentTG(0U) +{ + assert(slot == 1U || slot == 2U); +} + +CRewriteDynTGNet::~CRewriteDynTGNet() +{ +} + +bool CRewriteDynTGNet::process(CDMRData& data, bool trace) +{ + FLCO flco = data.getFLCO(); + unsigned int dstId = data.getDstId(); + unsigned int slotNo = data.getSlotNo(); + + if (flco != FLCO_GROUP || slotNo != m_fromSlot || dstId < m_fromTGStart || dstId > m_fromTGEnd) { + if (trace) { + if (m_fromTGStart == m_fromTGEnd) + LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + else + LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u-TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); + } + + return false; + } + + if (m_fromSlot != m_toSlot) + data.setSlotNo(m_toSlot); + + if (m_fromTGStart != m_toTGStart) { + unsigned int newTG = dstId + m_toTGStart - m_fromTGStart; + data.setDstId(newTG); + + processMessage(data); + } + + if (trace) { + if (m_fromTGStart == m_fromTGEnd) + LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + else + LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); + + if (m_toTGStart == m_toTGEnd) + LogDebug("Rule Trace,\tRewriteDynTGNet to %s Slot=%u Dst=TG%u", m_name.c_str(), m_toSlot, m_toTGStart); + else + LogDebug("Rule Trace,\tRewriteDynTGNet to %s Slot=%u Dst=TG%u-TG%u", m_name.c_str(), m_toSlot, m_toTGStart, m_toTGEnd); + } + + return true; +} diff --git a/RewriteDynTGNet.h b/RewriteDynTGNet.h new file mode 100644 index 0000000..feb6a83 --- /dev/null +++ b/RewriteDynTGNet.h @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX +* +* 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. +*/ + +#if !defined(REWRITEDYNTGNET_H) +#define REWRITEDYNTGNET_H + +#include "Rewrite.h" +#include "DMRData.h" + +#include + +class CRewriteDynTGNet : public CRewrite { +public: + CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range); + virtual ~CRewriteDynTGNet(); + + virtual bool process(CDMRData& data, bool trace); + + void setCurrentTG(unsigned int tg); + +private: + std::string m_name; + unsigned int m_slot; + unsigned int m_fromTGStart; + unsigned int m_fromTGEnd; + unsigned int m_toTG; + unsigned int m_discTG; + unsigned int m_currentTG; +}; + +#endif diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp new file mode 100644 index 0000000..eaa9aab --- /dev/null +++ b/RewriteDynTGRF.cpp @@ -0,0 +1,86 @@ +/* +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX +* +* 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 "RewriteDynTGRF.h" + +#include "DMRDefines.h" +#include "Log.h" + +#include +#include + +CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range, CRewriteDynTGNet* rewriteNet) : +CRewrite(), +m_name(name), +m_slot(slot), +m_fromTGStart(fromTG), +m_fromTGEnd(fromTG + range - 1U), +m_toTG(toTG), +m_discTG(discTG), +m_rewriteNet(rewriteNet), +m_currentTG(0U) +{ + assert(slot == 1U || slot == 2U); + assert(rewriteNet != NULL); +} + +CRewriteDynTGRF::~CRewriteDynTGRF() +{ +} + +bool CRewriteDynTGRF::process(CDMRData& data, bool trace) +{ + FLCO flco = data.getFLCO(); + unsigned int dstId = data.getDstId(); + unsigned int slotNo = data.getSlotNo(); + + if (flco != FLCO_GROUP || slotNo != m_fromSlot || dstId < m_fromTGStart || dstId > m_fromTGEnd) { + if (trace) { + if (m_fromTGStart == m_fromTGEnd) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + else + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); + } + + return false; + } + + if (m_fromSlot != m_toSlot) + data.setSlotNo(m_toSlot); + + if (m_fromTGStart != m_toTGStart) { + unsigned int newTG = dstId + m_toTGStart - m_fromTGStart; + data.setDstId(newTG); + + processMessage(data); + } + + if (trace) { + if (m_fromTGStart == m_fromTGEnd) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + else + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); + + if (m_toTGStart == m_toTGEnd) + LogDebug("Rule Trace,\tRewriteDynTGRF to %s Slot=%u Dst=TG%u", m_name.c_str(), m_toSlot, m_toTGStart); + else + LogDebug("Rule Trace,\tRewriteDynTGRF to %s Slot=%u Dst=TG%u-TG%u", m_name.c_str(), m_toSlot, m_toTGStart, m_toTGEnd); + } + + return true; +} diff --git a/RewriteDynTGRF.h b/RewriteDynTGRF.h new file mode 100644 index 0000000..9318789 --- /dev/null +++ b/RewriteDynTGRF.h @@ -0,0 +1,48 @@ +/* +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX +* +* 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. +*/ + +#if !defined(REWRITEDYNTGRF_H) +#define REWRITEDYNTGRF_H + +#include "Rewrite.h" +#include "DMRData.h" + +#include "RewriteDynTGNet.h" + +#include + +class CRewriteDynTGRF : public CRewrite { +public: + CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range, CRewriteDynTGNet* rewriteNet); + virtual ~CRewriteDynTGRF(); + + virtual bool process(CDMRData& data, bool trace); + +private: + std::string m_name; + unsigned int m_slot; + unsigned int m_fromTGStart; + unsigned int m_fromTGEnd; + unsigned int m_toTG; + unsigned int m_discTG; + CRewriteDynTGNet* m_rewriteNet; + unsigned int m_currentTG; +}; + + +#endif From 8fc9872aaaaec6520f1aa5406c8a9f31942edf34 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 1 Apr 2020 22:56:48 +0100 Subject: [PATCH 04/27] Finish off the translation logic. --- DMRGateway.cpp | 10 ++++---- RewriteDynTGNet.cpp | 43 ++++++++++----------------------- RewriteDynTGNet.h | 5 +--- RewriteDynTGRF.cpp | 59 ++++++++++++++++++++++++++------------------- Version.h | 4 +-- 5 files changed, 55 insertions(+), 66 deletions(-) diff --git a/DMRGateway.cpp b/DMRGateway.cpp index a7a8bd9..54f9b62 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -1339,7 +1339,7 @@ bool CDMRGateway::createDMRNetwork1() for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); - CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr1Name, (*it).m_slot, (*it).m_toTG); CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); m_dmr1RFRewrites.push_back(rfRewriteDynTG); @@ -1488,7 +1488,7 @@ bool CDMRGateway::createDMRNetwork2() for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); - CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr2Name, (*it).m_slot, (*it).m_toTG); CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); m_dmr2RFRewrites.push_back(rfRewriteDynTG); @@ -1637,7 +1637,7 @@ bool CDMRGateway::createDMRNetwork3() for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); - CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr3Name, (*it).m_slot, (*it).m_toTG); CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); m_dmr3RFRewrites.push_back(rfRewriteDynTG); @@ -1786,7 +1786,7 @@ bool CDMRGateway::createDMRNetwork4() for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); - CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr4Name, (*it).m_slot, (*it).m_toTG); CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); m_dmr4RFRewrites.push_back(rfRewriteDynTG); @@ -1935,7 +1935,7 @@ bool CDMRGateway::createDMRNetwork5() for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); - CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range); + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr5Name, (*it).m_slot, (*it).m_toTG); CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); m_dmr5RFRewrites.push_back(rfRewriteDynTG); diff --git a/RewriteDynTGNet.cpp b/RewriteDynTGNet.cpp index 3e4f99c..889117e 100644 --- a/RewriteDynTGNet.cpp +++ b/RewriteDynTGNet.cpp @@ -24,14 +24,11 @@ #include #include -CRewriteDynTGNet::CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range) : +CRewriteDynTGNet::CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int toTG) : CRewrite(), m_name(name), m_slot(slot), -m_fromTGStart(fromTG), -m_fromTGEnd(fromTG + range - 1U), m_toTG(toTG), -m_discTG(discTG), m_currentTG(0U) { assert(slot == 1U || slot == 2U); @@ -47,38 +44,24 @@ bool CRewriteDynTGNet::process(CDMRData& data, bool trace) unsigned int dstId = data.getDstId(); unsigned int slotNo = data.getSlotNo(); - if (flco != FLCO_GROUP || slotNo != m_fromSlot || dstId < m_fromTGStart || dstId > m_fromTGEnd) { - if (trace) { - if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart); - else - LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u-TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); - } + if (flco != FLCO_GROUP || slotNo != m_slot || dstId != m_currentTG) { + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_slot, m_currentTG); return false; } - if (m_fromSlot != m_toSlot) - data.setSlotNo(m_toSlot); + data.setDstId(m_toTG); - if (m_fromTGStart != m_toTGStart) { - unsigned int newTG = dstId + m_toTGStart - m_fromTGStart; - data.setDstId(newTG); + processMessage(data); - processMessage(data); - } - - if (trace) { - if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart); - else - LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); - - if (m_toTGStart == m_toTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGNet to %s Slot=%u Dst=TG%u", m_name.c_str(), m_toSlot, m_toTGStart); - else - LogDebug("Rule Trace,\tRewriteDynTGNet to %s Slot=%u Dst=TG%u-TG%u", m_name.c_str(), m_toSlot, m_toTGStart, m_toTGEnd); - } + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_currentTG); return true; } + +void CRewriteDynTGNet::setCurrentTG(unsigned int currentTG) +{ + m_currentTG = currentTG; +} diff --git a/RewriteDynTGNet.h b/RewriteDynTGNet.h index feb6a83..fb04031 100644 --- a/RewriteDynTGNet.h +++ b/RewriteDynTGNet.h @@ -26,7 +26,7 @@ class CRewriteDynTGNet : public CRewrite { public: - CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range); + CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int toTG); virtual ~CRewriteDynTGNet(); virtual bool process(CDMRData& data, bool trace); @@ -36,10 +36,7 @@ public: private: std::string m_name; unsigned int m_slot; - unsigned int m_fromTGStart; - unsigned int m_fromTGEnd; unsigned int m_toTG; - unsigned int m_discTG; unsigned int m_currentTG; }; diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index eaa9aab..a8cdb7f 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -49,38 +49,47 @@ bool CRewriteDynTGRF::process(CDMRData& data, bool trace) unsigned int dstId = data.getDstId(); unsigned int slotNo = data.getSlotNo(); - if (flco != FLCO_GROUP || slotNo != m_fromSlot || dstId < m_fromTGStart || dstId > m_fromTGEnd) { - if (trace) { - if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart); - else - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); - } - - return false; - } - - if (m_fromSlot != m_toSlot) - data.setSlotNo(m_toSlot); - - if (m_fromTGStart != m_toTGStart) { - unsigned int newTG = dstId + m_toTGStart - m_fromTGStart; - data.setDstId(newTG); + if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_toTG && m_currentTG != 0U) { + data.setDstId(m_currentTG); processMessage(data); + + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_toTG); + + return true; + } + + if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_discTG && m_currentTG != 0U) { + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_discTG); + + m_rewriteNet->setCurrentTG(0U); + m_currentTG = 0U; + + return true; + } + + if (flco == FLCO_GROUP && slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { + if (trace) { + if (m_fromTGStart == m_fromTGEnd) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart); + else + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd); + } + + m_rewriteNet->setCurrentTG(dstId); + m_currentTG = dstId; + + return true; } if (trace) { if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discTG); else - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); - - if (m_toTGStart == m_toTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGRF to %s Slot=%u Dst=TG%u", m_name.c_str(), m_toSlot, m_toTGStart); - else - LogDebug("Rule Trace,\tRewriteDynTGRF to %s Slot=%u Dst=TG%u-TG%u", m_name.c_str(), m_toSlot, m_toTGStart, m_toTGEnd); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discTG); } - return true; + return false; } diff --git a/Version.h b/Version.h index bd50711..726b272 100644 --- a/Version.h +++ b/Version.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX * * 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 @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20190717"; +const char* VERSION = "20200401"; #endif From bd2366ed23cae15f7ec50312fdf073b301cd37fb Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 2 Apr 2020 22:47:23 +0100 Subject: [PATCH 05/27] Fix cnfiguration bug. --- Conf.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index e42264a..6e966dd 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -409,7 +409,7 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, " \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { CTGDynRewriteStruct rewrite; @@ -519,7 +519,7 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, " \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { CTGDynRewriteStruct rewrite; @@ -629,7 +629,7 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, " \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { CTGDynRewriteStruct rewrite; @@ -739,7 +739,7 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, " \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { CTGDynRewriteStruct rewrite; @@ -849,7 +849,7 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, " \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { CTGDynRewriteStruct rewrite; From 73270ad7a58719e1aedc454abf77ba7b728c45cd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 3 Apr 2020 15:10:41 +0100 Subject: [PATCH 06/27] Allow for more rewrite processing options. --- DMRGateway.cpp | 102 ++++++++++++++++++++++---------------------- PassAllPC.cpp | 6 +-- PassAllPC.h | 4 +- PassAllTG.cpp | 6 +-- PassAllTG.h | 4 +- Rewrite.h | 10 ++++- RewriteDstId.cpp | 8 ++-- RewriteDstId.h | 4 +- RewriteDynTGNet.cpp | 6 +-- RewriteDynTGNet.h | 2 +- RewriteDynTGRF.cpp | 10 ++--- RewriteDynTGRF.h | 2 +- RewritePC.cpp | 8 ++-- RewritePC.h | 4 +- RewriteSrc.cpp | 8 ++-- RewriteSrc.h | 4 +- RewriteSrcId.cpp | 8 ++-- RewriteSrcId.h | 4 +- RewriteTG.cpp | 8 ++-- RewriteTG.h | 4 +- RewriteType.cpp | 8 ++-- RewriteType.h | 4 +- 22 files changed, 115 insertions(+), 109 deletions(-) diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 54f9b62..8795414 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -615,19 +615,19 @@ int CDMRGateway::run() if (trace) LogDebug("Rule Trace, RF transmission: Slot=%u Src=%u Dst=%s%u", slotNo, srcId, flco == FLCO_GROUP ? "TG" : "", dstId); - bool rewritten = false; + PROCESS_RESULT result = RESULT_UNMATCHED; if (m_dmrNetwork1 != NULL) { // Rewrite the slot and/or TG or neither for (std::vector::iterator it = m_dmr1RFRewrites.begin(); it != m_dmr1RFRewrites.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK1) { rewrite(m_dmr1SrcRewrites, data, trace); m_dmrNetwork1->write(data); @@ -638,18 +638,18 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork2 != NULL) { // Rewrite the slot and/or TG or neither for (std::vector::iterator it = m_dmr2RFRewrites.begin(); it != m_dmr2RFRewrites.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK2) { rewrite(m_dmr2SrcRewrites, data, trace); m_dmrNetwork2->write(data); @@ -661,18 +661,18 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork3 != NULL) { // Rewrite the slot and/or TG or neither for (std::vector::iterator it = m_dmr3RFRewrites.begin(); it != m_dmr3RFRewrites.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK3) { rewrite(m_dmr3SrcRewrites, data, trace); m_dmrNetwork3->write(data); @@ -684,18 +684,18 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork4 != NULL) { // Rewrite the slot and/or TG or neither for (std::vector::iterator it = m_dmr4RFRewrites.begin(); it != m_dmr4RFRewrites.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK4) { rewrite(m_dmr4SrcRewrites, data, trace); m_dmrNetwork4->write(data); @@ -707,18 +707,18 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork5 != NULL) { // Rewrite the slot and/or TG or neither for (std::vector::iterator it = m_dmr5RFRewrites.begin(); it != m_dmr5RFRewrites.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK5) { rewrite(m_dmr5SrcRewrites, data, trace); m_dmrNetwork5->write(data); @@ -730,17 +730,17 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork1 != NULL) { for (std::vector::iterator it = m_dmr1Passalls.begin(); it != m_dmr1Passalls.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK1) { rewrite(m_dmr1SrcRewrites, data, trace); m_dmrNetwork1->write(data); @@ -752,17 +752,17 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork2 != NULL) { for (std::vector::iterator it = m_dmr2Passalls.begin(); it != m_dmr2Passalls.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK2) { rewrite(m_dmr2SrcRewrites, data, trace); m_dmrNetwork2->write(data); @@ -774,17 +774,17 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork3 != NULL) { for (std::vector::iterator it = m_dmr3Passalls.begin(); it != m_dmr3Passalls.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK3) { rewrite(m_dmr3SrcRewrites, data, trace); m_dmrNetwork3->write(data); @@ -796,17 +796,17 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork4 != NULL) { for (std::vector::iterator it = m_dmr4Passalls.begin(); it != m_dmr4Passalls.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK4) { rewrite(m_dmr4SrcRewrites, data, trace); m_dmrNetwork4->write(data); @@ -818,17 +818,17 @@ int CDMRGateway::run() } } - if (!rewritten) { + if (result == RESULT_UNMATCHED) { if (m_dmrNetwork5 != NULL) { for (std::vector::iterator it = m_dmr5Passalls.begin(); it != m_dmr5Passalls.end(); ++it) { - bool ret = (*it)->process(data, trace); - if (ret) { - rewritten = true; + PROCESS_RESULT res = (*it)->process(data, trace); + if (res != RESULT_UNMATCHED) { + result = res; break; } } - if (rewritten) { + if (result == RESULT_MATCHED) { if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK5) { rewrite(m_dmr5SrcRewrites, data, trace); m_dmrNetwork5->write(data); @@ -840,7 +840,7 @@ int CDMRGateway::run() } } - if (!rewritten && trace) + if (result == RESULT_UNMATCHED && trace) LogDebug("Rule Trace,\tnot matched so rejected"); } } diff --git a/PassAllPC.cpp b/PassAllPC.cpp index 342e988..08129d7 100644 --- a/PassAllPC.cpp +++ b/PassAllPC.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -36,7 +36,7 @@ CPassAllPC::~CPassAllPC() { } -bool CPassAllPC::process(CDMRData& data, bool trace) +PROCESS_RESULT CPassAllPC::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int slotNo = data.getSlotNo(); @@ -46,5 +46,5 @@ bool CPassAllPC::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tPassAllPC %s Slot=%u: %s", m_name.c_str(), m_slot, ret ? "matched" : "not matched"); - return ret; + return ret ? RESULT_MATCHED : RESULT_UNMATCHED; } diff --git a/PassAllPC.h b/PassAllPC.h index 3b589b0..b48d5d4 100644 --- a/PassAllPC.h +++ b/PassAllPC.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CPassAllPC(const std::string& name, unsigned int slot); virtual ~CPassAllPC(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/PassAllTG.cpp b/PassAllTG.cpp index ccfb08e..7a72d33 100644 --- a/PassAllTG.cpp +++ b/PassAllTG.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -36,7 +36,7 @@ CPassAllTG::~CPassAllTG() { } -bool CPassAllTG::process(CDMRData& data, bool trace) +PROCESS_RESULT CPassAllTG::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int slotNo = data.getSlotNo(); @@ -46,5 +46,5 @@ bool CPassAllTG::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tPassAllTG %s Slot=%u: %s", m_name.c_str(), m_slot, ret ? "matched" : "not matched"); - return ret; + return ret ? RESULT_MATCHED : RESULT_UNMATCHED; } diff --git a/PassAllTG.h b/PassAllTG.h index 01078bd..0974701 100644 --- a/PassAllTG.h +++ b/PassAllTG.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CPassAllTG(const std::string& name, unsigned int slot); virtual ~CPassAllTG(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/Rewrite.h b/Rewrite.h index f2789eb..ce0dbf4 100644 --- a/Rewrite.h +++ b/Rewrite.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -23,12 +23,18 @@ #include "DMRData.h" #include "DMRLC.h" +enum PROCESS_RESULT { + RESULT_UNMATCHED, + RESULT_MATCHED, + RESULT_IGNORED +}; + class CRewrite { public: CRewrite(); virtual ~CRewrite(); - virtual bool process(CDMRData& data, bool trace) = 0; + virtual PROCESS_RESULT process(CDMRData& data, bool trace) = 0; protected: void processMessage(CDMRData& data); diff --git a/RewriteDstId.cpp b/RewriteDstId.cpp index ef796e3..e979965 100644 --- a/RewriteDstId.cpp +++ b/RewriteDstId.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -35,7 +35,7 @@ CRewriteDstId::~CRewriteDstId() { } -bool CRewriteDstId::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewriteDstId::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int dstId = data.getDstId(); @@ -44,7 +44,7 @@ bool CRewriteDstId::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteDstId from %s Src=%u: not matched", m_name.c_str(), m_fromId); - return false; + return RESULT_UNMATCHED; } data.setDstId(m_toId); @@ -56,5 +56,5 @@ bool CRewriteDstId::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewriteDstId to %s Src=%u", m_name.c_str(), m_toId); } - return true; + return RESULT_MATCHED; } diff --git a/RewriteDstId.h b/RewriteDstId.h index 8d066bd..388ffd6 100644 --- a/RewriteDstId.h +++ b/RewriteDstId.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CRewriteDstId(const std::string& name, unsigned int fromId, unsigned int toID); virtual ~CRewriteDstId(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/RewriteDynTGNet.cpp b/RewriteDynTGNet.cpp index 889117e..8854e34 100644 --- a/RewriteDynTGNet.cpp +++ b/RewriteDynTGNet.cpp @@ -38,7 +38,7 @@ CRewriteDynTGNet::~CRewriteDynTGNet() { } -bool CRewriteDynTGNet::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewriteDynTGNet::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int dstId = data.getDstId(); @@ -48,7 +48,7 @@ bool CRewriteDynTGNet::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_slot, m_currentTG); - return false; + return RESULT_UNMATCHED; } data.setDstId(m_toTG); @@ -58,7 +58,7 @@ bool CRewriteDynTGNet::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_currentTG); - return true; + return RESULT_MATCHED; } void CRewriteDynTGNet::setCurrentTG(unsigned int currentTG) diff --git a/RewriteDynTGNet.h b/RewriteDynTGNet.h index fb04031..60b59c7 100644 --- a/RewriteDynTGNet.h +++ b/RewriteDynTGNet.h @@ -29,7 +29,7 @@ public: CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int toTG); virtual ~CRewriteDynTGNet(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); void setCurrentTG(unsigned int tg); diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index a8cdb7f..c0abf4b 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -43,7 +43,7 @@ CRewriteDynTGRF::~CRewriteDynTGRF() { } -bool CRewriteDynTGRF::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int dstId = data.getDstId(); @@ -57,7 +57,7 @@ bool CRewriteDynTGRF::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_toTG); - return true; + return RESULT_MATCHED; } if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_discTG && m_currentTG != 0U) { @@ -67,7 +67,7 @@ bool CRewriteDynTGRF::process(CDMRData& data, bool trace) m_rewriteNet->setCurrentTG(0U); m_currentTG = 0U; - return true; + return RESULT_MATCHED; } if (flco == FLCO_GROUP && slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { @@ -81,7 +81,7 @@ bool CRewriteDynTGRF::process(CDMRData& data, bool trace) m_rewriteNet->setCurrentTG(dstId); m_currentTG = dstId; - return true; + return RESULT_MATCHED; } if (trace) { @@ -91,5 +91,5 @@ bool CRewriteDynTGRF::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discTG); } - return false; + return RESULT_UNMATCHED; } diff --git a/RewriteDynTGRF.h b/RewriteDynTGRF.h index 9318789..695970c 100644 --- a/RewriteDynTGRF.h +++ b/RewriteDynTGRF.h @@ -31,7 +31,7 @@ public: CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range, CRewriteDynTGNet* rewriteNet); virtual ~CRewriteDynTGRF(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/RewritePC.cpp b/RewritePC.cpp index 9420945..bc2b579 100644 --- a/RewritePC.cpp +++ b/RewritePC.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -42,7 +42,7 @@ CRewritePC::~CRewritePC() { } -bool CRewritePC::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewritePC::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int dstId = data.getDstId(); @@ -52,7 +52,7 @@ bool CRewritePC::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewritePC from %s Slot=%u Dst=%u-%u: not matched", m_name.c_str(), m_fromSlot, m_fromIdStart, m_fromIdEnd); - return false; + return RESULT_UNMATCHED; } if (m_fromSlot != m_toSlot) @@ -70,5 +70,5 @@ bool CRewritePC::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewritePC to %s Slot=%u Dst=%u-%u", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdEnd); } - return true; + return RESULT_MATCHED; } diff --git a/RewritePC.h b/RewritePC.h index 7d42432..d60b12b 100644 --- a/RewritePC.h +++ b/RewritePC.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CRewritePC(const std::string& name, unsigned int fromSlot, unsigned int fromId, unsigned int toSlot, unsigned int toId, unsigned int range); virtual ~CRewritePC(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/RewriteSrc.cpp b/RewriteSrc.cpp index dcd2152..ba61c25 100644 --- a/RewriteSrc.cpp +++ b/RewriteSrc.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -41,7 +41,7 @@ CRewriteSrc::~CRewriteSrc() { } -bool CRewriteSrc::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewriteSrc::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int srcId = data.getSrcId(); @@ -51,7 +51,7 @@ bool CRewriteSrc::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteSrc from %s Slot=%u Src=%u-%u: not matched", m_name.c_str(), m_fromSlot, m_fromIdStart, m_fromIdEnd); - return false; + return RESULT_UNMATCHED; } if (m_fromSlot != m_toSlot) @@ -67,5 +67,5 @@ bool CRewriteSrc::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewriteSrc to %s Slot=%u Dst=TG%u", m_name.c_str(), m_toSlot, m_toTG); } - return true; + return RESULT_MATCHED; } diff --git a/RewriteSrc.h b/RewriteSrc.h index d970f23..83321bc 100644 --- a/RewriteSrc.h +++ b/RewriteSrc.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CRewriteSrc(const std::string& name, unsigned int fromSlot, unsigned int fromId, unsigned int toSlot, unsigned int toTG, unsigned int range); virtual ~CRewriteSrc(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/RewriteSrcId.cpp b/RewriteSrcId.cpp index 2382c75..1255a65 100644 --- a/RewriteSrcId.cpp +++ b/RewriteSrcId.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -35,7 +35,7 @@ CRewriteSrcId::~CRewriteSrcId() { } -bool CRewriteSrcId::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewriteSrcId::process(CDMRData& data, bool trace) { unsigned int srcId = data.getSrcId(); @@ -43,7 +43,7 @@ bool CRewriteSrcId::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteSrcId from %s Src=%u: not matched", m_name.c_str(), m_fromId); - return false; + return RESULT_UNMATCHED; } data.setSrcId(m_toId); @@ -55,5 +55,5 @@ bool CRewriteSrcId::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewriteSrcId to %s Src=%u", m_name.c_str(), m_toId); } - return true; + return RESULT_MATCHED; } diff --git a/RewriteSrcId.h b/RewriteSrcId.h index 76bd17e..ff33006 100644 --- a/RewriteSrcId.h +++ b/RewriteSrcId.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CRewriteSrcId(const std::string& name, unsigned int fromId, unsigned int toID); virtual ~CRewriteSrcId(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/RewriteTG.cpp b/RewriteTG.cpp index 73d7176..1741a33 100644 --- a/RewriteTG.cpp +++ b/RewriteTG.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -42,7 +42,7 @@ CRewriteTG::~CRewriteTG() { } -bool CRewriteTG::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewriteTG::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int dstId = data.getDstId(); @@ -56,7 +56,7 @@ bool CRewriteTG::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewriteTG from %s Slot=%u Dst=TG%u-TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); } - return false; + return RESULT_UNMATCHED; } if (m_fromSlot != m_toSlot) @@ -81,5 +81,5 @@ bool CRewriteTG::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewriteTG to %s Slot=%u Dst=TG%u-TG%u", m_name.c_str(), m_toSlot, m_toTGStart, m_toTGEnd); } - return true; + return RESULT_MATCHED; } diff --git a/RewriteTG.h b/RewriteTG.h index 30c8984..88dd06f 100644 --- a/RewriteTG.h +++ b/RewriteTG.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CRewriteTG(const std::string& name, unsigned int fromSlot, unsigned int fromTG, unsigned int toSlot, unsigned int toTG, unsigned int range); virtual ~CRewriteTG(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; diff --git a/RewriteType.cpp b/RewriteType.cpp index c691fcc..c069145 100644 --- a/RewriteType.cpp +++ b/RewriteType.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -40,7 +40,7 @@ CRewriteType::~CRewriteType() { } -bool CRewriteType::process(CDMRData& data, bool trace) +PROCESS_RESULT CRewriteType::process(CDMRData& data, bool trace) { FLCO flco = data.getFLCO(); unsigned int dstId = data.getDstId(); @@ -50,7 +50,7 @@ bool CRewriteType::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteType %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTG); - return false; + return RESULT_UNMATCHED; } if (m_fromSlot != m_toSlot) @@ -64,5 +64,5 @@ bool CRewriteType::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteType %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTG); - return true; + return RESULT_MATCHED; } diff --git a/RewriteType.h b/RewriteType.h index 2cb8834..70399d0 100644 --- a/RewriteType.h +++ b/RewriteType.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -29,7 +29,7 @@ public: CRewriteType(const std::string& name, unsigned int fromSlot, unsigned int fromTG, unsigned int toSlot, unsigned int toId); virtual ~CRewriteType(); - virtual bool process(CDMRData& data, bool trace); + virtual PROCESS_RESULT process(CDMRData& data, bool trace); private: std::string m_name; From 9771b1ff0c484bc5ccf81473e6383ed48c0f6a09 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 3 Apr 2020 15:25:33 +0100 Subject: [PATCH 07/27] Prepare for having two voice subsystems. --- DMRGateway.cpp | 6 +++--- DMRGateway.ini | 2 +- DMRGateway.vcxproj | 4 ++-- DMRGateway.vcxproj.filters | 12 ++++++------ Makefile | 2 +- Voice.cpp => XLXVoice.cpp | 22 +++++++++++----------- Voice.h => XLXVoice.h | 12 ++++++------ 7 files changed, 30 insertions(+), 30 deletions(-) rename Voice.cpp => XLXVoice.cpp (93%) rename Voice.h => XLXVoice.h (89%) diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 8795414..073f026 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -29,10 +29,10 @@ #include "PassAllPC.h" #include "PassAllTG.h" #include "DMRFullLC.h" +#include "XLXVoice.h" #include "Version.h" #include "Thread.h" #include "DMRLC.h" -#include "Voice.h" #include "Sync.h" #include "Log.h" #include "GitVersion.h" @@ -409,7 +409,7 @@ int CDMRGateway::run() unsigned int rfTimeout = m_conf.getRFTimeout(); unsigned int netTimeout = m_conf.getNetTimeout(); - CVoice* voice = NULL; + CXLXVoice* voice = NULL; if (m_conf.getVoiceEnabled() && m_xlxNetwork != NULL) { std::string language = m_conf.getVoiceLanguage(); std::string directory = m_conf.getVoiceDirectory(); @@ -419,7 +419,7 @@ int CDMRGateway::run() LogInfo(" Language: %s", language.c_str()); LogInfo(" Directory: %s", directory.c_str()); - voice = new CVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG); + voice = new CXLXVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG); bool ret = voice->open(); if (!ret) { delete voice; diff --git a/DMRGateway.ini b/DMRGateway.ini index da20960..b888949 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -54,7 +54,7 @@ UserControl=1 # BrandMeister [DMR Network 1] -Enabled=0 +Enabled=1 Name=BM Address=44.131.4.1 Port=62031 diff --git a/DMRGateway.vcxproj b/DMRGateway.vcxproj index 10d9f01..3485b79 100644 --- a/DMRGateway.vcxproj +++ b/DMRGateway.vcxproj @@ -194,7 +194,7 @@ - + @@ -236,7 +236,7 @@ - + diff --git a/DMRGateway.vcxproj.filters b/DMRGateway.vcxproj.filters index ccb2799..91c4c0a 100644 --- a/DMRGateway.vcxproj.filters +++ b/DMRGateway.vcxproj.filters @@ -95,9 +95,6 @@ Header Files - - Header Files - Header Files @@ -140,6 +137,9 @@ Header Files + + Header Files + @@ -217,9 +217,6 @@ Source Files - - Source Files - Source Files @@ -262,5 +259,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index 3919aaf..4fc7e45 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ LDFLAGS = -g OBJECTS = BPTC19696.o Conf.o CRC.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREmbeddedData.o DMREMB.o DMRFullLC.o DMRGateway.o DMRLC.o DMRNetwork.o DMRSlotType.o \ Golay2087.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o \ RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o \ - Utils.o Voice.o + Utils.o XLXVoice.o all: DMRGateway diff --git a/Voice.cpp b/XLXVoice.cpp similarity index 93% rename from Voice.cpp rename to XLXVoice.cpp index 63b650c..b0b6fe2 100644 --- a/Voice.cpp +++ b/XLXVoice.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -18,8 +18,8 @@ #include "DMRSlotType.h" #include "DMRFullLC.h" +#include "XLXVoice.h" #include "DMREMB.h" -#include "Voice.h" #include "Sync.h" #include "Log.h" @@ -35,7 +35,7 @@ const unsigned char COLOR_CODE = 3U; const unsigned int SILENCE_LENGTH = 9U; const unsigned int AMBE_LENGTH = 9U; -CVoice::CVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg) : +CXLXVoice::CXLXVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg) : m_indxFile(), m_ambeFile(), m_slot(slot), @@ -63,7 +63,7 @@ m_it() #endif } -CVoice::~CVoice() +CXLXVoice::~CXLXVoice() { for (std::vector::iterator it = m_data.begin(); it != m_data.end(); ++it) delete *it; @@ -77,7 +77,7 @@ CVoice::~CVoice() delete[] m_ambe; } -bool CVoice::open() +bool CXLXVoice::open() { FILE* fpindx = ::fopen(m_indxFile.c_str(), "rt"); if (fpindx == NULL) { @@ -130,7 +130,7 @@ bool CVoice::open() return true; } -void CVoice::linkedTo(unsigned int number, unsigned int room) +void CXLXVoice::linkedTo(unsigned int number, unsigned int room) { char letters[10U]; ::sprintf(letters, "%03u", number); @@ -158,7 +158,7 @@ void CVoice::linkedTo(unsigned int number, unsigned int room) createVoice(words); } -void CVoice::unlinked() +void CXLXVoice::unlinked() { std::vector words; words.push_back("notlinked"); @@ -166,7 +166,7 @@ void CVoice::unlinked() createVoice(words); } -void CVoice::createVoice(const std::vector& words) +void CXLXVoice::createVoice(const std::vector& words) { unsigned int ambeLength = 0U; for (std::vector::const_iterator it = words.begin(); it != words.end(); ++it) { @@ -273,7 +273,7 @@ void CVoice::createVoice(const std::vector& words) m_timer.start(); } -bool CVoice::read(CDMRData& data) +bool CXLXVoice::read(CDMRData& data) { if (m_status != VS_SENDING) return false; @@ -300,7 +300,7 @@ bool CVoice::read(CDMRData& data) return false; } -void CVoice::clock(unsigned int ms) +void CXLXVoice::clock(unsigned int ms) { m_timer.clock(ms); if (m_timer.isRunning() && m_timer.hasExpired()) { @@ -313,7 +313,7 @@ void CVoice::clock(unsigned int ms) } } -void CVoice::createHeaderTerminator(unsigned char type) +void CXLXVoice::createHeaderTerminator(unsigned char type) { CDMRData* data = new CDMRData; diff --git a/Voice.h b/XLXVoice.h similarity index 89% rename from Voice.h rename to XLXVoice.h index c27aadb..c3ec43b 100644 --- a/Voice.h +++ b/XLXVoice.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2017 by Jonathan Naylor G4KLX +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX * * 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 @@ -16,8 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if !defined(Voice_H) -#define Voice_H +#if !defined(XLXVoice_H) +#define XLXVoice_H #include "DMREmbeddedData.h" #include "StopWatch.h" @@ -40,10 +40,10 @@ struct CPositions { unsigned int m_length; }; -class CVoice { +class CXLXVoice { public: - CVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg); - ~CVoice(); + CXLXVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg); + ~CXLXVoice(); bool open(); From 0fef073c13044343782553749f995106aba1d8cc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 3 Apr 2020 16:54:35 +0100 Subject: [PATCH 08/27] Add dynamic TG voice prompts and status TG. --- Conf.cpp | 80 +++++---- Conf.h | 1 + DMRGateway.cpp | 169 ++++++++++-------- DMRGateway.h | 13 +- DMRGateway.ini | 4 +- DMRGateway.vcxproj | 2 + DMRGateway.vcxproj.filters | 6 + DynVoice.cpp | 345 +++++++++++++++++++++++++++++++++++++ DynVoice.h | 81 +++++++++ Makefile | 6 +- RewriteDynTGNet.cpp | 4 +- RewriteDynTGRF.cpp | 50 ++++-- RewriteDynTGRF.h | 5 +- Version.h | 2 +- XLXVoice.cpp | 20 +-- XLXVoice.h | 14 +- 16 files changed, 651 insertions(+), 151 deletions(-) create mode 100644 DynVoice.cpp create mode 100644 DynVoice.h diff --git a/Conf.cpp b/Conf.cpp index 6e966dd..bf020ef 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -410,14 +410,16 @@ bool CConf::read() char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); - char* p5 = ::strtok(NULL, " \r\n"); - if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + char* p5 = ::strtok(NULL, ", "); + char* p6 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; - rewrite.m_slot = ::atoi(p1); - rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_toTG = ::atoi(p4); - rewrite.m_range = ::atoi(p5); + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_statusTG = ::atoi(p4); + rewrite.m_toTG = ::atoi(p5); + rewrite.m_range = ::atoi(p6); m_dmrNetwork1TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -520,14 +522,16 @@ bool CConf::read() char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); - char* p5 = ::strtok(NULL, " \r\n"); - if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + char* p5 = ::strtok(NULL, ", "); + char* p6 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; - rewrite.m_slot = ::atoi(p1); - rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_toTG = ::atoi(p4); - rewrite.m_range = ::atoi(p5); + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_statusTG = ::atoi(p4); + rewrite.m_toTG = ::atoi(p5); + rewrite.m_range = ::atoi(p6); m_dmrNetwork2TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -630,14 +634,16 @@ bool CConf::read() char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); - char* p5 = ::strtok(NULL, " \r\n"); - if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + char* p5 = ::strtok(NULL, ", "); + char* p6 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; - rewrite.m_slot = ::atoi(p1); - rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_toTG = ::atoi(p4); - rewrite.m_range = ::atoi(p5); + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_statusTG = ::atoi(p4); + rewrite.m_toTG = ::atoi(p5); + rewrite.m_range = ::atoi(p6); m_dmrNetwork3TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -740,14 +746,16 @@ bool CConf::read() char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); - char* p5 = ::strtok(NULL, " \r\n"); - if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + char* p5 = ::strtok(NULL, ", "); + char* p6 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; - rewrite.m_slot = ::atoi(p1); - rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_toTG = ::atoi(p4); - rewrite.m_range = ::atoi(p5); + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_statusTG = ::atoi(p4); + rewrite.m_toTG = ::atoi(p5); + rewrite.m_range = ::atoi(p6); m_dmrNetwork4TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -850,14 +858,16 @@ bool CConf::read() char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); - char* p5 = ::strtok(NULL, " \r\n"); - if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL) { + char* p5 = ::strtok(NULL, ", "); + char* p6 = ::strtok(NULL, " \r\n"); + if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; - rewrite.m_slot = ::atoi(p1); - rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_toTG = ::atoi(p4); - rewrite.m_range = ::atoi(p5); + rewrite.m_slot = ::atoi(p1); + rewrite.m_fromTG = ::atoi(p2); + rewrite.m_discTG = ::atoi(p3); + rewrite.m_statusTG = ::atoi(p4); + rewrite.m_toTG = ::atoi(p5); + rewrite.m_range = ::atoi(p6); m_dmrNetwork5TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { diff --git a/Conf.h b/Conf.h index 1bbea8d..b73eb83 100644 --- a/Conf.h +++ b/Conf.h @@ -57,6 +57,7 @@ struct CTGDynRewriteStruct { unsigned int m_slot; unsigned int m_fromTG; unsigned int m_discTG; + unsigned int m_statusTG; unsigned int m_toTG; unsigned int m_range; }; diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 073f026..30ad189 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -370,48 +370,17 @@ int CDMRGateway::run() bool ruleTrace = m_conf.getRuleTrace(); LogInfo("Rule trace: %s", ruleTrace ? "yes" : "no"); - if (m_conf.getDMRNetwork1Enabled()) { - ret = createDMRNetwork1(); - if (!ret) - return 1; - } - - if (m_conf.getDMRNetwork2Enabled()) { - ret = createDMRNetwork2(); - if (!ret) - return 1; - } - - if (m_conf.getDMRNetwork3Enabled()) { - ret = createDMRNetwork3(); - if (!ret) - return 1; - } - - if (m_conf.getDMRNetwork4Enabled()) { - ret = createDMRNetwork4(); - if (!ret) - return 1; - } - - if (m_conf.getDMRNetwork5Enabled()) { - ret = createDMRNetwork5(); - if (!ret) - return 1; - } - if (m_conf.getXLXNetworkEnabled()) { ret = createXLXNetwork(); if (!ret) return 1; } - unsigned int rfTimeout = m_conf.getRFTimeout(); - unsigned int netTimeout = m_conf.getNetTimeout(); + CXLXVoice* xlxVoice = NULL; + CDynVoice* dynVoice = NULL; - CXLXVoice* voice = NULL; - if (m_conf.getVoiceEnabled() && m_xlxNetwork != NULL) { - std::string language = m_conf.getVoiceLanguage(); + if (m_conf.getVoiceEnabled()) { + std::string language = m_conf.getVoiceLanguage(); std::string directory = m_conf.getVoiceDirectory(); LogInfo("Voice Parameters"); @@ -419,14 +388,56 @@ int CDMRGateway::run() LogInfo(" Language: %s", language.c_str()); LogInfo(" Directory: %s", directory.c_str()); - voice = new CXLXVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG); - bool ret = voice->open(); + if (m_xlxNetwork != NULL) { + xlxVoice = new CXLXVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG); + bool ret = xlxVoice->open(); + if (!ret) { + delete xlxVoice; + xlxVoice = NULL; + } + } + + dynVoice = new CDynVoice(directory, language, m_repeater->getId()); + bool ret = dynVoice->open(); if (!ret) { - delete voice; - voice = NULL; + delete dynVoice; + dynVoice = NULL; } } + if (m_conf.getDMRNetwork1Enabled()) { + ret = createDMRNetwork1(dynVoice); + if (!ret) + return 1; + } + + if (m_conf.getDMRNetwork2Enabled()) { + ret = createDMRNetwork2(dynVoice); + if (!ret) + return 1; + } + + if (m_conf.getDMRNetwork3Enabled()) { + ret = createDMRNetwork3(dynVoice); + if (!ret) + return 1; + } + + if (m_conf.getDMRNetwork4Enabled()) { + ret = createDMRNetwork4(dynVoice); + if (!ret) + return 1; + } + + if (m_conf.getDMRNetwork5Enabled()) { + ret = createDMRNetwork5(dynVoice); + if (!ret) + return 1; + } + + unsigned int rfTimeout = m_conf.getRFTimeout(); + unsigned int netTimeout = m_conf.getNetTimeout(); + CTimer* timer[3U]; timer[1U] = new CTimer(1000U); timer[2U] = new CTimer(1000U); @@ -468,18 +479,18 @@ int CDMRGateway::run() writeXLXLink(m_xlxId, m_xlxReflector, m_xlxNetwork); char c = ('A' + (m_xlxReflector % 100U)) - 1U; LogMessage("XLX, Linking to reflector XLX%03u %c", m_xlxNumber, c); - if (voice != NULL) - voice->linkedTo(m_xlxNumber, m_xlxReflector); + if (xlxVoice != NULL) + xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector); } else if (m_xlxRoom >= 4001U && m_xlxRoom <= 4026U) { writeXLXLink(m_xlxId, m_xlxRoom, m_xlxNetwork); char c = ('A' + (m_xlxRoom % 100U)) - 1U; LogMessage("XLX, Linking to reflector XLX%03u %c", m_xlxNumber, c); - if (voice != NULL) - voice->linkedTo(m_xlxNumber, m_xlxRoom); + if (xlxVoice != NULL) + xlxVoice->linkedTo(m_xlxNumber, m_xlxRoom); m_xlxReflector = m_xlxRoom; } else { - if (voice != NULL) - voice->linkedTo(m_xlxNumber, 0U); + if (xlxVoice != NULL) + xlxVoice->linkedTo(m_xlxNumber, 0U); } m_xlxConnected = true; @@ -491,8 +502,8 @@ int CDMRGateway::run() } else if (!connected && m_xlxConnected) { LogMessage("XLX, Unlinking from XLX%03u due to loss of connection", m_xlxNumber); - if (voice != NULL) - voice->unlinked(); + if (xlxVoice != NULL) + xlxVoice->unlinked(); m_xlxConnected = false; m_xlxRelink.stop(); @@ -523,11 +534,11 @@ int CDMRGateway::run() } m_xlxReflector = m_xlxRoom; - if (voice != NULL) { + if (xlxVoice != NULL) { if (m_xlxReflector < 4001U || m_xlxReflector > 4026U) - voice->linkedTo(m_xlxNumber, 0U); + xlxVoice->linkedTo(m_xlxNumber, 0U); else - voice->linkedTo(m_xlxNumber, m_xlxReflector); + xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector); } } } @@ -580,16 +591,16 @@ int CDMRGateway::run() timer[slotNo]->setTimeout(rfTimeout); timer[slotNo]->start(); - if (voice != NULL) { + if (xlxVoice != NULL) { unsigned char type = data.getDataType(); if (type == DT_TERMINATOR_WITH_LC) { if (m_xlxConnected) { if (m_xlxReflector != 4000U) - voice->linkedTo(m_xlxNumber, m_xlxReflector); + xlxVoice->linkedTo(m_xlxNumber, m_xlxReflector); else - voice->linkedTo(m_xlxNumber, 0U); + xlxVoice->linkedTo(m_xlxNumber, 0U); } else { - voice->unlinked(); + xlxVoice->unlinked(); } } } @@ -1111,8 +1122,8 @@ int CDMRGateway::run() processHomePosition(); - if (voice != NULL) { - ret = voice->read(data); + if (xlxVoice != NULL) { + ret = xlxVoice->read(data); if (ret) { m_repeater->write(data); m_status[m_xlxSlot] = DMRGWS_XLXREFLECTOR; @@ -1121,6 +1132,12 @@ int CDMRGateway::run() } } + if (dynVoice != NULL) { + ret = dynVoice->read(data); + if (ret) + m_repeater->write(data); + } + unsigned int ms = stopWatch.elapsed(); stopWatch.start(); @@ -1149,8 +1166,11 @@ int CDMRGateway::run() if (m_xlxReflectors != NULL) m_xlxReflectors->clock(ms); - if (voice != NULL) - voice->clock(ms); + if (xlxVoice != NULL) + xlxVoice->clock(ms); + + if (dynVoice != NULL) + dynVoice->clock(ms); for (unsigned int i = 1U; i < 3U; i++) { timer[i]->clock(ms); @@ -1164,7 +1184,8 @@ int CDMRGateway::run() CThread::sleep(10U); } - delete voice; + delete xlxVoice; + delete dynVoice; m_repeater->close(); delete m_repeater; @@ -1233,7 +1254,7 @@ bool CDMRGateway::createMMDVM() return true; } -bool CDMRGateway::createDMRNetwork1() +bool CDMRGateway::createDMRNetwork1(CDynVoice* voice) { std::string address = m_conf.getDMRNetwork1Address(); unsigned int port = m_conf.getDMRNetwork1Port(); @@ -1337,10 +1358,10 @@ bool CDMRGateway::createDMRNetwork1() std::vector dynRewrites = m_conf.getDMRNetwork1TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr1Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); m_dmr1RFRewrites.push_back(rfRewriteDynTG); m_dmr1NetRewrites.push_back(netRewriteDynTG); @@ -1382,7 +1403,7 @@ bool CDMRGateway::createDMRNetwork1() return true; } -bool CDMRGateway::createDMRNetwork2() +bool CDMRGateway::createDMRNetwork2(CDynVoice* voice) { std::string address = m_conf.getDMRNetwork2Address(); unsigned int port = m_conf.getDMRNetwork2Port(); @@ -1486,10 +1507,10 @@ bool CDMRGateway::createDMRNetwork2() std::vector dynRewrites = m_conf.getDMRNetwork2TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr2Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); m_dmr2RFRewrites.push_back(rfRewriteDynTG); m_dmr2NetRewrites.push_back(netRewriteDynTG); @@ -1531,7 +1552,7 @@ bool CDMRGateway::createDMRNetwork2() return true; } -bool CDMRGateway::createDMRNetwork3() +bool CDMRGateway::createDMRNetwork3(CDynVoice* voice) { std::string address = m_conf.getDMRNetwork3Address(); unsigned int port = m_conf.getDMRNetwork3Port(); @@ -1635,10 +1656,10 @@ bool CDMRGateway::createDMRNetwork3() std::vector dynRewrites = m_conf.getDMRNetwork3TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr3Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); m_dmr3RFRewrites.push_back(rfRewriteDynTG); m_dmr3NetRewrites.push_back(netRewriteDynTG); @@ -1680,7 +1701,7 @@ bool CDMRGateway::createDMRNetwork3() return true; } -bool CDMRGateway::createDMRNetwork4() +bool CDMRGateway::createDMRNetwork4(CDynVoice* voice) { std::string address = m_conf.getDMRNetwork4Address(); unsigned int port = m_conf.getDMRNetwork4Port(); @@ -1784,10 +1805,10 @@ bool CDMRGateway::createDMRNetwork4() std::vector dynRewrites = m_conf.getDMRNetwork4TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr4Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); m_dmr4RFRewrites.push_back(rfRewriteDynTG); m_dmr4NetRewrites.push_back(netRewriteDynTG); @@ -1829,7 +1850,7 @@ bool CDMRGateway::createDMRNetwork4() return true; } -bool CDMRGateway::createDMRNetwork5() +bool CDMRGateway::createDMRNetwork5(CDynVoice* voice) { std::string address = m_conf.getDMRNetwork5Address(); unsigned int port = m_conf.getDMRNetwork5Port(); @@ -1933,10 +1954,10 @@ bool CDMRGateway::createDMRNetwork5() std::vector dynRewrites = m_conf.getDMRNetwork5TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr5Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_range, netRewriteDynTG); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); m_dmr5RFRewrites.push_back(rfRewriteDynTG); m_dmr5NetRewrites.push_back(netRewriteDynTG); diff --git a/DMRGateway.h b/DMRGateway.h index becc3a7..f8debbd 100644 --- a/DMRGateway.h +++ b/DMRGateway.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2019,2020 by Jonathan Naylor G4KLX * * 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 @@ -24,6 +24,7 @@ #include "DMRNetwork.h" #include "Reflectors.h" #include "RewriteTG.h" +#include "DynVoice.h" #include "Rewrite.h" #include "Timer.h" #include "Conf.h" @@ -106,11 +107,11 @@ private: std::vector m_dmr5Passalls; bool createMMDVM(); - bool createDMRNetwork1(); - bool createDMRNetwork2(); - bool createDMRNetwork3(); - bool createDMRNetwork4(); - bool createDMRNetwork5(); + bool createDMRNetwork1(CDynVoice* voice); + bool createDMRNetwork2(CDynVoice* voice); + bool createDMRNetwork3(CDynVoice* voice); + bool createDMRNetwork4(CDynVoice* voice); + bool createDMRNetwork5(CDynVoice* voice); bool createXLXNetwork(); bool linkXLX(unsigned int number); diff --git a/DMRGateway.ini b/DMRGateway.ini index b888949..6789f4e 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -54,7 +54,7 @@ UserControl=1 # BrandMeister [DMR Network 1] -Enabled=1 +Enabled=0 Name=BM Address=44.131.4.1 Port=62031 @@ -71,7 +71,7 @@ SrcRewrite=1,9990,1,9990,1 # Reflector status returns SrcRewrite=2,4000,2,9,1001 # Dynamic rewriting of slot 2 TGs 23500-23599 to TG9 to emulate reflector behaviour -TGDynRewrite=2,23500,4000,9,100 +TGDynRewrite=2,23500,4000,5000,9,100 # Pass all of the other private traffic on slot 1 and slot 2 PassAllPC=1 PassAllPC=2 diff --git a/DMRGateway.vcxproj b/DMRGateway.vcxproj index 3485b79..fb7a833 100644 --- a/DMRGateway.vcxproj +++ b/DMRGateway.vcxproj @@ -166,6 +166,7 @@ + @@ -210,6 +211,7 @@ + diff --git a/DMRGateway.vcxproj.filters b/DMRGateway.vcxproj.filters index 91c4c0a..63ad046 100644 --- a/DMRGateway.vcxproj.filters +++ b/DMRGateway.vcxproj.filters @@ -140,6 +140,9 @@ Header Files + + Header Files + @@ -262,5 +265,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/DynVoice.cpp b/DynVoice.cpp new file mode 100644 index 0000000..bb32dc0 --- /dev/null +++ b/DynVoice.cpp @@ -0,0 +1,345 @@ +/* +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX +* +* 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 "DMRSlotType.h" +#include "DMRFullLC.h" +#include "DynVoice.h" +#include "DMREMB.h" +#include "Sync.h" +#include "Log.h" + +#include +#include + +#include + +const unsigned char SILENCE[] = {0xACU, 0xAAU, 0x40U, 0x20U, 0x00U, 0x44U, 0x40U, 0x80U, 0x80U}; + +const unsigned char COLOR_CODE = 3U; + +const unsigned int SILENCE_LENGTH = 9U; +const unsigned int AMBE_LENGTH = 9U; + +CDynVoice::CDynVoice(const std::string& directory, const std::string& language, unsigned int id) : +m_indxFile(), +m_ambeFile(), +m_id(id), +m_slot(0U), +m_lc(), +m_embeddedLC(), +m_status(DYNVS_NONE), +m_timer(1000U, 1U), +m_stopWatch(), +m_seqNo(0U), +m_streamId(0U), +m_sent(0U), +m_ambe(NULL), +m_positions(), +m_data(), +m_it() +{ +#if defined(_WIN32) || defined(_WIN64) + m_indxFile = directory + "\\" + language + ".indx"; + m_ambeFile = directory + "\\" + language + ".ambe"; +#else + m_indxFile = directory + "/" + language + ".indx"; + m_ambeFile = directory + "/" + language + ".ambe"; +#endif +} + +CDynVoice::~CDynVoice() +{ + for (std::vector::iterator it = m_data.begin(); it != m_data.end(); ++it) + delete *it; + + for (std::unordered_map::iterator it = m_positions.begin(); it != m_positions.end(); ++it) + delete it->second; + + m_data.clear(); + m_positions.clear(); + + delete[] m_ambe; +} + +void CDynVoice::setSlotAndTG(unsigned int slot, unsigned int tg) +{ + m_slot = slot; + + m_lc.setFLCO(FLCO_GROUP); + m_lc.setSrcId(m_id); + m_lc.setDstId(tg); + + m_embeddedLC.setLC(m_lc); +} + +bool CDynVoice::open() +{ + FILE* fpindx = ::fopen(m_indxFile.c_str(), "rt"); + if (fpindx == NULL) { + LogError("Unable to open the index file - %s", m_indxFile.c_str()); + return false; + } + + struct stat statStruct; + int ret = ::stat(m_ambeFile.c_str(), &statStruct); + if (ret != 0) { + LogError("Unable to stat the AMBE file - %s", m_ambeFile.c_str()); + ::fclose(fpindx); + return false; + } + + FILE* fpambe = ::fopen(m_ambeFile.c_str(), "rb"); + if (fpambe == NULL) { + LogError("Unable to open the AMBE file - %s", m_ambeFile.c_str()); + ::fclose(fpindx); + return false; + } + + m_ambe = new unsigned char[statStruct.st_size]; + + size_t sizeRead = ::fread(m_ambe, 1U, statStruct.st_size, fpambe); + if (sizeRead != 0U) { + char buffer[80U]; + while (::fgets(buffer, 80, fpindx) != NULL) { + char* p1 = ::strtok(buffer, "\t\r\n"); + char* p2 = ::strtok(NULL, "\t\r\n"); + char* p3 = ::strtok(NULL, "\t\r\n"); + + if (p1 != NULL && p2 != NULL && p3 != NULL) { + std::string symbol = std::string(p1); + unsigned int start = ::atoi(p2) * AMBE_LENGTH; + unsigned int length = ::atoi(p3) * AMBE_LENGTH; + + CDynPositions* pos = new CDynPositions; + pos->m_start = start; + pos->m_length = length; + + m_positions[symbol] = pos; + } + } + } + + ::fclose(fpindx); + ::fclose(fpambe); + + return true; +} + +void CDynVoice::linkedTo(unsigned int number) +{ + char letters[10U]; + ::sprintf(letters, "%u", number); + + std::vector words; + if (m_positions.count("linkedto") == 0U) { + words.push_back("linked"); + words.push_back("2"); + } else { + words.push_back("linkedto"); + } + + for (unsigned int i = 0U; letters[i] != '\0'; i++) + words.push_back(std::string(1U, letters[i])); + + createVoice(words); +} + +void CDynVoice::unlinked() +{ + std::vector words; + words.push_back("notlinked"); + + createVoice(words); +} + +void CDynVoice::createVoice(const std::vector& words) +{ + unsigned int ambeLength = 0U; + for (std::vector::const_iterator it = words.begin(); it != words.end(); ++it) { + if (m_positions.count(*it) > 0U) { + CDynPositions* position = m_positions.at(*it); + ambeLength += position->m_length; + } else { + LogWarning("Unable to find character/phrase \"%s\" in the index", (*it).c_str()); + } + } + + // Ensure that the AMBE is an integer number of DMR frames + if ((ambeLength % (3U * AMBE_LENGTH)) != 0U) { + unsigned int frames = ambeLength / (3U * AMBE_LENGTH); + frames++; + ambeLength = frames * (3U * AMBE_LENGTH); + } + + // Add space for silence before and after the voice + ambeLength += SILENCE_LENGTH * AMBE_LENGTH; + ambeLength += SILENCE_LENGTH * AMBE_LENGTH; + + unsigned char* ambeData = new unsigned char[ambeLength]; + + // Fill the AMBE data with silence + for (unsigned int i = 0U; i < ambeLength; i += AMBE_LENGTH) + ::memcpy(ambeData + i, SILENCE, AMBE_LENGTH); + + // Put offset in for silence at the beginning + unsigned int pos = SILENCE_LENGTH * AMBE_LENGTH; + for (std::vector::const_iterator it = words.begin(); it != words.end(); ++it) { + if (m_positions.count(*it) > 0U) { + CDynPositions* position = m_positions.at(*it); + unsigned int start = position->m_start; + unsigned int length = position->m_length; + ::memcpy(ambeData + pos, m_ambe + start, length); + pos += length; + } + } + + for (std::vector::iterator it = m_data.begin(); it != m_data.end(); ++it) + delete *it; + + m_data.clear(); + + m_streamId = ::rand() + 1U; + m_seqNo = 0U; + + createHeaderTerminator(DT_VOICE_LC_HEADER); + createHeaderTerminator(DT_VOICE_LC_HEADER); + createHeaderTerminator(DT_VOICE_LC_HEADER); + + unsigned char buffer[DMR_FRAME_LENGTH_BYTES]; + + unsigned int n = 0U; + for (unsigned int i = 0U; i < ambeLength; i += (3U * AMBE_LENGTH)) { + unsigned char* p = ambeData + i; + + CDMRData* data = new CDMRData; + + data->setSlotNo(m_slot); + data->setFLCO(FLCO_GROUP); + data->setSrcId(m_lc.getSrcId()); + data->setDstId(m_lc.getDstId()); + data->setN(n); + data->setSeqNo(m_seqNo++); + data->setStreamId(m_streamId); + + ::memcpy(buffer + 0U, p + 0U, AMBE_LENGTH); + ::memcpy(buffer + 9U, p + 9U, AMBE_LENGTH); + ::memcpy(buffer + 15U, p + 9U, AMBE_LENGTH); + ::memcpy(buffer + 24U, p + 18U, AMBE_LENGTH); + + if (n == 0U) { + CSync::addDMRAudioSync(buffer, true); + data->setDataType(DT_VOICE_SYNC); + } else { + unsigned char lcss = m_embeddedLC.getData(buffer, n); + + CDMREMB emb; + emb.setColorCode(COLOR_CODE); + emb.setPI(false); + emb.setLCSS(lcss); + emb.getData(buffer); + + data->setDataType(DT_VOICE); + } + + n++; + if (n >= 6U) + n = 0U; + + data->setData(buffer); + + m_data.push_back(data); + } + + createHeaderTerminator(DT_TERMINATOR_WITH_LC); + createHeaderTerminator(DT_TERMINATOR_WITH_LC); + + delete[] ambeData; + + m_status = DYNVS_WAITING; + m_timer.start(); +} + +bool CDynVoice::read(CDMRData& data) +{ + if (m_status != DYNVS_SENDING) + return false; + + unsigned int count = m_stopWatch.elapsed() / DMR_SLOT_TIME; + + if (m_sent < count) { + data = *(*m_it); + + ++m_sent; + ++m_it; + + if (m_it == m_data.end()) { + for (std::vector::iterator it = m_data.begin(); it != m_data.end(); ++it) + delete *it; + m_data.clear(); + m_timer.stop(); + m_status = DYNVS_NONE; + } + + return true; + } + + return false; +} + +void CDynVoice::clock(unsigned int ms) +{ + m_timer.clock(ms); + if (m_timer.isRunning() && m_timer.hasExpired()) { + if (m_status == DYNVS_WAITING) { + m_stopWatch.start(); + m_status = DYNVS_SENDING; + m_it = m_data.begin(); + m_sent = 0U; + } + } +} + +void CDynVoice::createHeaderTerminator(unsigned char type) +{ + CDMRData* data = new CDMRData; + + data->setSlotNo(m_slot); + data->setFLCO(FLCO_GROUP); + data->setSrcId(m_lc.getSrcId()); + data->setDstId(m_lc.getDstId()); + data->setDataType(type); + data->setN(0U); + data->setSeqNo(m_seqNo++); + data->setStreamId(m_streamId); + + unsigned char buffer[DMR_FRAME_LENGTH_BYTES]; + + CDMRFullLC fullLC; + fullLC.encode(m_lc, buffer, type); + + CDMRSlotType slotType; + slotType.setColorCode(COLOR_CODE); + slotType.setDataType(type); + slotType.getData(buffer); + + CSync::addDMRDataSync(buffer, true); + + data->setData(buffer); + + m_data.push_back(data); +} diff --git a/DynVoice.h b/DynVoice.h new file mode 100644 index 0000000..755145e --- /dev/null +++ b/DynVoice.h @@ -0,0 +1,81 @@ +/* +* Copyright (C) 2017,2020 by Jonathan Naylor G4KLX +* +* 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. +*/ + +#if !defined(DynVoice_H) +#define DynVoice_H + +#include "DMREmbeddedData.h" +#include "StopWatch.h" +#include "DMRData.h" +#include "DMRLC.h" +#include "Timer.h" + +#include +#include +#include + +enum DYNVOICE_STATUS { + DYNVS_NONE, + DYNVS_WAITING, + DYNVS_SENDING +}; + +struct CDynPositions { + unsigned int m_start; + unsigned int m_length; +}; + +class CDynVoice { +public: + CDynVoice(const std::string& directory, const std::string& language, unsigned int id); + ~CDynVoice(); + + void setSlotAndTG(unsigned int slot, unsigned int tg); + + bool open(); + + void linkedTo(unsigned int number); + void unlinked(); + + bool read(CDMRData& data); + + void clock(unsigned int ms); + +private: + std::string m_indxFile; + std::string m_ambeFile; + unsigned int m_id; + unsigned int m_slot; + CDMRLC m_lc; + CDMREmbeddedData m_embeddedLC; + DYNVOICE_STATUS m_status; + CTimer m_timer; + CStopWatch m_stopWatch; + unsigned int m_seqNo; + unsigned int m_streamId; + unsigned int m_sent; + unsigned char* m_ambe; + std::unordered_map m_positions; + std::vector m_data; + std::vector::const_iterator m_it; + + void createHeaderTerminator(unsigned char type); + void createVoice(const std::vector& words); +}; + +#endif diff --git a/Makefile b/Makefile index 4fc7e45..22656d1 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,9 @@ LIBS = -lpthread LDFLAGS = -g OBJECTS = BPTC19696.o Conf.o CRC.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREmbeddedData.o DMREMB.o DMRFullLC.o DMRGateway.o DMRLC.o DMRNetwork.o DMRSlotType.o \ - Golay2087.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.o Rewrite.o RewriteDstId.o RewriteDynTGNet.o \ - RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o \ - Utils.o XLXVoice.o + DynVoice.o Golay2087.o Hamming.o Log.o MMDVMNetwork.o PassAllPC.o PassAllTG.o QR1676.o Reflectors.o RepeaterProtocol.o Rewrite.o RewriteDstId.o \ + RewriteDynTGNet.o RewriteDynTGRF.o RewritePC.o RewriteSrc.o RewriteSrcId.o RewriteTG.o RewriteType.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o \ + Timer.o UDPSocket.o Utils.o XLXVoice.o all: DMRGateway diff --git a/RewriteDynTGNet.cpp b/RewriteDynTGNet.cpp index 8854e34..fde2ffc 100644 --- a/RewriteDynTGNet.cpp +++ b/RewriteDynTGNet.cpp @@ -40,8 +40,8 @@ CRewriteDynTGNet::~CRewriteDynTGNet() PROCESS_RESULT CRewriteDynTGNet::process(CDMRData& data, bool trace) { - FLCO flco = data.getFLCO(); - unsigned int dstId = data.getDstId(); + FLCO flco = data.getFLCO(); + unsigned int dstId = data.getDstId(); unsigned int slotNo = data.getSlotNo(); if (flco != FLCO_GROUP || slotNo != m_slot || dstId != m_currentTG) { diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index c0abf4b..dfd7bb5 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -24,7 +24,7 @@ #include #include -CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range, CRewriteDynTGNet* rewriteNet) : +CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int statusTG, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice) : CRewrite(), m_name(name), m_slot(slot), @@ -32,11 +32,16 @@ m_fromTGStart(fromTG), m_fromTGEnd(fromTG + range - 1U), m_toTG(toTG), m_discTG(discTG), +m_statusTG(statusTG), m_rewriteNet(rewriteNet), +m_voice(voice), m_currentTG(0U) { assert(slot == 1U || slot == 2U); assert(rewriteNet != NULL); + + if (voice != NULL) + voice->setSlotAndTG(slot, toTG); } CRewriteDynTGRF::~CRewriteDynTGRF() @@ -45,9 +50,10 @@ CRewriteDynTGRF::~CRewriteDynTGRF() PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) { - FLCO flco = data.getFLCO(); - unsigned int dstId = data.getDstId(); + FLCO flco = data.getFLCO(); + unsigned int dstId = data.getDstId(); unsigned int slotNo = data.getSlotNo(); + unsigned char type = data.getDataType(); if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_toTG && m_currentTG != 0U) { data.setDstId(m_currentTG); @@ -64,13 +70,17 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) if (trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_discTG); - m_rewriteNet->setCurrentTG(0U); - m_currentTG = 0U; + if (type == DT_TERMINATOR_WITH_LC) { + m_rewriteNet->setCurrentTG(0U); + m_currentTG = 0U; + if (m_voice != NULL) + m_voice->unlinked(); + } return RESULT_MATCHED; } - if (flco == FLCO_GROUP && slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { + if (slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { if (trace) { if (m_fromTGStart == m_fromTGEnd) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart); @@ -78,17 +88,37 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd); } - m_rewriteNet->setCurrentTG(dstId); - m_currentTG = dstId; + data.setFLCO(FLCO_GROUP); + + if (type == DT_TERMINATOR_WITH_LC) { + m_rewriteNet->setCurrentTG(dstId); + m_currentTG = dstId; + if (m_voice != NULL) + m_voice->linkedTo(dstId); + } return RESULT_MATCHED; } + if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_statusTG) { + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_statusTG); + + if (type == DT_TERMINATOR_WITH_LC && m_voice != NULL) { + if (m_currentTG == 0U) + m_voice->unlinked(); + else + m_voice->linkedTo(dstId); + } + + return RESULT_IGNORED; + } + if (trace) { if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discTG); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u or Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discTG, m_statusTG); else - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discTG); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u or Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discTG, m_statusTG); } return RESULT_UNMATCHED; diff --git a/RewriteDynTGRF.h b/RewriteDynTGRF.h index 695970c..388b835 100644 --- a/RewriteDynTGRF.h +++ b/RewriteDynTGRF.h @@ -19,6 +19,7 @@ #if !defined(REWRITEDYNTGRF_H) #define REWRITEDYNTGRF_H +#include "DynVoice.h" #include "Rewrite.h" #include "DMRData.h" @@ -28,7 +29,7 @@ class CRewriteDynTGRF : public CRewrite { public: - CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int range, CRewriteDynTGNet* rewriteNet); + CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int statusTG, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice); virtual ~CRewriteDynTGRF(); virtual PROCESS_RESULT process(CDMRData& data, bool trace); @@ -40,7 +41,9 @@ private: unsigned int m_fromTGEnd; unsigned int m_toTG; unsigned int m_discTG; + unsigned int m_statusTG; CRewriteDynTGNet* m_rewriteNet; + CDynVoice* m_voice; unsigned int m_currentTG; }; diff --git a/Version.h b/Version.h index 726b272..54b6d54 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200401"; +const char* VERSION = "20200403"; #endif diff --git a/XLXVoice.cpp b/XLXVoice.cpp index b0b6fe2..bcc3edb 100644 --- a/XLXVoice.cpp +++ b/XLXVoice.cpp @@ -41,7 +41,7 @@ m_ambeFile(), m_slot(slot), m_lc(FLCO_GROUP, id, tg), m_embeddedLC(), -m_status(VS_NONE), +m_status(XLXVS_NONE), m_timer(1000U, 1U), m_stopWatch(), m_seqNo(0U), @@ -68,7 +68,7 @@ CXLXVoice::~CXLXVoice() for (std::vector::iterator it = m_data.begin(); it != m_data.end(); ++it) delete *it; - for (std::unordered_map::iterator it = m_positions.begin(); it != m_positions.end(); ++it) + for (std::unordered_map::iterator it = m_positions.begin(); it != m_positions.end(); ++it) delete it->second; m_data.clear(); @@ -115,7 +115,7 @@ bool CXLXVoice::open() unsigned int start = ::atoi(p2) * AMBE_LENGTH; unsigned int length = ::atoi(p3) * AMBE_LENGTH; - CPositions* pos = new CPositions; + CXLXPositions* pos = new CXLXPositions; pos->m_start = start; pos->m_length = length; @@ -171,7 +171,7 @@ void CXLXVoice::createVoice(const std::vector& words) unsigned int ambeLength = 0U; for (std::vector::const_iterator it = words.begin(); it != words.end(); ++it) { if (m_positions.count(*it) > 0U) { - CPositions* position = m_positions.at(*it); + CXLXPositions* position = m_positions.at(*it); ambeLength += position->m_length; } else { LogWarning("Unable to find character/phrase \"%s\" in the index", (*it).c_str()); @@ -199,7 +199,7 @@ void CXLXVoice::createVoice(const std::vector& words) unsigned int pos = SILENCE_LENGTH * AMBE_LENGTH; for (std::vector::const_iterator it = words.begin(); it != words.end(); ++it) { if (m_positions.count(*it) > 0U) { - CPositions* position = m_positions.at(*it); + CXLXPositions* position = m_positions.at(*it); unsigned int start = position->m_start; unsigned int length = position->m_length; ::memcpy(ambeData + pos, m_ambe + start, length); @@ -269,13 +269,13 @@ void CXLXVoice::createVoice(const std::vector& words) delete[] ambeData; - m_status = VS_WAITING; + m_status = XLXVS_WAITING; m_timer.start(); } bool CXLXVoice::read(CDMRData& data) { - if (m_status != VS_SENDING) + if (m_status != XLXVS_SENDING) return false; unsigned int count = m_stopWatch.elapsed() / DMR_SLOT_TIME; @@ -291,7 +291,7 @@ bool CXLXVoice::read(CDMRData& data) delete *it; m_data.clear(); m_timer.stop(); - m_status = VS_NONE; + m_status = XLXVS_NONE; } return true; @@ -304,9 +304,9 @@ void CXLXVoice::clock(unsigned int ms) { m_timer.clock(ms); if (m_timer.isRunning() && m_timer.hasExpired()) { - if (m_status == VS_WAITING) { + if (m_status == XLXVS_WAITING) { m_stopWatch.start(); - m_status = VS_SENDING; + m_status = XLXVS_SENDING; m_it = m_data.begin(); m_sent = 0U; } diff --git a/XLXVoice.h b/XLXVoice.h index c3ec43b..186d3f6 100644 --- a/XLXVoice.h +++ b/XLXVoice.h @@ -29,13 +29,13 @@ #include #include -enum VOICE_STATUS { - VS_NONE, - VS_WAITING, - VS_SENDING +enum XLXVOICE_STATUS { + XLXVS_NONE, + XLXVS_WAITING, + XLXVS_SENDING }; -struct CPositions { +struct CXLXPositions { unsigned int m_start; unsigned int m_length; }; @@ -60,14 +60,14 @@ private: unsigned int m_slot; CDMRLC m_lc; CDMREmbeddedData m_embeddedLC; - VOICE_STATUS m_status; + XLXVOICE_STATUS m_status; CTimer m_timer; CStopWatch m_stopWatch; unsigned int m_seqNo; unsigned int m_streamId; unsigned int m_sent; unsigned char* m_ambe; - std::unordered_map m_positions; + std::unordered_map m_positions; std::vector m_data; std::vector::const_iterator m_it; From 8f39ca9ecef574910a02733d1c59696e38e8fb10 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 5 Apr 2020 13:43:57 +0100 Subject: [PATCH 09/27] Fix reported bugs in the dynamic rewrite code. --- Conf.cpp | 20 ++++++++++---------- Conf.h | 4 ++-- DMRGateway.cpp | 20 ++++++++++---------- RewriteDynTGRF.cpp | 28 +++++++++++++++------------- RewriteDynTGRF.h | 6 +++--- Version.h | 2 +- 6 files changed, 41 insertions(+), 39 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index bf020ef..e714a31 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -416,8 +416,8 @@ bool CConf::read() CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_statusTG = ::atoi(p4); + rewrite.m_discPC = ::atoi(p3); + rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); m_dmrNetwork1TGDynRewrites.push_back(rewrite); @@ -528,8 +528,8 @@ bool CConf::read() CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_statusTG = ::atoi(p4); + rewrite.m_discPC = ::atoi(p3); + rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); m_dmrNetwork2TGDynRewrites.push_back(rewrite); @@ -640,8 +640,8 @@ bool CConf::read() CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_statusTG = ::atoi(p4); + rewrite.m_discPC = ::atoi(p3); + rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); m_dmrNetwork3TGDynRewrites.push_back(rewrite); @@ -752,8 +752,8 @@ bool CConf::read() CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_statusTG = ::atoi(p4); + rewrite.m_discPC = ::atoi(p3); + rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); m_dmrNetwork4TGDynRewrites.push_back(rewrite); @@ -864,8 +864,8 @@ bool CConf::read() CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); - rewrite.m_discTG = ::atoi(p3); - rewrite.m_statusTG = ::atoi(p4); + rewrite.m_discPC = ::atoi(p3); + rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); m_dmrNetwork5TGDynRewrites.push_back(rewrite); diff --git a/Conf.h b/Conf.h index b73eb83..59c4100 100644 --- a/Conf.h +++ b/Conf.h @@ -56,8 +56,8 @@ struct CSrcRewriteStruct { struct CTGDynRewriteStruct { unsigned int m_slot; unsigned int m_fromTG; - unsigned int m_discTG; - unsigned int m_statusTG; + unsigned int m_discPC; + unsigned int m_statusPC; unsigned int m_toTG; unsigned int m_range; }; diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 30ad189..4b9a302 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -1358,10 +1358,10 @@ bool CDMRGateway::createDMRNetwork1(CDynVoice* voice) std::vector dynRewrites = m_conf.getDMRNetwork1TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr1Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); m_dmr1RFRewrites.push_back(rfRewriteDynTG); m_dmr1NetRewrites.push_back(netRewriteDynTG); @@ -1507,10 +1507,10 @@ bool CDMRGateway::createDMRNetwork2(CDynVoice* voice) std::vector dynRewrites = m_conf.getDMRNetwork2TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr2Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); m_dmr2RFRewrites.push_back(rfRewriteDynTG); m_dmr2NetRewrites.push_back(netRewriteDynTG); @@ -1656,10 +1656,10 @@ bool CDMRGateway::createDMRNetwork3(CDynVoice* voice) std::vector dynRewrites = m_conf.getDMRNetwork3TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr3Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); m_dmr3RFRewrites.push_back(rfRewriteDynTG); m_dmr3NetRewrites.push_back(netRewriteDynTG); @@ -1805,10 +1805,10 @@ bool CDMRGateway::createDMRNetwork4(CDynVoice* voice) std::vector dynRewrites = m_conf.getDMRNetwork4TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr4Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); m_dmr4RFRewrites.push_back(rfRewriteDynTG); m_dmr4NetRewrites.push_back(netRewriteDynTG); @@ -1954,10 +1954,10 @@ bool CDMRGateway::createDMRNetwork5(CDynVoice* voice) std::vector dynRewrites = m_conf.getDMRNetwork5TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:TG%u) (status %u:TG%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discTG, (*it).m_slot, (*it).m_statusTG); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr5Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discTG, (*it).m_statusTG, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); m_dmr5RFRewrites.push_back(rfRewriteDynTG); m_dmr5NetRewrites.push_back(netRewriteDynTG); diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index dfd7bb5..1484b1e 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -24,15 +24,15 @@ #include #include -CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int statusTG, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice) : +CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discPC, unsigned int statusPC, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice) : CRewrite(), m_name(name), m_slot(slot), m_fromTGStart(fromTG), m_fromTGEnd(fromTG + range - 1U), m_toTG(toTG), -m_discTG(discTG), -m_statusTG(statusTG), +m_discPC(discPC), +m_statusPC(statusPC), m_rewriteNet(rewriteNet), m_voice(voice), m_currentTG(0U) @@ -66,9 +66,11 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) return RESULT_MATCHED; } - if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_discTG && m_currentTG != 0U) { + if (flco == FLCO_USER_USER && slotNo == m_slot && dstId == m_discPC && m_currentTG != 0U) { if (trace) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_discTG); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_discPC); + + data.setFLCO(FLCO_GROUP); if (type == DT_TERMINATOR_WITH_LC) { m_rewriteNet->setCurrentTG(0U); @@ -80,12 +82,12 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) return RESULT_MATCHED; } - if (slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { + if (flco == FLCO_USER_USER && slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { if (trace) { if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_fromTGStart); else - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u: matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd); } data.setFLCO(FLCO_GROUP); @@ -100,15 +102,15 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) return RESULT_MATCHED; } - if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_statusTG) { + if (flco == FLCO_USER_USER && slotNo == m_slot && dstId == m_statusPC) { if (trace) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_statusTG); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_statusPC); if (type == DT_TERMINATOR_WITH_LC && m_voice != NULL) { if (m_currentTG == 0U) m_voice->unlinked(); else - m_voice->linkedTo(dstId); + m_voice->linkedTo(m_currentTG); } return RESULT_IGNORED; @@ -116,9 +118,9 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) if (trace) { if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u or Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discTG, m_statusTG); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u or Dst=TG%u or Dst=%u or Dst=%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discPC, m_statusPC); else - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u-TG%u or Dst=TG%u or Dst=TG%u or Dst=TG%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discTG, m_statusTG); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u-%u or Dst=TG%u or Dst=%u or Dst=%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_fromTGEnd, m_toTG, m_discPC, m_statusPC); } return RESULT_UNMATCHED; diff --git a/RewriteDynTGRF.h b/RewriteDynTGRF.h index 388b835..17146f6 100644 --- a/RewriteDynTGRF.h +++ b/RewriteDynTGRF.h @@ -29,7 +29,7 @@ class CRewriteDynTGRF : public CRewrite { public: - CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discTG, unsigned int statusTG, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice); + CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discPC, unsigned int statusPC, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice); virtual ~CRewriteDynTGRF(); virtual PROCESS_RESULT process(CDMRData& data, bool trace); @@ -40,8 +40,8 @@ private: unsigned int m_fromTGStart; unsigned int m_fromTGEnd; unsigned int m_toTG; - unsigned int m_discTG; - unsigned int m_statusTG; + unsigned int m_discPC; + unsigned int m_statusPC; CRewriteDynTGNet* m_rewriteNet; CDynVoice* m_voice; unsigned int m_currentTG; diff --git a/Version.h b/Version.h index 54b6d54..6981bfa 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200403"; +const char* VERSION = "20200405"; #endif From efed75f1608fdacba5f3e4e22b4410f2c83c0bee Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 6 Apr 2020 16:00:55 +0100 Subject: [PATCH 10/27] Fix type rewriting bug. --- RewriteDynTGRF.cpp | 4 ++++ Version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index 1484b1e..d748862 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -72,6 +72,8 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) data.setFLCO(FLCO_GROUP); + processMessage(data); + if (type == DT_TERMINATOR_WITH_LC) { m_rewriteNet->setCurrentTG(0U); m_currentTG = 0U; @@ -92,6 +94,8 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) data.setFLCO(FLCO_GROUP); + processMessage(data); + if (type == DT_TERMINATOR_WITH_LC) { m_rewriteNet->setCurrentTG(dstId); m_currentTG = dstId; diff --git a/Version.h b/Version.h index 6981bfa..093d5d4 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200405"; +const char* VERSION = "20200406"; #endif From 6b470c92a7729e019649bccc9c70e2b5ab61e509 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 7 Apr 2020 23:03:27 +0100 Subject: [PATCH 11/27] Allow for excluded TGs. --- Conf.cpp | 50 +++++++++++++++-- Conf.h | 1 + DMRGateway.cpp | 133 ++++++++++++++++++++++++++++++++++----------- DMRGateway.h | 11 ++-- DMRGateway.ini | 4 +- DynVoice.cpp | 21 +++---- DynVoice.h | 4 +- RewriteDynTGRF.cpp | 14 +++-- RewriteDynTGRF.h | 4 +- Version.h | 2 +- 10 files changed, 178 insertions(+), 66 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index e714a31..1765a76 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -406,12 +406,16 @@ bool CConf::read() m_dmrNetwork1SrcRewrites.push_back(rewrite); } } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + std::vector p7; char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, ", "); - char* p6 = ::strtok(NULL, " \r\n"); + char* p6 = ::strtok(NULL, ", \r\n"); + char* p; + while ((p = ::strtok(NULL, ", \r\n")) != NULL) + p7.push_back(p); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); @@ -420,6 +424,10 @@ bool CConf::read() rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); + for (std::vector::const_iterator it = p7.cbegin(); it != p7.cend(); ++it) { + unsigned int tg = ::atoi(*it); + rewrite.m_exclTGs.push_back(tg); + } m_dmrNetwork1TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -518,12 +526,16 @@ bool CConf::read() m_dmrNetwork2SrcRewrites.push_back(rewrite); } } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + std::vector p7; char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, ", "); - char* p6 = ::strtok(NULL, " \r\n"); + char* p6 = ::strtok(NULL, ", \r\n"); + char* p; + while ((p = ::strtok(NULL, ", \r\n")) != NULL) + p7.push_back(p); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); @@ -532,6 +544,10 @@ bool CConf::read() rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); + for (std::vector::const_iterator it = p7.cbegin(); it != p7.cend(); ++it) { + unsigned int tg = ::atoi(*it); + rewrite.m_exclTGs.push_back(tg); + } m_dmrNetwork2TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -630,12 +646,16 @@ bool CConf::read() m_dmrNetwork3SrcRewrites.push_back(rewrite); } } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + std::vector p7; char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, ", "); - char* p6 = ::strtok(NULL, " \r\n"); + char* p6 = ::strtok(NULL, ", \r\n"); + char* p; + while ((p = ::strtok(NULL, ", \r\n")) != NULL) + p7.push_back(p); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); @@ -644,6 +664,10 @@ bool CConf::read() rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); + for (std::vector::const_iterator it = p7.cbegin(); it != p7.cend(); ++it) { + unsigned int tg = ::atoi(*it); + rewrite.m_exclTGs.push_back(tg); + } m_dmrNetwork3TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -742,12 +766,16 @@ bool CConf::read() m_dmrNetwork4SrcRewrites.push_back(rewrite); } } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + std::vector p7; char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, ", "); - char* p6 = ::strtok(NULL, " \r\n"); + char* p6 = ::strtok(NULL, ", \r\n"); + char* p; + while ((p = ::strtok(NULL, ", \r\n")) != NULL) + p7.push_back(p); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); @@ -756,6 +784,10 @@ bool CConf::read() rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); + for (std::vector::const_iterator it = p7.cbegin(); it != p7.cend(); ++it) { + unsigned int tg = ::atoi(*it); + rewrite.m_exclTGs.push_back(tg); + } m_dmrNetwork4TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { @@ -854,12 +886,16 @@ bool CConf::read() m_dmrNetwork5SrcRewrites.push_back(rewrite); } } else if (::strncmp(key, "TGDynRewrite", 12U) == 0) { + std::vector p7; char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); char* p4 = ::strtok(NULL, ", "); char* p5 = ::strtok(NULL, ", "); - char* p6 = ::strtok(NULL, " \r\n"); + char* p6 = ::strtok(NULL, ", \r\n"); + char* p; + while ((p = ::strtok(NULL, ", \r\n")) != NULL) + p7.push_back(p); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL && p5 != NULL && p6 != NULL) { CTGDynRewriteStruct rewrite; rewrite.m_slot = ::atoi(p1); @@ -868,6 +904,10 @@ bool CConf::read() rewrite.m_statusPC = ::atoi(p4); rewrite.m_toTG = ::atoi(p5); rewrite.m_range = ::atoi(p6); + for (std::vector::const_iterator it = p7.cbegin(); it != p7.cend(); ++it) { + unsigned int tg = ::atoi(*it); + rewrite.m_exclTGs.push_back(tg); + } m_dmrNetwork5TGDynRewrites.push_back(rewrite); } } else if (::strncmp(key, "IdRewrite", 9U) == 0) { diff --git a/Conf.h b/Conf.h index 59c4100..2df5ede 100644 --- a/Conf.h +++ b/Conf.h @@ -60,6 +60,7 @@ struct CTGDynRewriteStruct { unsigned int m_statusPC; unsigned int m_toTG; unsigned int m_range; + std::vector m_exclTGs; }; struct CIdRewriteStruct { diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 4b9a302..f76a071 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -180,7 +180,8 @@ m_dmr1Passalls(), m_dmr2Passalls(), m_dmr3Passalls(), m_dmr4Passalls(), -m_dmr5Passalls() +m_dmr5Passalls(), +m_dynVoices() { m_status = new DMRGW_STATUS[3U]; m_status[1U] = DMRGWS_NONE; @@ -201,10 +202,10 @@ CDMRGateway::~CDMRGateway() delete *it; for (std::vector::iterator it = m_dmr2NetRewrites.begin(); it != m_dmr2NetRewrites.end(); ++it) - delete *it; + delete *it; for (std::vector::iterator it = m_dmr2RFRewrites.begin(); it != m_dmr2RFRewrites.end(); ++it) - delete *it; + delete *it; for (std::vector::iterator it = m_dmr2SrcRewrites.begin(); it != m_dmr2SrcRewrites.end(); ++it) delete *it; @@ -251,6 +252,9 @@ CDMRGateway::~CDMRGateway() for (std::vector::iterator it = m_dmr5Passalls.begin(); it != m_dmr5Passalls.end(); ++it) delete *it; + for (std::vector::iterator it = m_dynVoices.begin(); it != m_dynVoices.end(); ++it) + delete* it; + delete m_rptRewrite; delete m_xlxRewrite; @@ -377,8 +381,6 @@ int CDMRGateway::run() } CXLXVoice* xlxVoice = NULL; - CDynVoice* dynVoice = NULL; - if (m_conf.getVoiceEnabled()) { std::string language = m_conf.getVoiceLanguage(); std::string directory = m_conf.getVoiceDirectory(); @@ -396,41 +398,34 @@ int CDMRGateway::run() xlxVoice = NULL; } } - - dynVoice = new CDynVoice(directory, language, m_repeater->getId()); - bool ret = dynVoice->open(); - if (!ret) { - delete dynVoice; - dynVoice = NULL; - } } if (m_conf.getDMRNetwork1Enabled()) { - ret = createDMRNetwork1(dynVoice); + ret = createDMRNetwork1(); if (!ret) return 1; } if (m_conf.getDMRNetwork2Enabled()) { - ret = createDMRNetwork2(dynVoice); + ret = createDMRNetwork2(); if (!ret) return 1; } if (m_conf.getDMRNetwork3Enabled()) { - ret = createDMRNetwork3(dynVoice); + ret = createDMRNetwork3(); if (!ret) return 1; } if (m_conf.getDMRNetwork4Enabled()) { - ret = createDMRNetwork4(dynVoice); + ret = createDMRNetwork4(); if (!ret) return 1; } if (m_conf.getDMRNetwork5Enabled()) { - ret = createDMRNetwork5(dynVoice); + ret = createDMRNetwork5(); if (!ret) return 1; } @@ -1132,8 +1127,8 @@ int CDMRGateway::run() } } - if (dynVoice != NULL) { - ret = dynVoice->read(data); + for (std::vector::iterator it = m_dynVoices.begin(); it != m_dynVoices.end(); ++it) { + ret = (*it)->read(data); if (ret) m_repeater->write(data); } @@ -1169,8 +1164,8 @@ int CDMRGateway::run() if (xlxVoice != NULL) xlxVoice->clock(ms); - if (dynVoice != NULL) - dynVoice->clock(ms); + for (std::vector::iterator it = m_dynVoices.begin(); it != m_dynVoices.end(); ++it) + (*it)->clock(ms); for (unsigned int i = 1U; i < 3U; i++) { timer[i]->clock(ms); @@ -1185,7 +1180,6 @@ int CDMRGateway::run() } delete xlxVoice; - delete dynVoice; m_repeater->close(); delete m_repeater; @@ -1254,7 +1248,7 @@ bool CDMRGateway::createMMDVM() return true; } -bool CDMRGateway::createDMRNetwork1(CDynVoice* voice) +bool CDMRGateway::createDMRNetwork1() { std::string address = m_conf.getDMRNetwork1Address(); unsigned int port = m_conf.getDMRNetwork1Port(); @@ -1360,8 +1354,23 @@ bool CDMRGateway::createDMRNetwork1(CDynVoice* voice) for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + CDynVoice* voice = NULL; + if (m_conf.getVoiceEnabled()) { + std::string language = m_conf.getVoiceLanguage(); + std::string directory = m_conf.getVoiceDirectory(); + + voice = new CDynVoice(directory, language, m_repeater->getId(), (*it).m_slot, (*it).m_toTG); + bool ret = voice->open(); + if (!ret) { + delete voice; + voice = NULL; + } else { + m_dynVoices.push_back(voice); + } + } + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr1Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr1Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, (*it).m_exclTGs, netRewriteDynTG, voice); m_dmr1RFRewrites.push_back(rfRewriteDynTG); m_dmr1NetRewrites.push_back(netRewriteDynTG); @@ -1403,7 +1412,7 @@ bool CDMRGateway::createDMRNetwork1(CDynVoice* voice) return true; } -bool CDMRGateway::createDMRNetwork2(CDynVoice* voice) +bool CDMRGateway::createDMRNetwork2() { std::string address = m_conf.getDMRNetwork2Address(); unsigned int port = m_conf.getDMRNetwork2Port(); @@ -1509,8 +1518,23 @@ bool CDMRGateway::createDMRNetwork2(CDynVoice* voice) for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + CDynVoice* voice = NULL; + if (m_conf.getVoiceEnabled()) { + std::string language = m_conf.getVoiceLanguage(); + std::string directory = m_conf.getVoiceDirectory(); + + voice = new CDynVoice(directory, language, m_repeater->getId(), (*it).m_slot, (*it).m_toTG); + bool ret = voice->open(); + if (!ret) { + delete voice; + voice = NULL; + } else { + m_dynVoices.push_back(voice); + } + } + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr2Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr2Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, (*it).m_exclTGs, netRewriteDynTG, voice); m_dmr2RFRewrites.push_back(rfRewriteDynTG); m_dmr2NetRewrites.push_back(netRewriteDynTG); @@ -1552,7 +1576,7 @@ bool CDMRGateway::createDMRNetwork2(CDynVoice* voice) return true; } -bool CDMRGateway::createDMRNetwork3(CDynVoice* voice) +bool CDMRGateway::createDMRNetwork3() { std::string address = m_conf.getDMRNetwork3Address(); unsigned int port = m_conf.getDMRNetwork3Port(); @@ -1658,8 +1682,23 @@ bool CDMRGateway::createDMRNetwork3(CDynVoice* voice) for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + CDynVoice* voice = NULL; + if (m_conf.getVoiceEnabled()) { + std::string language = m_conf.getVoiceLanguage(); + std::string directory = m_conf.getVoiceDirectory(); + + voice = new CDynVoice(directory, language, m_repeater->getId(), (*it).m_slot, (*it).m_toTG); + bool ret = voice->open(); + if (!ret) { + delete voice; + voice = NULL; + } else { + m_dynVoices.push_back(voice); + } + } + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr3Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr3Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, (*it).m_exclTGs, netRewriteDynTG, voice); m_dmr3RFRewrites.push_back(rfRewriteDynTG); m_dmr3NetRewrites.push_back(netRewriteDynTG); @@ -1701,7 +1740,7 @@ bool CDMRGateway::createDMRNetwork3(CDynVoice* voice) return true; } -bool CDMRGateway::createDMRNetwork4(CDynVoice* voice) +bool CDMRGateway::createDMRNetwork4() { std::string address = m_conf.getDMRNetwork4Address(); unsigned int port = m_conf.getDMRNetwork4Port(); @@ -1807,8 +1846,23 @@ bool CDMRGateway::createDMRNetwork4(CDynVoice* voice) for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + CDynVoice* voice = NULL; + if (m_conf.getVoiceEnabled()) { + std::string language = m_conf.getVoiceLanguage(); + std::string directory = m_conf.getVoiceDirectory(); + + voice = new CDynVoice(directory, language, m_repeater->getId(), (*it).m_slot, (*it).m_toTG); + bool ret = voice->open(); + if (!ret) { + delete voice; + voice = NULL; + } else { + m_dynVoices.push_back(voice); + } + } + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr4Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr4Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, (*it).m_exclTGs, netRewriteDynTG, voice); m_dmr4RFRewrites.push_back(rfRewriteDynTG); m_dmr4NetRewrites.push_back(netRewriteDynTG); @@ -1850,7 +1904,7 @@ bool CDMRGateway::createDMRNetwork4(CDynVoice* voice) return true; } -bool CDMRGateway::createDMRNetwork5(CDynVoice* voice) +bool CDMRGateway::createDMRNetwork5() { std::string address = m_conf.getDMRNetwork5Address(); unsigned int port = m_conf.getDMRNetwork5Port(); @@ -1956,8 +2010,23 @@ bool CDMRGateway::createDMRNetwork5(CDynVoice* voice) for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + CDynVoice* voice = NULL; + if (m_conf.getVoiceEnabled()) { + std::string language = m_conf.getVoiceLanguage(); + std::string directory = m_conf.getVoiceDirectory(); + + voice = new CDynVoice(directory, language, m_repeater->getId(), (*it).m_slot, (*it).m_toTG); + bool ret = voice->open(); + if (!ret) { + delete voice; + voice = NULL; + } else { + m_dynVoices.push_back(voice); + } + } + CRewriteDynTGNet* netRewriteDynTG = new CRewriteDynTGNet(m_dmr5Name, (*it).m_slot, (*it).m_toTG); - CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, netRewriteDynTG, voice); + CRewriteDynTGRF* rfRewriteDynTG = new CRewriteDynTGRF(m_dmr5Name, (*it).m_slot, (*it).m_fromTG, (*it).m_toTG, (*it).m_discPC, (*it).m_statusPC, (*it).m_range, (*it).m_exclTGs, netRewriteDynTG, voice); m_dmr5RFRewrites.push_back(rfRewriteDynTG); m_dmr5NetRewrites.push_back(netRewriteDynTG); diff --git a/DMRGateway.h b/DMRGateway.h index f8debbd..fd5c6b3 100644 --- a/DMRGateway.h +++ b/DMRGateway.h @@ -105,13 +105,14 @@ private: std::vector m_dmr3Passalls; std::vector m_dmr4Passalls; std::vector m_dmr5Passalls; + std::vector m_dynVoices; bool createMMDVM(); - bool createDMRNetwork1(CDynVoice* voice); - bool createDMRNetwork2(CDynVoice* voice); - bool createDMRNetwork3(CDynVoice* voice); - bool createDMRNetwork4(CDynVoice* voice); - bool createDMRNetwork5(CDynVoice* voice); + bool createDMRNetwork1(); + bool createDMRNetwork2(); + bool createDMRNetwork3(); + bool createDMRNetwork4(); + bool createDMRNetwork5(); bool createXLXNetwork(); bool linkXLX(unsigned int number); diff --git a/DMRGateway.ini b/DMRGateway.ini index 6789f4e..bc8a390 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -70,8 +70,8 @@ TypeRewrite=1,9990,1,9990 SrcRewrite=1,9990,1,9990,1 # Reflector status returns SrcRewrite=2,4000,2,9,1001 -# Dynamic rewriting of slot 2 TGs 23500-23599 to TG9 to emulate reflector behaviour -TGDynRewrite=2,23500,4000,5000,9,100 +# Dynamic rewriting of slot 2 TGs 90-999999 to TG9 to emulate reflector behaviour +TGDynRewrite=2,90,4000,5000,9,999909,4000,5000,9900 # Pass all of the other private traffic on slot 1 and slot 2 PassAllPC=1 PassAllPC=2 diff --git a/DynVoice.cpp b/DynVoice.cpp index bb32dc0..380a890 100644 --- a/DynVoice.cpp +++ b/DynVoice.cpp @@ -35,11 +35,11 @@ const unsigned char COLOR_CODE = 3U; const unsigned int SILENCE_LENGTH = 9U; const unsigned int AMBE_LENGTH = 9U; -CDynVoice::CDynVoice(const std::string& directory, const std::string& language, unsigned int id) : +CDynVoice::CDynVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg) : m_indxFile(), m_ambeFile(), m_id(id), -m_slot(0U), +m_slot(slot), m_lc(), m_embeddedLC(), m_status(DYNVS_NONE), @@ -60,6 +60,12 @@ m_it() m_indxFile = directory + "/" + language + ".indx"; m_ambeFile = directory + "/" + language + ".ambe"; #endif + + m_lc.setFLCO(FLCO_GROUP); + m_lc.setSrcId(id); + m_lc.setDstId(tg); + + m_embeddedLC.setLC(m_lc); } CDynVoice::~CDynVoice() @@ -76,17 +82,6 @@ CDynVoice::~CDynVoice() delete[] m_ambe; } -void CDynVoice::setSlotAndTG(unsigned int slot, unsigned int tg) -{ - m_slot = slot; - - m_lc.setFLCO(FLCO_GROUP); - m_lc.setSrcId(m_id); - m_lc.setDstId(tg); - - m_embeddedLC.setLC(m_lc); -} - bool CDynVoice::open() { FILE* fpindx = ::fopen(m_indxFile.c_str(), "rt"); diff --git a/DynVoice.h b/DynVoice.h index 755145e..53b269f 100644 --- a/DynVoice.h +++ b/DynVoice.h @@ -42,11 +42,9 @@ struct CDynPositions { class CDynVoice { public: - CDynVoice(const std::string& directory, const std::string& language, unsigned int id); + CDynVoice(const std::string& directory, const std::string& language, unsigned int id, unsigned int slot, unsigned int tg); ~CDynVoice(); - void setSlotAndTG(unsigned int slot, unsigned int tg); - bool open(); void linkedTo(unsigned int number); diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index d748862..3829953 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -23,8 +23,9 @@ #include #include +#include -CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discPC, unsigned int statusPC, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice) : +CRewriteDynTGRF::CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discPC, unsigned int statusPC, unsigned int range, const std::vector& exclTGs, CRewriteDynTGNet* rewriteNet, CDynVoice* voice) : CRewrite(), m_name(name), m_slot(slot), @@ -33,15 +34,13 @@ m_fromTGEnd(fromTG + range - 1U), m_toTG(toTG), m_discPC(discPC), m_statusPC(statusPC), +m_exclTGs(exclTGs), m_rewriteNet(rewriteNet), m_voice(voice), m_currentTG(0U) { assert(slot == 1U || slot == 2U); assert(rewriteNet != NULL); - - if (voice != NULL) - voice->setSlotAndTG(slot, toTG); } CRewriteDynTGRF::~CRewriteDynTGRF() @@ -66,6 +65,13 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) return RESULT_MATCHED; } + if (flco == FLCO_GROUP && std::find(m_exclTGs.cbegin(), m_exclTGs.cend(), dstId) != m_exclTGs.cend()) { + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_slot, dstId); + + return RESULT_UNMATCHED; + } + if (flco == FLCO_USER_USER && slotNo == m_slot && dstId == m_discPC && m_currentTG != 0U) { if (trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_discPC); diff --git a/RewriteDynTGRF.h b/RewriteDynTGRF.h index 17146f6..8e6a8d4 100644 --- a/RewriteDynTGRF.h +++ b/RewriteDynTGRF.h @@ -26,10 +26,11 @@ #include "RewriteDynTGNet.h" #include +#include class CRewriteDynTGRF : public CRewrite { public: - CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discPC, unsigned int statusPC, unsigned int range, CRewriteDynTGNet* rewriteNet, CDynVoice* voice); + CRewriteDynTGRF(const std::string& name, unsigned int slot, unsigned int fromTG, unsigned int toTG, unsigned int discPC, unsigned int statusPC, unsigned int range, const std::vector& exclTGs, CRewriteDynTGNet* rewriteNet, CDynVoice* voice); virtual ~CRewriteDynTGRF(); virtual PROCESS_RESULT process(CDMRData& data, bool trace); @@ -42,6 +43,7 @@ private: unsigned int m_toTG; unsigned int m_discPC; unsigned int m_statusPC; + std::vector m_exclTGs; CRewriteDynTGNet* m_rewriteNet; CDynVoice* m_voice; unsigned int m_currentTG; diff --git a/Version.h b/Version.h index 093d5d4..cfa3710 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200406"; +const char* VERSION = "20200407"; #endif From 3b7083b373c8112f987abbfe24edb44c6a8d10e2 Mon Sep 17 00:00:00 2001 From: John doe Date: Wed, 8 Apr 2020 16:21:35 +0900 Subject: [PATCH 12/27] Extended TypeRewrite --- Conf.cpp | 20 +++++++++++++++----- Conf.h | 1 + RewriteType.cpp | 37 +++++++++++++++++++++++++++---------- RewriteType.h | 8 +++++--- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index e714a31..a38836a 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -381,13 +381,15 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL) { CTypeRewriteStruct rewrite; rewrite.m_fromSlot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); rewrite.m_toSlot = ::atoi(p3); rewrite.m_toId = ::atoi(p4); + char* p5 = ::strtok(NULL, " \r\n"); + rewrite.m_range = p5 != NULL ? ::atoi(p5) : 1; m_dmrNetwork1TypeRewrites.push_back(rewrite); } } else if (::strncmp(key, "SrcRewrite", 10U) == 0) { @@ -493,13 +495,15 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL) { CTypeRewriteStruct rewrite; rewrite.m_fromSlot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); rewrite.m_toSlot = ::atoi(p3); rewrite.m_toId = ::atoi(p4); + char* p5 = ::strtok(NULL, " \r\n"); + rewrite.m_range = p5 != NULL ? ::atoi(p5) : 1; m_dmrNetwork2TypeRewrites.push_back(rewrite); } } else if (::strncmp(key, "SrcRewrite", 10U) == 0) { @@ -605,13 +609,15 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL) { CTypeRewriteStruct rewrite; rewrite.m_fromSlot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); rewrite.m_toSlot = ::atoi(p3); rewrite.m_toId = ::atoi(p4); + char* p5 = ::strtok(NULL, " \r\n"); + rewrite.m_range = p5 != NULL ? ::atoi(p5) : 1; m_dmrNetwork3TypeRewrites.push_back(rewrite); } } else if (::strncmp(key, "SrcRewrite", 10U) == 0) { @@ -717,13 +723,15 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL) { CTypeRewriteStruct rewrite; rewrite.m_fromSlot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); rewrite.m_toSlot = ::atoi(p3); rewrite.m_toId = ::atoi(p4); + char* p5 = ::strtok(NULL, " \r\n"); + rewrite.m_range = p5 != NULL ? ::atoi(p5) : 1; m_dmrNetwork4TypeRewrites.push_back(rewrite); } } else if (::strncmp(key, "SrcRewrite", 10U) == 0) { @@ -829,13 +837,15 @@ bool CConf::read() char* p1 = ::strtok(value, ", "); char* p2 = ::strtok(NULL, ", "); char* p3 = ::strtok(NULL, ", "); - char* p4 = ::strtok(NULL, " \r\n"); + char* p4 = ::strtok(NULL, ", \r\n"); if (p1 != NULL && p2 != NULL && p3 != NULL && p4 != NULL) { CTypeRewriteStruct rewrite; rewrite.m_fromSlot = ::atoi(p1); rewrite.m_fromTG = ::atoi(p2); rewrite.m_toSlot = ::atoi(p3); rewrite.m_toId = ::atoi(p4); + char* p5 = ::strtok(NULL, " \r\n"); + rewrite.m_range = p5 != NULL ? ::atoi(p5) : 1; m_dmrNetwork5TypeRewrites.push_back(rewrite); } } else if (::strncmp(key, "SrcRewrite", 10U) == 0) { diff --git a/Conf.h b/Conf.h index 59c4100..c151dc1 100644 --- a/Conf.h +++ b/Conf.h @@ -43,6 +43,7 @@ struct CTypeRewriteStruct { unsigned int m_fromTG; unsigned int m_toSlot; unsigned int m_toId; + unsigned int m_range; }; struct CSrcRewriteStruct { diff --git a/RewriteType.cpp b/RewriteType.cpp index c069145..00fafdf 100644 --- a/RewriteType.cpp +++ b/RewriteType.cpp @@ -24,13 +24,15 @@ #include #include -CRewriteType::CRewriteType(const std::string& name, unsigned int fromSlot, unsigned int fromTG, unsigned int toSlot, unsigned int toId) : +CRewriteType::CRewriteType(const std::string& name, unsigned int fromSlot, unsigned int fromTG, unsigned int toSlot, unsigned int toId, unsigned int range) : CRewrite(), m_name(name), m_fromSlot(fromSlot), -m_fromTG(fromTG), +m_fromTGStart(fromTG), +m_fromTGEnd(fromTG + range - 1U), m_toSlot(toSlot), -m_toId(toId) +m_toIdStart(toId), +m_toIdEnd(toId + range - 1U) { assert(fromSlot == 1U || fromSlot == 2U); assert(toSlot == 1U || toSlot == 2U); @@ -46,23 +48,38 @@ PROCESS_RESULT CRewriteType::process(CDMRData& data, bool trace) unsigned int dstId = data.getDstId(); unsigned int slotNo = data.getSlotNo(); - if (flco != FLCO_GROUP || slotNo != m_fromSlot || dstId != m_fromTG) { - if (trace) - LogDebug("Rule Trace,\tRewriteType %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTG); - + if (flco != FLCO_GROUP || slotNo != m_fromSlot || dstId < m_fromTGStart || dstId > m_fromTGEnd) { + if (trace) { + if (m_fromTGStart == m_fromTGEnd) + LogDebug("Rule Trace,\tRewriteType from \"%s\" Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + else + LogDebug("Rule Trace,\tRewriteType from \"%s\" Slot=%u Dst=TG%u-%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); + } return RESULT_UNMATCHED; } if (m_fromSlot != m_toSlot) data.setSlotNo(m_toSlot); - data.setDstId(m_toId); + if (m_fromTGStart != m_fromTGEnd) { + unsigned int newDstId = dstId + m_toIdStart - m_fromTGStart; + data.setDstId(newDstId); + } else + data.setDstId(toId); data.setFLCO(FLCO_USER_USER); processMessage(data); - if (trace) - LogDebug("Rule Trace,\tRewriteType %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_fromSlot, m_fromTG); + if (trace) { + if (m_fromTGStart == m_fromTGEnd) + LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + else + LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); + if (m_toIdStart == m_toIdEnd) + LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_toSlot, m_toIdStart); + else + LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdTGEnd); + } return RESULT_MATCHED; } diff --git a/RewriteType.h b/RewriteType.h index 70399d0..07e7edd 100644 --- a/RewriteType.h +++ b/RewriteType.h @@ -26,7 +26,7 @@ class CRewriteType : public CRewrite { public: - CRewriteType(const std::string& name, unsigned int fromSlot, unsigned int fromTG, unsigned int toSlot, unsigned int toId); + CRewriteType(const std::string& name, unsigned int fromSlot, unsigned int fromTG, unsigned int toSlot, unsigned int toId, unsigned int range); virtual ~CRewriteType(); virtual PROCESS_RESULT process(CDMRData& data, bool trace); @@ -34,9 +34,11 @@ public: private: std::string m_name; unsigned int m_fromSlot; - unsigned int m_fromTG; + unsigned int m_fromTGStart; + unsigned int m_fromTGEnd; unsigned int m_toSlot; - unsigned int m_toId; + unsigned int m_toIdStart; + unsigned int m_toIdEnd; }; From a3884c2150865d1965bc407536d943e1182da8c3 Mon Sep 17 00:00:00 2001 From: John doe Date: Wed, 8 Apr 2020 16:48:43 +0900 Subject: [PATCH 13/27] Using in DMRGateway.cpp --- DMRGateway.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 4b9a302..b7774a5 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -1337,9 +1337,12 @@ bool CDMRGateway::createDMRNetwork1(CDynVoice* voice) std::vector typeRewrites = m_conf.getDMRNetwork1TypeRewrites(); for (std::vector::const_iterator it = typeRewrites.begin(); it != typeRewrites.end(); ++it) { - LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + if ((*it).m_range == 1) + LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + else + LogInfo(" Rewrite RF: %u:TG%u-%u -> %u:%u-%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_toSlot, (*it).m_toId, (*it).m_toId + (*it).m_range - 1U); - CRewriteType* rewrite = new CRewriteType(m_dmr1Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + CRewriteType* rewrite = new CRewriteType(m_dmr1Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId, (*it).m_range); m_dmr1RFRewrites.push_back(rewrite); } @@ -1486,9 +1489,12 @@ bool CDMRGateway::createDMRNetwork2(CDynVoice* voice) std::vector typeRewrites = m_conf.getDMRNetwork2TypeRewrites(); for (std::vector::const_iterator it = typeRewrites.begin(); it != typeRewrites.end(); ++it) { - LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + if ((*it).m_range == 1) + LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + else + LogInfo(" Rewrite RF: %u:TG%u-%u -> %u:%u-%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_toSlot, (*it).m_toId, (*it).m_toId + (*it).m_range - 1U); - CRewriteType* rewrite = new CRewriteType(m_dmr2Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + CRewriteType* rewrite = new CRewriteType(m_dmr2Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId, (*it).m_range); m_dmr2RFRewrites.push_back(rewrite); } @@ -1635,9 +1641,12 @@ bool CDMRGateway::createDMRNetwork3(CDynVoice* voice) std::vector typeRewrites = m_conf.getDMRNetwork3TypeRewrites(); for (std::vector::const_iterator it = typeRewrites.begin(); it != typeRewrites.end(); ++it) { - LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + if ((*it).m_range == 1) + LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + else + LogInfo(" Rewrite RF: %u:TG%u-%u -> %u:%u-%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_toSlot, (*it).m_toId, (*it).m_toId + (*it).m_range - 1U); - CRewriteType* rewrite = new CRewriteType(m_dmr3Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + CRewriteType* rewrite = new CRewriteType(m_dmr3Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId, (*it).m_range); m_dmr3RFRewrites.push_back(rewrite); } @@ -1784,9 +1793,12 @@ bool CDMRGateway::createDMRNetwork4(CDynVoice* voice) std::vector typeRewrites = m_conf.getDMRNetwork4TypeRewrites(); for (std::vector::const_iterator it = typeRewrites.begin(); it != typeRewrites.end(); ++it) { - LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + if ((*it).m_range == 1) + LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + else + LogInfo(" Rewrite RF: %u:TG%u-%u -> %u:%u-%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_toSlot, (*it).m_toId, (*it).m_toId + (*it).m_range - 1U); - CRewriteType* rewrite = new CRewriteType(m_dmr4Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + CRewriteType* rewrite = new CRewriteType(m_dmr4Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId, (*it).m_range); m_dmr4RFRewrites.push_back(rewrite); } @@ -1933,9 +1945,12 @@ bool CDMRGateway::createDMRNetwork5(CDynVoice* voice) std::vector typeRewrites = m_conf.getDMRNetwork5TypeRewrites(); for (std::vector::const_iterator it = typeRewrites.begin(); it != typeRewrites.end(); ++it) { - LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + if ((*it).m_range == 1) + LogInfo(" Rewrite RF: %u:TG%u -> %u:%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + else + LogInfo(" Rewrite RF: %u:TG%u-%u -> %u:%u-%u", (*it).m_fromSlot, (*it).m_fromTG, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_toSlot, (*it).m_toId, (*it).m_toId + (*it).m_range - 1U); - CRewriteType* rewrite = new CRewriteType(m_dmr5Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId); + CRewriteType* rewrite = new CRewriteType(m_dmr5Name, (*it).m_fromSlot, (*it).m_fromTG, (*it).m_toSlot, (*it).m_toId, (*it).m_range); m_dmr5RFRewrites.push_back(rewrite); } From 1bfaf84dc8570a835d61de457fd708f649d42db6 Mon Sep 17 00:00:00 2001 From: John doe Date: Wed, 8 Apr 2020 17:11:54 +0900 Subject: [PATCH 14/27] . --- RewriteType.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/RewriteType.cpp b/RewriteType.cpp index 00fafdf..73e809d 100644 --- a/RewriteType.cpp +++ b/RewriteType.cpp @@ -61,11 +61,10 @@ PROCESS_RESULT CRewriteType::process(CDMRData& data, bool trace) if (m_fromSlot != m_toSlot) data.setSlotNo(m_toSlot); - if (m_fromTGStart != m_fromTGEnd) { + if (m_fromTGStart != m_toIdStart) { unsigned int newDstId = dstId + m_toIdStart - m_fromTGStart; data.setDstId(newDstId); - } else - data.setDstId(toId); + } data.setFLCO(FLCO_USER_USER); processMessage(data); From ec0b11c8e14908280e9d72e094fa17f5a565686b Mon Sep 17 00:00:00 2001 From: John doe Date: Wed, 8 Apr 2020 17:19:51 +0900 Subject: [PATCH 15/27] fix --- RewriteType.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RewriteType.cpp b/RewriteType.cpp index 73e809d..602c62e 100644 --- a/RewriteType.cpp +++ b/RewriteType.cpp @@ -71,13 +71,13 @@ PROCESS_RESULT CRewriteType::process(CDMRData& data, bool trace) if (trace) { if (m_fromTGStart == m_fromTGEnd) - LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart); + LogDebug("Rule Trace,\tRewriteType from \"%s\" Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart); else - LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); + LogDebug("Rule Trace,\tRewriteType from \"%s\" Slot=%u Dst=TG%u-%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); if (m_toIdStart == m_toIdEnd) LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_toSlot, m_toIdStart); else - LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdTGEnd); + LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdEnd); } return RESULT_MATCHED; From f4dd4968ae98b30f4d6b7bf56c5ca75a32eb61bd Mon Sep 17 00:00:00 2001 From: John doe Date: Wed, 8 Apr 2020 17:21:51 +0900 Subject: [PATCH 16/27] fix err --- RewriteType.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RewriteType.cpp b/RewriteType.cpp index 602c62e..0ceb1da 100644 --- a/RewriteType.cpp +++ b/RewriteType.cpp @@ -75,9 +75,9 @@ PROCESS_RESULT CRewriteType::process(CDMRData& data, bool trace) else LogDebug("Rule Trace,\tRewriteType from \"%s\" Slot=%u Dst=TG%u-%u: not matched", m_name.c_str(), m_fromSlot, m_fromTGStart, m_fromTGEnd); if (m_toIdStart == m_toIdEnd) - LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_toSlot, m_toIdStart); + LogDebug("Rule Trace,\tRewriteType to \"\%s\" Slot=%u Dst=%u: matched", m_name.c_str(), m_toSlot, m_toIdStart); else - LogDebug("Rule Trace,\tRewriteType to \"\s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdEnd); + LogDebug("Rule Trace,\tRewriteType to \"\%s\" Slot=%u Dst=%u-%u: matched", m_name.c_str(), m_toSlot, m_toIdStart, m_toIdEnd); } return RESULT_MATCHED; From dafac8c0257649fe133c494d2006f0f1c0d2f4df Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 8 Apr 2020 17:28:43 +0100 Subject: [PATCH 17/27] Fix the order of processing the dynamic rewrite rules. --- DMRGateway.cpp | 10 +++--- DMRGateway.ini | 2 +- RewriteDynTGRF.cpp | 84 +++++++++++++++++++++++++--------------------- Version.h | 2 +- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/DMRGateway.cpp b/DMRGateway.cpp index f76a071..25e54cd 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -1352,7 +1352,7 @@ bool CDMRGateway::createDMRNetwork1() std::vector dynRewrites = m_conf.getDMRNetwork1TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u) (%u exclusions)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC, (*it).m_exclTGs.size()); CDynVoice* voice = NULL; if (m_conf.getVoiceEnabled()) { @@ -1516,7 +1516,7 @@ bool CDMRGateway::createDMRNetwork2() std::vector dynRewrites = m_conf.getDMRNetwork2TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u) (%u exclusions)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC, (*it).m_exclTGs.size()); CDynVoice* voice = NULL; if (m_conf.getVoiceEnabled()) { @@ -1680,7 +1680,7 @@ bool CDMRGateway::createDMRNetwork3() std::vector dynRewrites = m_conf.getDMRNetwork3TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u) (%u exclusions)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC, (*it).m_exclTGs.size()); CDynVoice* voice = NULL; if (m_conf.getVoiceEnabled()) { @@ -1844,7 +1844,7 @@ bool CDMRGateway::createDMRNetwork4() std::vector dynRewrites = m_conf.getDMRNetwork4TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u) (%u exclusions)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC, (*it).m_exclTGs.size()); CDynVoice* voice = NULL; if (m_conf.getVoiceEnabled()) { @@ -2008,7 +2008,7 @@ bool CDMRGateway::createDMRNetwork5() std::vector dynRewrites = m_conf.getDMRNetwork5TGDynRewrites(); for (std::vector::const_iterator it = dynRewrites.begin(); it != dynRewrites.end(); ++it) { - LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC); + LogInfo(" Dyn Rewrite: %u:TG%u-%u:TG%u <-> %u:TG%u (disc %u:%u) (status %u:%u) (%u exclusions)", (*it).m_slot, (*it).m_fromTG, (*it).m_slot, (*it).m_fromTG + (*it).m_range - 1U, (*it).m_slot, (*it).m_toTG, (*it).m_slot, (*it).m_discPC, (*it).m_slot, (*it).m_statusPC, (*it).m_exclTGs.size()); CDynVoice* voice = NULL; if (m_conf.getVoiceEnabled()) { diff --git a/DMRGateway.ini b/DMRGateway.ini index bc8a390..a0266e5 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -71,7 +71,7 @@ SrcRewrite=1,9990,1,9990,1 # Reflector status returns SrcRewrite=2,4000,2,9,1001 # Dynamic rewriting of slot 2 TGs 90-999999 to TG9 to emulate reflector behaviour -TGDynRewrite=2,90,4000,5000,9,999909,4000,5000,9900 +TGDynRewrite=2,90,4000,5000,9,999910,9900 # Pass all of the other private traffic on slot 1 and slot 2 PassAllPC=1 PassAllPC=2 diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index 3829953..805938c 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -54,43 +54,65 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) unsigned int slotNo = data.getSlotNo(); unsigned char type = data.getDataType(); - if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_toTG && m_currentTG != 0U) { - data.setDstId(m_currentTG); - - processMessage(data); - + if (flco == FLCO_GROUP && slotNo == m_slot && dstId == m_toTG) { if (trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_toTG); - return RESULT_MATCHED; + if (m_currentTG != 0U) { + data.setDstId(m_currentTG); + + processMessage(data); + + return RESULT_MATCHED; + } else { + return RESULT_IGNORED; + } } - if (flco == FLCO_GROUP && std::find(m_exclTGs.cbegin(), m_exclTGs.cend(), dstId) != m_exclTGs.cend()) { - if (trace) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: not matched", m_name.c_str(), m_slot, dstId); - - return RESULT_UNMATCHED; - } - - if (flco == FLCO_USER_USER && slotNo == m_slot && dstId == m_discPC && m_currentTG != 0U) { + if (slotNo == m_slot && dstId == m_discPC) { if (trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_discPC); - data.setFLCO(FLCO_GROUP); + if (m_currentTG != 0U) { + data.setFLCO(FLCO_GROUP); - processMessage(data); + processMessage(data); - if (type == DT_TERMINATOR_WITH_LC) { - m_rewriteNet->setCurrentTG(0U); - m_currentTG = 0U; - if (m_voice != NULL) - m_voice->unlinked(); + if (type == DT_TERMINATOR_WITH_LC) { + m_rewriteNet->setCurrentTG(0U); + m_currentTG = 0U; + if (m_voice != NULL) + m_voice->unlinked(); + } + + return RESULT_MATCHED; + } else { + return RESULT_IGNORED; } - - return RESULT_MATCHED; } - if (flco == FLCO_USER_USER && slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { + if (slotNo == m_slot && dstId == m_statusPC) { + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_statusPC); + + if (type == DT_TERMINATOR_WITH_LC && m_voice != NULL) { + if (m_currentTG == 0U) + m_voice->unlinked(); + else + m_voice->linkedTo(m_currentTG); + } + + return RESULT_IGNORED; + } + + if (std::find(m_exclTGs.cbegin(), m_exclTGs.cend(), dstId) != m_exclTGs.cend()) { + if (trace) + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, dstId); + + return RESULT_IGNORED; + } + + if (slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { if (trace) { if (m_fromTGStart == m_fromTGEnd) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_fromTGStart); @@ -112,20 +134,6 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) return RESULT_MATCHED; } - if (flco == FLCO_USER_USER && slotNo == m_slot && dstId == m_statusPC) { - if (trace) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, m_statusPC); - - if (type == DT_TERMINATOR_WITH_LC && m_voice != NULL) { - if (m_currentTG == 0U) - m_voice->unlinked(); - else - m_voice->linkedTo(m_currentTG); - } - - return RESULT_IGNORED; - } - if (trace) { if (m_fromTGStart == m_fromTGEnd) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u or Dst=TG%u or Dst=%u or Dst=%u: not matched", m_name.c_str(), m_slot, m_fromTGStart, m_toTG, m_discPC, m_statusPC); diff --git a/Version.h b/Version.h index cfa3710..394903b 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200407"; +const char* VERSION = "20200408"; #endif From 55af548e6dff092426f680076999df3c100dd78d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 8 Apr 2020 19:41:19 +0100 Subject: [PATCH 18/27] Fix pass through bug. --- DMRGateway.ini | 2 +- RewriteDynTGRF.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DMRGateway.ini b/DMRGateway.ini index a0266e5..d9b339d 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -71,7 +71,7 @@ SrcRewrite=1,9990,1,9990,1 # Reflector status returns SrcRewrite=2,4000,2,9,1001 # Dynamic rewriting of slot 2 TGs 90-999999 to TG9 to emulate reflector behaviour -TGDynRewrite=2,90,4000,5000,9,999910,9900 +TGDynRewrite=2,90,4000,5000,9,999910,9990 # Pass all of the other private traffic on slot 1 and slot 2 PassAllPC=1 PassAllPC=2 diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index 805938c..1af6d20 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -107,9 +107,9 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) if (std::find(m_exclTGs.cbegin(), m_exclTGs.cend(), dstId) != m_exclTGs.cend()) { if (trace) - LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: matched", m_name.c_str(), m_slot, dstId); + LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: not matched", m_name.c_str(), m_slot, dstId); - return RESULT_IGNORED; + return RESULT_UNMATCHED; } if (slotNo == m_slot && dstId >= m_fromTGStart && dstId <= m_fromTGEnd) { From 42afea8527728b95eb719cc27d79e47d4bf1c030 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 13 Apr 2020 14:15:21 +0100 Subject: [PATCH 19/27] Add extern dynamic TG control via UDP. --- Conf.cpp | 24 ++++++++++++++-- Conf.h | 7 +++++ DMRGateway.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++-- DMRGateway.h | 7 +++++ DMRGateway.ini | 4 +++ RewriteDynTGRF.cpp | 17 +++++++++++ RewriteDynTGRF.h | 2 ++ Version.h | 2 +- 8 files changed, 129 insertions(+), 6 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index 21ab2e4..13d9a62 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -37,7 +37,8 @@ enum SECTION { SECTION_DMR_NETWORK_3, SECTION_DMR_NETWORK_4, SECTION_DMR_NETWORK_5, - SECTION_XLX_NETWORK + SECTION_XLX_NETWORK, + SECTION_DYNAMIC_TG_CONTROL }; CConf::CConf(const std::string& file) : @@ -172,7 +173,9 @@ m_xlxNetworkStartup(4000U), m_xlxNetworkRelink(0U), m_xlxNetworkDebug(false), m_xlxNetworkUserControl(true), -m_xlxNetworkModule() +m_xlxNetworkModule(), +m_dynamicTGControlEnabled(false), +m_dynamicTGControlPort(3769U) { } @@ -216,6 +219,8 @@ bool CConf::read() section = SECTION_DMR_NETWORK_4; else if (::strncmp(buffer, "[DMR Network 5]", 15U) == 0) section = SECTION_DMR_NETWORK_5; + else if (::strncmp(buffer, "[Dynamic TG Control]", 20U) == 0) + section = SECTION_DYNAMIC_TG_CONTROL; else section = SECTION_NONE; @@ -936,6 +941,11 @@ bool CConf::read() unsigned int slotNo = (unsigned int)::atoi(value); m_dmrNetwork5PassAllTG.push_back(slotNo); } + } else if (section == SECTION_DYNAMIC_TG_CONTROL) { + if (::strcmp(key, "Enabled") == 0) + m_dynamicTGControlEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Port") == 0) + m_dynamicTGControlPort = (unsigned int)::atoi(value); } } @@ -1611,3 +1621,13 @@ std::vector CConf::getDMRNetwork5PassAllTG() const { return m_dmrNetwork5PassAllTG; } + +bool CConf::getDynamicTGControlEnabled() const +{ + return m_dynamicTGControlEnabled; +} + +unsigned int CConf::getDynamicTGControlPort() const +{ + return m_dynamicTGControlPort; +} diff --git a/Conf.h b/Conf.h index 30c85db..b038329 100644 --- a/Conf.h +++ b/Conf.h @@ -228,6 +228,10 @@ public: bool getXLXNetworkUserControl() const; char getXLXNetworkModule() const; + // The Dynamic TG Control section + bool getDynamicTGControlEnabled() const; + unsigned int getDynamicTGControlPort() const; + private: std::string m_file; bool m_daemon; @@ -370,6 +374,9 @@ private: bool m_xlxNetworkDebug; bool m_xlxNetworkUserControl; char m_xlxNetworkModule; + + bool m_dynamicTGControlEnabled; + unsigned int m_dynamicTGControlPort; }; #endif diff --git a/DMRGateway.cpp b/DMRGateway.cpp index c3621d6..0adb93b 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -24,8 +24,6 @@ #include "RewritePC.h" #include "RewriteSrcId.h" #include "RewriteDstId.h" -#include "RewriteDynTGNet.h" -#include "RewriteDynTGRF.h" #include "PassAllPC.h" #include "PassAllTG.h" #include "DMRFullLC.h" @@ -181,7 +179,9 @@ m_dmr2Passalls(), m_dmr3Passalls(), m_dmr4Passalls(), m_dmr5Passalls(), -m_dynVoices() +m_dynVoices(), +m_dynRF(), +m_socket(NULL) { m_status = new DMRGW_STATUS[3U]; m_status[1U] = DMRGWS_NONE; @@ -430,6 +430,12 @@ int CDMRGateway::run() return 1; } + if (m_conf.getDynamicTGControlEnabled()) { + bool ret = createDynamicTGControl(); + if (!ret) + return 1; + } + unsigned int rfTimeout = m_conf.getRFTimeout(); unsigned int netTimeout = m_conf.getNetTimeout(); @@ -1133,6 +1139,9 @@ int CDMRGateway::run() m_repeater->write(data); } + if (m_socket != NULL) + processDynamicTGControl(); + unsigned int ms = stopWatch.elapsed(); stopWatch.start(); @@ -1214,6 +1223,11 @@ int CDMRGateway::run() delete m_xlxNetwork; } + if (m_socket != NULL) { + m_socket->close(); + delete m_socket; + } + delete timer[1U]; delete timer[2U]; @@ -1377,6 +1391,7 @@ bool CDMRGateway::createDMRNetwork1() m_dmr1RFRewrites.push_back(rfRewriteDynTG); m_dmr1NetRewrites.push_back(netRewriteDynTG); + m_dynRF.push_back(rfRewriteDynTG); } std::vector idRewrites = m_conf.getDMRNetwork1IdRewrites(); @@ -1544,6 +1559,7 @@ bool CDMRGateway::createDMRNetwork2() m_dmr2RFRewrites.push_back(rfRewriteDynTG); m_dmr2NetRewrites.push_back(netRewriteDynTG); + m_dynRF.push_back(rfRewriteDynTG); } std::vector idRewrites = m_conf.getDMRNetwork2IdRewrites(); @@ -1711,6 +1727,7 @@ bool CDMRGateway::createDMRNetwork3() m_dmr3RFRewrites.push_back(rfRewriteDynTG); m_dmr3NetRewrites.push_back(netRewriteDynTG); + m_dynRF.push_back(rfRewriteDynTG); } std::vector idRewrites = m_conf.getDMRNetwork3IdRewrites(); @@ -1878,6 +1895,7 @@ bool CDMRGateway::createDMRNetwork4() m_dmr4RFRewrites.push_back(rfRewriteDynTG); m_dmr4NetRewrites.push_back(netRewriteDynTG); + m_dynRF.push_back(rfRewriteDynTG); } std::vector idRewrites = m_conf.getDMRNetwork4IdRewrites(); @@ -2045,6 +2063,7 @@ bool CDMRGateway::createDMRNetwork5() m_dmr5RFRewrites.push_back(rfRewriteDynTG); m_dmr5NetRewrites.push_back(netRewriteDynTG); + m_dynRF.push_back(rfRewriteDynTG); } std::vector idRewrites = m_conf.getDMRNetwork5IdRewrites(); @@ -2153,6 +2172,22 @@ bool CDMRGateway::createXLXNetwork() return true; } +bool CDMRGateway::createDynamicTGControl() +{ + unsigned int port = m_conf.getDynamicTGControlPort(); + + m_socket = new CUDPSocket(port); + + bool ret = m_socket->open(); + if (!ret) { + delete m_socket; + m_socket = NULL; + return false; + } + + return true; +} + bool CDMRGateway::linkXLX(unsigned int number) { CReflector* reflector = m_xlxReflectors->find(number); @@ -2395,3 +2430,34 @@ void CDMRGateway::processHomePosition() if (m_dmrNetwork5 != NULL) m_dmrNetwork5->writeHomePosition(buffer, length); } + +void CDMRGateway::processDynamicTGControl() +{ + unsigned char buffer[100U]; + in_addr address; + unsigned int port; + + int len = m_socket->read(buffer, 100U, address, port); + if (len <= 0) + return; + + buffer[len] = '\0'; + + if (::memcmp(buffer + 0U, "DynTG", 5U) == 0) { + char* pSlot = ::strtok((char*)(buffer + 5U), ", \r\n"); + char* pTG = ::strtok(NULL, ", \r\n"); + + if (pSlot == NULL || pTG == NULL) { + LogWarning("Malformed dynamic TG control message"); + return; + } + + unsigned int slot = (unsigned int)::atoi(pSlot); + unsigned int tg = (unsigned int)::atoi(pTG); + + for (std::vector::iterator it = m_dynRF.begin(); it != m_dynRF.end(); ++it) + (*it)->tgChange(slot, tg); + } else { + LogWarning("Unknown dynamic TG control message: %s", buffer); + } +} diff --git a/DMRGateway.h b/DMRGateway.h index fd5c6b3..0312e5b 100644 --- a/DMRGateway.h +++ b/DMRGateway.h @@ -20,9 +20,12 @@ #define DMRGateway_H #include "RepeaterProtocol.h" +#include "RewriteDynTGNet.h" +#include "RewriteDynTGRF.h" #include "MMDVMNetwork.h" #include "DMRNetwork.h" #include "Reflectors.h" +#include "UDPSocket.h" #include "RewriteTG.h" #include "DynVoice.h" #include "Rewrite.h" @@ -106,6 +109,8 @@ private: std::vector m_dmr4Passalls; std::vector m_dmr5Passalls; std::vector m_dynVoices; + std::vector m_dynRF; + CUDPSocket* m_socket; bool createMMDVM(); bool createDMRNetwork1(); @@ -114,6 +119,7 @@ private: bool createDMRNetwork4(); bool createDMRNetwork5(); bool createXLXNetwork(); + bool createDynamicTGControl(); bool linkXLX(unsigned int number); void unlinkXLX(); @@ -126,6 +132,7 @@ private: void processRadioPosition(); void processTalkerAlias(); void processHomePosition(); + void processDynamicTGControl(); }; #endif diff --git a/DMRGateway.ini b/DMRGateway.ini index d9b339d..675e5f9 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -136,3 +136,7 @@ TGRewrite=2,11,2,11,1 Password=PASSWORD Location=0 Debug=0 + +[Dynamic TG Control] +Enabled=1 +Port=3769 diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index 1af6d20..1aa8796 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -143,3 +143,20 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) return RESULT_UNMATCHED; } + +void CRewriteDynTGRF::tgChange(unsigned int slot, unsigned int tg) +{ + if (slot == m_slot && tg == m_discPC && m_currentTG != 0U) { + m_currentTG = 0U; + m_rewriteNet->setCurrentTG(0U); + if (m_voice != NULL) + m_voice->unlinked(); + } + + if (slot == m_slot && tg >= m_fromTGStart && tg <= m_fromTGEnd && m_currentTG != tg) { + m_currentTG = tg; + m_rewriteNet->setCurrentTG(tg); + if (m_voice != NULL) + m_voice->linkedTo(tg); + } +} \ No newline at end of file diff --git a/RewriteDynTGRF.h b/RewriteDynTGRF.h index 8e6a8d4..d263e84 100644 --- a/RewriteDynTGRF.h +++ b/RewriteDynTGRF.h @@ -35,6 +35,8 @@ public: virtual PROCESS_RESULT process(CDMRData& data, bool trace); + void tgChange(unsigned int slot, unsigned int tg); + private: std::string m_name; unsigned int m_slot; diff --git a/Version.h b/Version.h index 394903b..1442d4b 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200408"; +const char* VERSION = "20200413"; #endif From 4ab6ef030e347ac33167883c246c5a4d4f771197 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 13 Apr 2020 17:53:36 +0100 Subject: [PATCH 20/27] Fix bug. --- RewriteDynTGRF.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index 1aa8796..4e56c48 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -146,17 +146,23 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) void CRewriteDynTGRF::tgChange(unsigned int slot, unsigned int tg) { - if (slot == m_slot && tg == m_discPC && m_currentTG != 0U) { - m_currentTG = 0U; - m_rewriteNet->setCurrentTG(0U); - if (m_voice != NULL) - m_voice->unlinked(); + if (slot == m_slot && tg == m_discPC) { + if (m_currentTG != 0U) { + m_currentTG = 0U; + m_rewriteNet->setCurrentTG(0U); + if (m_voice != NULL) + m_voice->unlinked(); + } + return; } - if (slot == m_slot && tg >= m_fromTGStart && tg <= m_fromTGEnd && m_currentTG != tg) { - m_currentTG = tg; - m_rewriteNet->setCurrentTG(tg); - if (m_voice != NULL) - m_voice->linkedTo(tg); + if (slot == m_slot && tg >= m_fromTGStart && tg <= m_fromTGEnd) { + if (m_currentTG != tg) { + m_currentTG = tg; + m_rewriteNet->setCurrentTG(tg); + if (m_voice != NULL) + m_voice->linkedTo(tg); + } + return; } } \ No newline at end of file From 3b3243c1bf967046a4a83d8adabc4e13de96fe5b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 13 Apr 2020 20:53:05 +0100 Subject: [PATCH 21/27] Add the status and exclusion PC/TG to the control ignore list. --- RewriteDynTGRF.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index 4e56c48..2c39577 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -105,7 +105,7 @@ PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace) return RESULT_IGNORED; } - if (std::find(m_exclTGs.cbegin(), m_exclTGs.cend(), dstId) != m_exclTGs.cend()) { + if (slotNo == m_slot && std::find(m_exclTGs.cbegin(), m_exclTGs.cend(), dstId) != m_exclTGs.cend()) { if (trace) LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=%u: not matched", m_name.c_str(), m_slot, dstId); @@ -156,6 +156,12 @@ void CRewriteDynTGRF::tgChange(unsigned int slot, unsigned int tg) return; } + if (slot == m_slot && tg == m_statusPC) + return; + + if (slot == m_slot && std::find(m_exclTGs.cbegin(), m_exclTGs.cend(), tg) != m_exclTGs.cend()) + return; + if (slot == m_slot && tg >= m_fromTGStart && tg <= m_fromTGEnd) { if (m_currentTG != tg) { m_currentTG = tg; From 00342c763a7f380f737f3ba5f718ccc9f95e3307 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 18 Apr 2020 22:33:24 +0100 Subject: [PATCH 22/27] Abort the voice prompt if network traffic appears on the same slot. --- DMRGateway.cpp | 10 ++++++++++ DynVoice.cpp | 11 +++++++++++ DynVoice.h | 2 ++ RewriteDynTGRF.cpp | 8 +++++++- RewriteDynTGRF.h | 2 ++ Version.h | 2 +- 6 files changed, 33 insertions(+), 2 deletions(-) diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 0adb93b..4f961d6 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -909,6 +909,8 @@ int CDMRGateway::run() // Check that the rewritten slot is free to use. slotNo = data.getSlotNo(); if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK1) { + for (std::vector::iterator it = m_dynRF.begin(); it != m_dynRF.end(); ++it) + (*it)->stopVoice(slotNo); m_repeater->write(data); m_status[slotNo] = DMRGWS_DMRNETWORK1; timer[slotNo]->setTimeout(netTimeout); @@ -957,6 +959,8 @@ int CDMRGateway::run() // Check that the rewritten slot is free to use. slotNo = data.getSlotNo(); if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK2) { + for (std::vector::iterator it = m_dynRF.begin(); it != m_dynRF.end(); ++it) + (*it)->stopVoice(slotNo); m_repeater->write(data); m_status[slotNo] = DMRGWS_DMRNETWORK2; timer[slotNo]->setTimeout(netTimeout); @@ -1005,6 +1009,8 @@ int CDMRGateway::run() // Check that the rewritten slot is free to use. slotNo = data.getSlotNo(); if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK3) { + for (std::vector::iterator it = m_dynRF.begin(); it != m_dynRF.end(); ++it) + (*it)->stopVoice(slotNo); m_repeater->write(data); m_status[slotNo] = DMRGWS_DMRNETWORK3; timer[slotNo]->setTimeout(netTimeout); @@ -1053,6 +1059,8 @@ int CDMRGateway::run() // Check that the rewritten slot is free to use. slotNo = data.getSlotNo(); if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK4) { + for (std::vector::iterator it = m_dynRF.begin(); it != m_dynRF.end(); ++it) + (*it)->stopVoice(slotNo); m_repeater->write(data); m_status[slotNo] = DMRGWS_DMRNETWORK4; timer[slotNo]->setTimeout(netTimeout); @@ -1101,6 +1109,8 @@ int CDMRGateway::run() // Check that the rewritten slot is free to use. slotNo = data.getSlotNo(); if (m_status[slotNo] == DMRGWS_NONE || m_status[slotNo] == DMRGWS_DMRNETWORK5) { + for (std::vector::iterator it = m_dynRF.begin(); it != m_dynRF.end(); ++it) + (*it)->stopVoice(slotNo); m_repeater->write(data); m_status[slotNo] = DMRGWS_DMRNETWORK5; timer[slotNo]->setTimeout(netTimeout); diff --git a/DynVoice.cpp b/DynVoice.cpp index 380a890..46d1e04 100644 --- a/DynVoice.cpp +++ b/DynVoice.cpp @@ -162,6 +162,17 @@ void CDynVoice::unlinked() createVoice(words); } +void CDynVoice::abort() +{ + for (std::vector::iterator it = m_data.begin(); it != m_data.end(); ++it) + delete* it; + + m_data.clear(); + m_timer.stop(); + + m_status = DYNVS_NONE; +} + void CDynVoice::createVoice(const std::vector& words) { unsigned int ambeLength = 0U; diff --git a/DynVoice.h b/DynVoice.h index 53b269f..64abd2e 100644 --- a/DynVoice.h +++ b/DynVoice.h @@ -52,6 +52,8 @@ public: bool read(CDMRData& data); + void abort(); + void clock(unsigned int ms); private: diff --git a/RewriteDynTGRF.cpp b/RewriteDynTGRF.cpp index 2c39577..728b472 100644 --- a/RewriteDynTGRF.cpp +++ b/RewriteDynTGRF.cpp @@ -171,4 +171,10 @@ void CRewriteDynTGRF::tgChange(unsigned int slot, unsigned int tg) } return; } -} \ No newline at end of file +} + +void CRewriteDynTGRF::stopVoice(unsigned int slot) +{ + if (slot == m_slot && m_voice != NULL) + m_voice->abort(); +} diff --git a/RewriteDynTGRF.h b/RewriteDynTGRF.h index d263e84..d5a2b06 100644 --- a/RewriteDynTGRF.h +++ b/RewriteDynTGRF.h @@ -35,6 +35,8 @@ public: virtual PROCESS_RESULT process(CDMRData& data, bool trace); + void stopVoice(unsigned int slot); + void tgChange(unsigned int slot, unsigned int tg); private: diff --git a/Version.h b/Version.h index 1442d4b..049e6ea 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200413"; +const char* VERSION = "20200418"; #endif From 1542c9750db9db6f214b4f19783aa078bdd878ef Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 21 Apr 2020 21:31:29 +0100 Subject: [PATCH 23/27] Removed the 2 in the linked to message, it sounded odd. --- DynVoice.cpp | 6 ++---- Version.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/DynVoice.cpp b/DynVoice.cpp index 46d1e04..7643163 100644 --- a/DynVoice.cpp +++ b/DynVoice.cpp @@ -141,12 +141,10 @@ void CDynVoice::linkedTo(unsigned int number) ::sprintf(letters, "%u", number); std::vector words; - if (m_positions.count("linkedto") == 0U) { + if (m_positions.count("linkedto") == 0U) words.push_back("linked"); - words.push_back("2"); - } else { + else words.push_back("linkedto"); - } for (unsigned int i = 0U; letters[i] != '\0'; i++) words.push_back(std::string(1U, letters[i])); diff --git a/Version.h b/Version.h index 049e6ea..aa4c644 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200418"; +const char* VERSION = "20200421"; #endif From 4ed53d9bab08c5be3791d794bed2a978611ff07d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 21 Apr 2020 21:43:53 +0100 Subject: [PATCH 24/27] Add dynamic talk group scripts from Jon G4TSN. --- scripts/opt/script/README | 130 ++++++++++++++++++++ scripts/opt/script/install-relinker.sh | 11 ++ scripts/opt/script/relink-hotspot.sh | 135 +++++++++++++++++++++ scripts/opt/script/relink-repeater.sh | 135 +++++++++++++++++++++ scripts/opt/script/run-relinker-hotspot.sh | 8 ++ scripts/opt/script/run-relinker.sh | 8 ++ scripts/opt/script/script.conf | 7 ++ scripts/opt/script/start.sh | 12 ++ scripts/opt/script/var-log-script.tgz | Bin 0 -> 2136 bytes scripts/var/log/script/slot1.txt | 0 scripts/var/log/script/slot2.txt | 0 scripts/var/log/script/static-slot1.txt | 1 + scripts/var/log/script/static-slot2.txt | 1 + scripts/var/log/script/test1.txt | 0 scripts/var/log/script/test2.txt | 1 + scripts/var/log/script/test3.txt | 1 + scripts/var/log/script/test4.txt | 0 scripts/var/log/script/var-log-script.tgz | Bin 0 -> 2136 bytes 18 files changed, 450 insertions(+) create mode 100644 scripts/opt/script/README create mode 100644 scripts/opt/script/install-relinker.sh create mode 100644 scripts/opt/script/relink-hotspot.sh create mode 100644 scripts/opt/script/relink-repeater.sh create mode 100644 scripts/opt/script/run-relinker-hotspot.sh create mode 100644 scripts/opt/script/run-relinker.sh create mode 100644 scripts/opt/script/script.conf create mode 100644 scripts/opt/script/start.sh create mode 100644 scripts/opt/script/var-log-script.tgz create mode 100644 scripts/var/log/script/slot1.txt create mode 100644 scripts/var/log/script/slot2.txt create mode 100644 scripts/var/log/script/static-slot1.txt create mode 100644 scripts/var/log/script/static-slot2.txt create mode 100644 scripts/var/log/script/test1.txt create mode 100644 scripts/var/log/script/test2.txt create mode 100644 scripts/var/log/script/test3.txt create mode 100644 scripts/var/log/script/test4.txt create mode 100644 scripts/var/log/script/var-log-script.tgz diff --git a/scripts/opt/script/README b/scripts/opt/script/README new file mode 100644 index 0000000..c582fe9 --- /dev/null +++ b/scripts/opt/script/README @@ -0,0 +1,130 @@ + + + + + + + +These scripts are supplied as is and work in conjuction with DMRGateway Mid April 2020 Onwards .....If you don't understand the notes ask someone who does please + +Tested on rasp pi running MMDVMHost and DMRGateway Using SUDO-Reflector-TalkGroups + + +These scripts provide a means to setup via the config file default TG's for each slot on a repeater. These should be also setup as only Static TG setup via Brandmeister Selfcare, so that when +a slot is commanded to another dynamic TG by a user and then after use they forget to unlink. The BM Dynamic TG timer which is monitored by this script (expires 10 minutes after inactivity) +the slot will be returned to the configured Static default TG. + +Both slots can be monitored together and as they maybe taken off to other dynamics at the same time or individually it is worth getting users in the habit of sending a PC 4000 once they finish +using a different TG as it ensures the repeater when not in use is in the correct place for most of the time. + + +A default TG of choice which can be configured linking provided on on both slots. + + + +Installation + +Firstly DMRGateway should have the following lines minimum configuring if running both timeslots for SUDO Reflector on a repeater + + +# Dynamic rewriting of slot 2 TGs 90-999999 to TG9 to emulate reflector behaviour Private call manual dial commands PC 2351 for SUDO REF TG 2351 PC 4000 unlink PC 5000 Status PC 9990 echo BM + + +TGDynRewrite0=1,90,4000,5000,9,999910,9990 +TGDynRewrite1=2,90,4000,5000,9,999910,9990 + +Check you also have the following section added in your DMRGateway config file its usually at the bottom + +[Dynamic TG Control] +Enabled=1 +Port=3769 + + +copy the package DMRGateway-TGDynRewrite-relinker-2.0.tgz to the folder / unpack with tar -xvf packagename which should create folders /opt/script/script runtimes and /var/log/script/various working files and log + +configure the config file /opt/script/script.conf call repeater=235??? ID with your default slots and dont forget to set these static via BM selfcare also min relink timer minrelinktimer in seconds + +this is the time before reconnection on a slot after someone finishes and either the slot is unlinked by the user or the dynamic times out + + + + + +Add the following line to crontab on the rasp pi you dont need to do anything else just save crontab and exit + +17 * * * * root echo -n "" > /var/log/script/checkBMAPI.log + + +Add one of the following to etc/rc.local right at end just before exit 0 + + +/opt/script/./run-relinker.sh + +or + +/opt/script/./run-relinker-hotspot.sh + + + +pi-star additional step + + +Also in same file etc/rc.local + +look for + +if [ ! -d /var/log/unattended-upgrades ]; then + mkdir -p /var/log/unattended-upgrades + + + + +fi + +add only the below lines just below the above block + +if [ ! -d /var/log/script ]; then + /opt/script/./start.sh +fi + + +reboot + + + +you can tail the log file at the command prompt + + +tail -f /var/log/script/checkBMAPI.log + + + + + + + + + +Have fun + +73, + +Jon G4TSN + +jon@g4tsn.com + + + + + + + + + + + + + + + + diff --git a/scripts/opt/script/install-relinker.sh b/scripts/opt/script/install-relinker.sh new file mode 100644 index 0000000..25b23e2 --- /dev/null +++ b/scripts/opt/script/install-relinker.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +cp DMRG*.tgz / +cd / + +tar -xvf DMRG* + + + + + diff --git a/scripts/opt/script/relink-hotspot.sh b/scripts/opt/script/relink-hotspot.sh new file mode 100644 index 0000000..a1c9fcd --- /dev/null +++ b/scripts/opt/script/relink-hotspot.sh @@ -0,0 +1,135 @@ +#!/bin/bash + + +source /opt/script/script.conf + + +#check BM API + +check_BM_API(){ + + echo "Repeater $call $repeater" + + date + + curl "https://api.brandmeister.network/v1.0/repeater/?action=profile&q=$repeater" > /var/log/script/test1.txt + + sed -n -e 's/^.*tarantool"}],//p' /var/log/script/test1.txt > /var/log/script/test2.txt + + sed 's/}],"timedSubscriptions.*//' /var/log/script/test2.txt > /var/log/script/test3.txt + + sed -n -e 's/^.*slot":1,"timeout"://p' /var/log/script/test3.txt > /var/log/script/slot1.txt + + + + #sed -n -e 's/^.*slot":2,"timeout"://p' /var/log/script/test3.txt > /var/log/script/test4.txt + + sed -n -e 's/^.*slot":0,"timeout"://p' /Var/log/script/test3.txt > /var/log/script/test4.txt + + + sed 's/},{"repeaterid.*//' /var/log/script/test4.txt > /var/log/script/slot2.txt + +} + + +check_status_slot1(){ + + if [ -s "/var/log/script/slot1.txt" ] + then + echo "Dynamic is linked slot 1." + echo -n "" > /var/log/script/static-slot1.txt + else + echo + #echo "Dynamic is not linked slot 1."./check + fi + if [ -s "/var/log/script/static-slot1.txt" ] + then + echo "Static is linked slot 1." + echo + else + #echo "Static is not linked slot 1." + echo + + fi +} + +check_status_slot2(){ + + if [ -s "/var/log/script/slot2.txt" ] + then + echo "Dynamic is linked slot 2." + echo -n "" > /var/log/script/static-slot2.txt + else + echo + #echo "Dynamic is not linked slot 2." + fi + if [ -s "/var/log/script/static-slot2.txt" ] + then + echo "Static is linked slot 2." + echo + else + #echo "Static is not linked slot 2." + echo + + fi +} + + +#check if static-slot1.txt and slot.txt are blank + +check_if_nothing_linked_slot1(){ + + if [ -s "/var/log/script/static-slot1.txt" ] + + then + echo "Linked to Static $defaultslot1 Slot 1" + + elif [ -s "/var/log/script/slot1.txt" ] + + then + echo "Dynamic is Linked slot 1" + else + echo "DMRGateway slot 1 is Unlinked" + echo "Linking slot 1 $defaultslot1" && sleep $minrelinktimerslot1; echo "DynTG1,$defaultslot1" > /dev/udp/127.0.0.1/3769 + echo -n "Linked to $defaultslot1" > /var/log/script/static-slot1.txt + + + fi + +} + + + +#check if static-slot2.txt and slot.txt are blank + +check_if_nothing_linked_slot2(){ + + if [ -s "/var/log/script/static-slot2.txt" ] + + then + echo "Linked to Static $defaultslot2 Slot 2" + + elif [ -s "/var/log/script/slot2.txt" ] + + then + echo "Dynamic is Linked slot 2" + else + echo "DMRGateway slot 2 is Unlinked" + echo "Linking slot 2 $defaultslot2" && sleep $minrelinktimerslot2; echo "DynTG2,$defaultslot2" > /dev/udp/127.0.0.1/3769 + echo -n "Linked to $defaultslot2" > /var/log/script/static-slot2.txt + fi + +} + + +check_BM_API +echo +#check_status_slot1 +check_status_slot2 +#check_if_nothing_linked_slot1 +check_if_nothing_linked_slot2 +echo + + + + diff --git a/scripts/opt/script/relink-repeater.sh b/scripts/opt/script/relink-repeater.sh new file mode 100644 index 0000000..9e89601 --- /dev/null +++ b/scripts/opt/script/relink-repeater.sh @@ -0,0 +1,135 @@ +#!/bin/bash + + +source /opt/script/script.conf + + +#check BM API + +check_BM_API(){ + + echo "Repeater $call $repeater" + + date + + curl "https://api.brandmeister.network/v1.0/repeater/?action=profile&q=$repeater" > /var/log/script/test1.txt + + sed -n -e 's/^.*tarantool"}],//p' /var/log/script/test1.txt > /var/log/script/test2.txt + + sed 's/}],"timedSubscriptions.*//' /var/log/script/test2.txt > /var/log/script/test3.txt + + sed -n -e 's/^.*slot":1,"timeout"://p' /var/log/script/test3.txt > /var/log/script/slot1.txt + + + + sed -n -e 's/^.*slot":2,"timeout"://p' /var/log/script/test3.txt > /var/log/script/test4.txt + + #sed -n -e 's/^.*slot":0,"timeout"://p' /Var/log/script/test3.txt > /var/log/script/test4.txt + + + sed 's/},{"repeaterid.*//' /var/log/script/test4.txt > /var/log/script/slot2.txt + +} + + +check_status_slot1(){ + + if [ -s "/var/log/script/slot1.txt" ] + then + echo "Dynamic is linked slot 1." + echo -n "" > /var/log/script/static-slot1.txt + else + echo + #echo "Dynamic is not linked slot 1."./check + fi + if [ -s "/var/log/script/static-slot1.txt" ] + then + echo "Static is linked slot 1." + echo + else + #echo "Static is not linked slot 1." + echo + + fi +} + +check_status_slot2(){ + + if [ -s "/var/log/script/slot2.txt" ] + then + echo "Dynamic is linked slot 2." + echo -n "" > /var/log/script/static-slot2.txt + else + echo + #echo "Dynamic is not linked slot 2." + fi + if [ -s "/var/log/script/static-slot2.txt" ] + then + echo "Static is linked slot 2." + echo + else + #echo "Static is not linked slot 2." + echo + + fi +} + + +#check if static-slot1.txt and slot.txt are blank + +check_if_nothing_linked_slot1(){ + + if [ -s "/var/log/script/static-slot1.txt" ] + + then + echo "Linked to Static $defaultslot1 Slot 1" + + elif [ -s "/var/log/script/slot1.txt" ] + + then + echo "Dynamic is Linked slot 1" + else + echo "DMRGateway slot 1 is Unlinked" + echo "Linking slot 1 $defaultslot1" && sleep $minrelinktimerslot1; echo "DynTG1,$defaultslot1" > /dev/udp/127.0.0.1/3769 + echo -n "Linked to $defaultslot1" > /var/log/script/static-slot1.txt + + + fi + +} + + + +#check if static-slot2.txt and slot.txt are blank + +check_if_nothing_linked_slot2(){ + + if [ -s "/var/log/script/static-slot2.txt" ] + + then + echo "Linked to Static $defaultslot2 Slot 2" + + elif [ -s "/var/log/script/slot2.txt" ] + + then + echo "Dynamic is Linked slot 2" + else + echo "DMRGateway slot 2 is Unlinked" + echo "Linking slot 2 $defaultslot2" && sleep $minrelinktimerslot2; echo "DynTG2,$defaultslot2" > /dev/udp/127.0.0.1/3769 + echo -n "Linked to $defaultslot2" > /var/log/script/static-slot2.txt + fi + +} + + +check_BM_API +echo +check_status_slot1 +check_status_slot2 +check_if_nothing_linked_slot1 +check_if_nothing_linked_slot2 +echo +echo +sleep 5 +#/opt/script/./check.sh >> /var/log/script/checkBMAPI.log + diff --git a/scripts/opt/script/run-relinker-hotspot.sh b/scripts/opt/script/run-relinker-hotspot.sh new file mode 100644 index 0000000..c48d5ab --- /dev/null +++ b/scripts/opt/script/run-relinker-hotspot.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# This is just a nice way to start the script + + +while /bin/true; do + /opt/script/./relink-repeater-hotspot.sh >> /var/log/script/checkBMAPI.log 2>&1 +done & \ No newline at end of file diff --git a/scripts/opt/script/run-relinker.sh b/scripts/opt/script/run-relinker.sh new file mode 100644 index 0000000..160ca46 --- /dev/null +++ b/scripts/opt/script/run-relinker.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# This is just a nice way to start the script + + +while /bin/true; do + /opt/script/./relink-repeater.sh >> /var/log/script/checkBMAPI.log 2>&1 +done & \ No newline at end of file diff --git a/scripts/opt/script/script.conf b/scripts/opt/script/script.conf new file mode 100644 index 0000000..3e7d1c4 --- /dev/null +++ b/scripts/opt/script/script.conf @@ -0,0 +1,7 @@ +#!/usr/bin/bash +repeater=235192 +call=GB3IN +defaultslot1=23590 +defaultslot2=91 +minrelinktimerslot1=30 +minrelinktimerslot2=30 diff --git a/scripts/opt/script/start.sh b/scripts/opt/script/start.sh new file mode 100644 index 0000000..c56a620 --- /dev/null +++ b/scripts/opt/script/start.sh @@ -0,0 +1,12 @@ +#!/bin/bash +mkdir /var/log/script +sleep 1 +cp /opt/script/var-log-script.tgz /var/log/script/ +sleep 1 +cd /var/log/script +sleep 1 +tar -xvf var-log-script.tgz + + + + diff --git a/scripts/opt/script/var-log-script.tgz b/scripts/opt/script/var-log-script.tgz new file mode 100644 index 0000000000000000000000000000000000000000..7f5a7fcc7457dc1a1a9035c6e68f6ae4d9b9c411 GIT binary patch literal 2136 zcmY*adpr|*8+QvuROFVqbmX>-GAx>sY;PBwMN`b>kV{KuP7y;Xm#{eHmM}U~(_AK( zrfkf0hum2?E^`?rm!>hRTy|Ec_ni0r>-TxS-_P^>e$VrKpWmaMDl4|`NbnMqTq@vV z@*rx=73+abMPxC3K|fetnZ1+*b{ugc)n+(ZkIQ9Oc@2S2#)rEVtTh&%8UbB>6F;IK zd$%$DX=410lFDMbHol2-Gv!lTo-;-Gc^U0aP_#}y?r?CHhiGeo@0K%~7FYDk{g1jq zvYHesRDI`#zV3HN@udz0Zup(#sxm4a^Y$yD9fRLimOQ!D+de(g@;c{FUZH!>Z5_@6 z1&lFk{ltW5fw@`YjqAfB)8i9Azi0t4Tc(zadlot#I;sR)=Xxp!1|KrH((b)8i5n8| zW%ix%V`K~pN;wn0j@=Er%y7!q_7qMs`HE!BI;ty`1~OjTa{N3cc;|O?Z_8lm?d?5Y zy+D;^JoDmjRi-3NuIx#(ON-lVOctU?f_ZXlFV$2tuCzrrZEYZ31M&0*5P5^|X%cj;~SJhAy{sfp^8{>Q|91%xRBqq_@@3cw?TNO3Il^ z1ga~v83d|H%?QWd_e2G&<_xz1M%$i*ms557k#AB7&Cn{Z6RfEHiF|O1Tv^~P;#E4~ za;LoDWQA&?0AJfy-#A?d08M$6Q(Zy|Z5!RB*9jA2?&WdOx#ecBdz}K_N0gppzll86 zZVz!LRx%=`AtOCM6?_0>uEf&O5l^YlEoV#5m;XxFa}fe>D6&V>?g&<~H7;-r-9YJv zGm*i-NkeWp?|U2B5SUo)fqyyf+qII&GP+kH|{nWUk- zVwi)}y;rSv#J;(ypw;AGS8c$LY!h(B2s=08x#L8QZPILWMicHUWDncs*6N|=hi3~U zB)RI7lh7E=r6#9+ZFN~NPB`S%2fs(ye6c|zv%V5>1q~LHZyX~(7iF5cOn}A33FJeU z36>S!lF;oq)9L?%*u)V}LkanjIM`zZ#$x145x`ut{hroF9fBpbJ^y)FioH_2{@fAB zC7zyzG1g-b2@<5Nah-&?#FMUz_2(h6Myx|>x2-G`Odi>5x`S(idYk$~`d1ULt!|!{ zeS(P71vp{*48imDFx*6Avw8CF{on1=9k>99bN#bOm0uXiE}GyS_iSb0Hv9Ol#NR)( zC%_)}FF}G_wc+l>KVT-8!L6RY`O`%R(al#Ah-HXmU7Gbjb;(z%nxa=4SuAVOr~n!6 z2hJq)0bA*z!q24tb|Z;{I>XNRA4EGTx;IU*AC=5embrI=m`MvvTmi>qb|*aTGyD-G zbolH5P8U?rZ)CPi5LaLiGW(shZJ;|yxMT9Ur%=`+Phd-DB~Pi&DZ}FxGVRgfoj{w` zrcRjcSX6Q+_q5Y*n5py zd^Os?`DIu!NeCiXpIWt9z3sqj{t2hcCvPQ`% zx4E-&Wvtk!~+A{VoCD>_q_Yri=VUflpro- z7oWZWwaLDKIZkMcmJK@tqWa9mXA&x@Nh75%uxc)ddvYBhqojW@`-Z?498;b71uW|O zD#Ie`7W)d0Wi}qoRa+6*x$fG_gK~M$vvuFf*nqBaqgoY}_A84hVqXbWW9jWh)hc4} zxwA5|BAzYc{|w3>U>OFe#tSCt>>CvCg53B)co#^P+k{*8GGG&fV8kVV(~rx=;FR5`MfPH8R3(Y4C8b^PJaAXE|xKPGxGVrB}SpaZDLl3 zaKEhBH{<%|!ZpF<^p(@Z8hC9~R0s0m_Oas(BZUV^GvlYUVx+Rc#@J&L-=`=6<}o#g zcJ+*~FoV9R9F`$&Sr4M&7;qio`F?OVBO2vgk&4h~X{}?yU#(4;otoTI z9=buz|K?^4*uD0Eft$A~2Yr}gFk5!<(?m%RN%ejAI_zR+I;{HlEia^MMm0kJ#51pw zkoDtk6fmGD<%xzKe=*2)qKlPd49n`BugXu0)r9JR2D1b0zEFzLE4|-$-GAx>sY;PBwMN`b>kV{KuP7y;Xm#{eHmM}U~(_AK( zrfkf0hum2?E^`?rm!>hRTy|Ec_ni0r>-TxS-_P^>e$VrKpWmaMDl4|`NbnMqTq@vV z@*rx=73+abMPxC3K|fetnZ1+*b{ugc)n+(ZkIQ9Oc@2S2#)rEVtTh&%8UbB>6F;IK zd$%$DX=410lFDMbHol2-Gv!lTo-;-Gc^U0aP_#}y?r?CHhiGeo@0K%~7FYDk{g1jq zvYHesRDI`#zV3HN@udz0Zup(#sxm4a^Y$yD9fRLimOQ!D+de(g@;c{FUZH!>Z5_@6 z1&lFk{ltW5fw@`YjqAfB)8i9Azi0t4Tc(zadlot#I;sR)=Xxp!1|KrH((b)8i5n8| zW%ix%V`K~pN;wn0j@=Er%y7!q_7qMs`HE!BI;ty`1~OjTa{N3cc;|O?Z_8lm?d?5Y zy+D;^JoDmjRi-3NuIx#(ON-lVOctU?f_ZXlFV$2tuCzrrZEYZ31M&0*5P5^|X%cj;~SJhAy{sfp^8{>Q|91%xRBqq_@@3cw?TNO3Il^ z1ga~v83d|H%?QWd_e2G&<_xz1M%$i*ms557k#AB7&Cn{Z6RfEHiF|O1Tv^~P;#E4~ za;LoDWQA&?0AJfy-#A?d08M$6Q(Zy|Z5!RB*9jA2?&WdOx#ecBdz}K_N0gppzll86 zZVz!LRx%=`AtOCM6?_0>uEf&O5l^YlEoV#5m;XxFa}fe>D6&V>?g&<~H7;-r-9YJv zGm*i-NkeWp?|U2B5SUo)fqyyf+qII&GP+kH|{nWUk- zVwi)}y;rSv#J;(ypw;AGS8c$LY!h(B2s=08x#L8QZPILWMicHUWDncs*6N|=hi3~U zB)RI7lh7E=r6#9+ZFN~NPB`S%2fs(ye6c|zv%V5>1q~LHZyX~(7iF5cOn}A33FJeU z36>S!lF;oq)9L?%*u)V}LkanjIM`zZ#$x145x`ut{hroF9fBpbJ^y)FioH_2{@fAB zC7zyzG1g-b2@<5Nah-&?#FMUz_2(h6Myx|>x2-G`Odi>5x`S(idYk$~`d1ULt!|!{ zeS(P71vp{*48imDFx*6Avw8CF{on1=9k>99bN#bOm0uXiE}GyS_iSb0Hv9Ol#NR)( zC%_)}FF}G_wc+l>KVT-8!L6RY`O`%R(al#Ah-HXmU7Gbjb;(z%nxa=4SuAVOr~n!6 z2hJq)0bA*z!q24tb|Z;{I>XNRA4EGTx;IU*AC=5embrI=m`MvvTmi>qb|*aTGyD-G zbolH5P8U?rZ)CPi5LaLiGW(shZJ;|yxMT9Ur%=`+Phd-DB~Pi&DZ}FxGVRgfoj{w` zrcRjcSX6Q+_q5Y*n5py zd^Os?`DIu!NeCiXpIWt9z3sqj{t2hcCvPQ`% zx4E-&Wvtk!~+A{VoCD>_q_Yri=VUflpro- z7oWZWwaLDKIZkMcmJK@tqWa9mXA&x@Nh75%uxc)ddvYBhqojW@`-Z?498;b71uW|O zD#Ie`7W)d0Wi}qoRa+6*x$fG_gK~M$vvuFf*nqBaqgoY}_A84hVqXbWW9jWh)hc4} zxwA5|BAzYc{|w3>U>OFe#tSCt>>CvCg53B)co#^P+k{*8GGG&fV8kVV(~rx=;FR5`MfPH8R3(Y4C8b^PJaAXE|xKPGxGVrB}SpaZDLl3 zaKEhBH{<%|!ZpF<^p(@Z8hC9~R0s0m_Oas(BZUV^GvlYUVx+Rc#@J&L-=`=6<}o#g zcJ+*~FoV9R9F`$&Sr4M&7;qio`F?OVBO2vgk&4h~X{}?yU#(4;otoTI z9=buz|K?^4*uD0Eft$A~2Yr}gFk5!<(?m%RN%ejAI_zR+I;{HlEia^MMm0kJ#51pw zkoDtk6fmGD<%xzKe=*2)qKlPd49n`BugXu0)r9JR2D1b0zEFzLE4|-$ Date: Wed, 22 Apr 2020 17:47:33 +0100 Subject: [PATCH 25/27] Updated script files. --- scripts/lib/systemd/system/relinker.service | 12 ++ .../lib/systemd/system/relinkerhot.service | 12 ++ scripts/opt/script/README | 109 +++++++++++++++--- scripts/opt/script/install-relinker.sh | 20 ++-- scripts/opt/script/relink-hotspot.sh | 15 ++- scripts/opt/script/relink-repeater.sh | 13 +-- scripts/opt/script/script.conf | 21 +++- scripts/var/log/script/test1.txt | 1 + 8 files changed, 166 insertions(+), 37 deletions(-) create mode 100644 scripts/lib/systemd/system/relinker.service create mode 100644 scripts/lib/systemd/system/relinkerhot.service diff --git a/scripts/lib/systemd/system/relinker.service b/scripts/lib/systemd/system/relinker.service new file mode 100644 index 0000000..bd91ae7 --- /dev/null +++ b/scripts/lib/systemd/system/relinker.service @@ -0,0 +1,12 @@ +[Unit] +Description=relinker service +After=multi-user.target + +[Service] +Type=idle + +ExecStart=/bin/bash /opt/script/relink-repeater.sh >> /var/log/script/checkBMAPI.log 2>&1 + + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/scripts/lib/systemd/system/relinkerhot.service b/scripts/lib/systemd/system/relinkerhot.service new file mode 100644 index 0000000..4848676 --- /dev/null +++ b/scripts/lib/systemd/system/relinkerhot.service @@ -0,0 +1,12 @@ +[Unit] +Description=relinkerhot service +After=multi-user.target + +[Service] +Type=idle + +ExecStart=/bin/bash /opt/script/relink-hotspot.sh >> /var/log/script/checkBMAPI.log 2>&1 + + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/scripts/opt/script/README b/scripts/opt/script/README index c582fe9..e4865b7 100644 --- a/scripts/opt/script/README +++ b/scripts/opt/script/README @@ -1,8 +1,14 @@ +DMR SUDO Reflector - TG +This is the first release version of the relinker scripts 3.1 + + + + These scripts are supplied as is and work in conjuction with DMRGateway Mid April 2020 Onwards .....If you don't understand the notes ask someone who does please @@ -40,33 +46,62 @@ Enabled=1 Port=3769 -copy the package DMRGateway-TGDynRewrite-relinker-2.0.tgz to the folder / unpack with tar -xvf packagename which should create folders /opt/script/script runtimes and /var/log/script/various working files and log -configure the config file /opt/script/script.conf call repeater=235??? ID with your default slots and dont forget to set these static via BM selfcare also min relink timer minrelinktimer in seconds -this is the time before reconnection on a slot after someone finishes and either the slot is unlinked by the user or the dynamic times out +1. Copy the package DMRGateway-TGDynRewrite-relinker-3.1.tgz to the folder/boot and also the install-relinker.sh script supplied (you can do this with a card reader from windows if you like) + + +2. run /boot#./install-relinker which should create folders /opt/script/script and /var/log/script/various working files and logfile. it also sets up services in systemd + +ready to run the script required + + + +3. Edit the config file /opt/script/script.conf repeater=235??? ID call callsign your defaults for slot linking + +also min relink timer minrelinktimer in seconds this is the time before reconnection on a slot after someone finishes RF and either the slot is unlinked by the user + +or the dynamic times out i.e BM timer + +it waits a further minlinktimer seconds before relinking + +slowdown=10 This is higher for faster rasp pi 10 for pi 3B + or 1 for original Pi B + +checkslot1=check_status_slot1 +checkslot2=check_status_slot2 +slot1notlinked=check_if_nothing_linked_slot1 +slot2notlinked=check_if_nothing_linked_slot2 + +Above checks all slots default for repeater with prefered config SUDO Reflectors both slots ............if in doubt include all these lines !!!! + + +checkslot1= +checkslot2=check_status_slot2 +slot1notlinked= +slot2notlinked=check_if_nothing_linked_slot2 + +Above checks only slot 2 typically a hotspot........ or a repeater that only has SUDO Reflectors enabled in DMRGateway on one of the slots + + +............if in doubt include all these lines in first example!!!! +4. Don't forget to set these static via Brandmeister selfcare + -Add the following line to crontab on the rasp pi you dont need to do anything else just save crontab and exit + +5. Add the following line to crontab on the rasp pi you dont need to do anything else just save crontab and exit 17 * * * * root echo -n "" > /var/log/script/checkBMAPI.log -Add one of the following to etc/rc.local right at end just before exit 0 - - -/opt/script/./run-relinker.sh - -or - -/opt/script/./run-relinker-hotspot.sh -pi-star additional step + +6. Pi-star additional step Also in same file etc/rc.local @@ -88,9 +123,57 @@ if [ ! -d /var/log/script ]; then fi +7. start one of the services with following command + + +choose either Repeater + +systemctl start relinker.service + + + +or Hotspot ? + +systemctl start relinkerhot.service + + +systemctl status relinker.service + +or + +systemctl status relinkerhot.service + + +will show if its running if it is running ? + + +you can tail the log file at the command prompt + + +tail -f /var/log/script/checkBMAPI.log + + +once it is confirmed running and working + + +enable the service you chose to enable automatically at boot example + +systemctl enable relinker.service + +for repeater + +or + +systemctl enable relinkerhot.service + +for hotspot + + reboot +once you have rebooted check all is auto starting + you can tail the log file at the command prompt diff --git a/scripts/opt/script/install-relinker.sh b/scripts/opt/script/install-relinker.sh index 25b23e2..0bb8850 100644 --- a/scripts/opt/script/install-relinker.sh +++ b/scripts/opt/script/install-relinker.sh @@ -1,11 +1,17 @@ #!/bin/bash -cp DMRG*.tgz / + + + cd / +rm -rf DMRGa* +cd /opt +rm -rf script +cd /var/log +rm -rf script -tar -xvf DMRG* - - - - - +cd /boot +cp DMRGateway*.tgz / +cd / +tar -xvf DMRGateway*.tgz +systemctl daemon-reload diff --git a/scripts/opt/script/relink-hotspot.sh b/scripts/opt/script/relink-hotspot.sh index a1c9fcd..4221849 100644 --- a/scripts/opt/script/relink-hotspot.sh +++ b/scripts/opt/script/relink-hotspot.sh @@ -24,7 +24,7 @@ check_BM_API(){ #sed -n -e 's/^.*slot":2,"timeout"://p' /var/log/script/test3.txt > /var/log/script/test4.txt - sed -n -e 's/^.*slot":0,"timeout"://p' /Var/log/script/test3.txt > /var/log/script/test4.txt + sed -n -e 's/^.*slot":0,"timeout"://p' /var/log/script/test3.txt > /var/log/script/test4.txt sed 's/},{"repeaterid.*//' /var/log/script/test4.txt > /var/log/script/slot2.txt @@ -124,11 +124,14 @@ check_if_nothing_linked_slot2(){ check_BM_API echo -#check_status_slot1 -check_status_slot2 -#check_if_nothing_linked_slot1 -check_if_nothing_linked_slot2 -echo +$checkslot1 +$checkslot2 +$slot1notlinked +$slot2notlinked +echo +sleep $slowdown +/bin/bash /opt/script/relink-hotspot.sh >> /var/log/script/checkBMAPI.log 2>&1 + diff --git a/scripts/opt/script/relink-repeater.sh b/scripts/opt/script/relink-repeater.sh index 9e89601..d333513 100644 --- a/scripts/opt/script/relink-repeater.sh +++ b/scripts/opt/script/relink-repeater.sh @@ -124,12 +124,11 @@ check_if_nothing_linked_slot2(){ check_BM_API echo -check_status_slot1 -check_status_slot2 -check_if_nothing_linked_slot1 -check_if_nothing_linked_slot2 -echo +$checkslot1 +$checkslot2 +$slot1notlinked +$slot2notlinked echo -sleep 5 -#/opt/script/./check.sh >> /var/log/script/checkBMAPI.log +sleep $slowdown +/bin/bash /opt/script/relink-repeater.sh >> /var/log/script/checkBMAPI.log 2>&1 diff --git a/scripts/opt/script/script.conf b/scripts/opt/script/script.conf index 3e7d1c4..ab1bbf4 100644 --- a/scripts/opt/script/script.conf +++ b/scripts/opt/script/script.conf @@ -1,7 +1,20 @@ #!/usr/bin/bash -repeater=235192 -call=GB3IN -defaultslot1=23590 -defaultslot2=91 +repeater=234587501 +call=M0VUB +defaultslot1=0 +defaultslot2=2350 minrelinktimerslot1=30 minrelinktimerslot2=30 +slowdown=10 +checkslot1= +checkslot2=check_status_slot2 +slot1notlinked= +slot2notlinked=check_if_nothing_linked_slot2 + +#configuration above enabled to watch slot 2 only on a hotspot + +# add the lines as required you may only have 1 slot monitored on a repeater if thats + +# all using SUDO Reflectors Cant imagine why + + \ No newline at end of file diff --git a/scripts/var/log/script/test1.txt b/scripts/var/log/script/test1.txt index e69de29..4f60d09 100644 --- a/scripts/var/log/script/test1.txt +++ b/scripts/var/log/script/test1.txt @@ -0,0 +1 @@ +{"reflector":{"reflector":0,"interval":0,"active":4000},"blockedGroups":[],"staticSubscriptions":[{"talkgroup":91,"networkid":2341,"repeaterid":235192,"slot":2,"type":"tarantool"},{"talkgroup":23590,"networkid":2341,"repeaterid":235192,"slot":1,"type":"tarantool"}],"dynamicSubscriptions":[],"timedSubscriptions":[],"clusters":[]} \ No newline at end of file From 6be27b37593031ee514e7359c31835a47f4c9dca Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 22 Apr 2020 21:32:29 +0100 Subject: [PATCH 26/27] Remove unneeded files. --- scripts/opt/script/run-relinker-hotspot.sh | 8 -------- scripts/opt/script/run-relinker.sh | 8 -------- 2 files changed, 16 deletions(-) delete mode 100644 scripts/opt/script/run-relinker-hotspot.sh delete mode 100644 scripts/opt/script/run-relinker.sh diff --git a/scripts/opt/script/run-relinker-hotspot.sh b/scripts/opt/script/run-relinker-hotspot.sh deleted file mode 100644 index c48d5ab..0000000 --- a/scripts/opt/script/run-relinker-hotspot.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# This is just a nice way to start the script - - -while /bin/true; do - /opt/script/./relink-repeater-hotspot.sh >> /var/log/script/checkBMAPI.log 2>&1 -done & \ No newline at end of file diff --git a/scripts/opt/script/run-relinker.sh b/scripts/opt/script/run-relinker.sh deleted file mode 100644 index 160ca46..0000000 --- a/scripts/opt/script/run-relinker.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# This is just a nice way to start the script - - -while /bin/true; do - /opt/script/./relink-repeater.sh >> /var/log/script/checkBMAPI.log 2>&1 -done & \ No newline at end of file From 8e75b2453b93b32dd713a231e2f8c27dcfe806ab Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 23 Apr 2020 21:36:43 +0100 Subject: [PATCH 27/27] Update scripts. --- scripts/install-linker.sh | 21 ++++++++++++++++++ scripts/lib/systemd/system/relinker.service | 4 +++- .../lib/systemd/system/relinkerhot.service | 2 +- scripts/opt/script/README | 4 ++-- scripts/opt/script/install-relinker.sh | 17 -------------- scripts/opt/script/relink-hotspot.sh | 20 ++++++++++------- scripts/opt/script/relink-repeater.sh | 15 ++++++++++--- scripts/opt/script/script.conf | 14 ++++++------ scripts/opt/script/start.sh | 5 ++++- scripts/opt/script/var-log-script.tgz | Bin 2136 -> 205 bytes scripts/var/log/script/test1.txt | 1 - scripts/var/log/script/var-log-script.tgz | Bin 2136 -> 0 bytes 12 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 scripts/install-linker.sh delete mode 100644 scripts/opt/script/install-relinker.sh delete mode 100644 scripts/var/log/script/var-log-script.tgz diff --git a/scripts/install-linker.sh b/scripts/install-linker.sh new file mode 100644 index 0000000..636d7a4 --- /dev/null +++ b/scripts/install-linker.sh @@ -0,0 +1,21 @@ +#!/bin/bash + + + + +cd / +rm -rf DMRGa* +cd /opt +rm -rf script +cd /var/log +rm -rf script + +cd /boot +cp DMRGateway*.tgz / +cd / +tar -xvf DMRGateway*.tgz +systemctl daemon-reload +echo -n "" > /var/log/script/static-slot1.txt +echo -n "" > /var/log/script/static-slot2.txt +echo -n "" > /var/log/script/slot1.txt +echo -n "" > /var/log/script/slot2.txt diff --git a/scripts/lib/systemd/system/relinker.service b/scripts/lib/systemd/system/relinker.service index bd91ae7..69cb9a4 100644 --- a/scripts/lib/systemd/system/relinker.service +++ b/scripts/lib/systemd/system/relinker.service @@ -5,7 +5,9 @@ After=multi-user.target [Service] Type=idle -ExecStart=/bin/bash /opt/script/relink-repeater.sh >> /var/log/script/checkBMAPI.log 2>&1 +ExecStart=/bin/bash /opt/script/relink-repeater.sh + + [Install] diff --git a/scripts/lib/systemd/system/relinkerhot.service b/scripts/lib/systemd/system/relinkerhot.service index 4848676..4331bf1 100644 --- a/scripts/lib/systemd/system/relinkerhot.service +++ b/scripts/lib/systemd/system/relinkerhot.service @@ -5,7 +5,7 @@ After=multi-user.target [Service] Type=idle -ExecStart=/bin/bash /opt/script/relink-hotspot.sh >> /var/log/script/checkBMAPI.log 2>&1 +ExecStart=/bin/bash /opt/script/relink-hotspot.sh [Install] diff --git a/scripts/opt/script/README b/scripts/opt/script/README index e4865b7..b0e5eb2 100644 --- a/scripts/opt/script/README +++ b/scripts/opt/script/README @@ -4,7 +4,7 @@ DMR SUDO Reflector - TG -This is the first release version of the relinker scripts 3.1 +This is the first release version of the relinker scripts 3.2 @@ -48,7 +48,7 @@ Port=3769 -1. Copy the package DMRGateway-TGDynRewrite-relinker-3.1.tgz to the folder/boot and also the install-relinker.sh script supplied (you can do this with a card reader from windows if you like) +1. Copy the package DMRGateway-TGDynRewrite-relinker-3.2.tgz to the folder/boot and also the install-relinker.sh script supplied (you can do this with a card reader from windows if you like) 2. run /boot#./install-relinker which should create folders /opt/script/script and /var/log/script/various working files and logfile. it also sets up services in systemd diff --git a/scripts/opt/script/install-relinker.sh b/scripts/opt/script/install-relinker.sh deleted file mode 100644 index 0bb8850..0000000 --- a/scripts/opt/script/install-relinker.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - - - - -cd / -rm -rf DMRGa* -cd /opt -rm -rf script -cd /var/log -rm -rf script - -cd /boot -cp DMRGateway*.tgz / -cd / -tar -xvf DMRGateway*.tgz -systemctl daemon-reload diff --git a/scripts/opt/script/relink-hotspot.sh b/scripts/opt/script/relink-hotspot.sh index 4221849..c175e9a 100644 --- a/scripts/opt/script/relink-hotspot.sh +++ b/scripts/opt/script/relink-hotspot.sh @@ -3,6 +3,14 @@ source /opt/script/script.conf +exec 3>&1 4>&2 +trap 'exec 2>&4 1>&3' 0 1 2 3 +exec 1>/var/log/script/checkBMAPI.log 2>&1 + + + + + #check BM API @@ -121,7 +129,8 @@ check_if_nothing_linked_slot2(){ } - +while : +do check_BM_API echo $checkslot1 @@ -129,10 +138,5 @@ $checkslot2 $slot1notlinked $slot2notlinked echo -sleep $slowdown -/bin/bash /opt/script/relink-hotspot.sh >> /var/log/script/checkBMAPI.log 2>&1 - - - - - +sleep $slowdown +done \ No newline at end of file diff --git a/scripts/opt/script/relink-repeater.sh b/scripts/opt/script/relink-repeater.sh index d333513..6700195 100644 --- a/scripts/opt/script/relink-repeater.sh +++ b/scripts/opt/script/relink-repeater.sh @@ -3,6 +3,13 @@ source /opt/script/script.conf +exec 3>&1 4>&2 +trap 'exec 2>&4 1>&3' 0 1 2 3 +exec 1>/var/log/script/checkBMAPI.log 2>&1 + + + + #check BM API @@ -122,6 +129,9 @@ check_if_nothing_linked_slot2(){ } + +while : +do check_BM_API echo $checkslot1 @@ -129,6 +139,5 @@ $checkslot2 $slot1notlinked $slot2notlinked echo -sleep $slowdown -/bin/bash /opt/script/relink-repeater.sh >> /var/log/script/checkBMAPI.log 2>&1 - +sleep $slowdown +done diff --git a/scripts/opt/script/script.conf b/scripts/opt/script/script.conf index ab1bbf4..8736739 100644 --- a/scripts/opt/script/script.conf +++ b/scripts/opt/script/script.conf @@ -1,14 +1,14 @@ #!/usr/bin/bash -repeater=234587501 -call=M0VUB -defaultslot1=0 -defaultslot2=2350 +repeater=235192 +call=GB3IN +defaultslot1=23590 +defaultslot2=91 minrelinktimerslot1=30 minrelinktimerslot2=30 -slowdown=10 -checkslot1= +slowdown=0 +checkslot1=check_status_slot1 checkslot2=check_status_slot2 -slot1notlinked= +slot1notlinked=check_if_nothing_linked_slot1 slot2notlinked=check_if_nothing_linked_slot2 #configuration above enabled to watch slot 2 only on a hotspot diff --git a/scripts/opt/script/start.sh b/scripts/opt/script/start.sh index c56a620..5caca19 100644 --- a/scripts/opt/script/start.sh +++ b/scripts/opt/script/start.sh @@ -6,7 +6,10 @@ sleep 1 cd /var/log/script sleep 1 tar -xvf var-log-script.tgz - +echo -n "" > /var/log/script/static-slot1.txt +echo -n "" > /var/log/script/static-slot2.txt +echo -n "" > /var/log/script/slot1.txt +echo -n "" > /var/log/script/slot2.txt diff --git a/scripts/opt/script/var-log-script.tgz b/scripts/opt/script/var-log-script.tgz index 7f5a7fcc7457dc1a1a9035c6e68f6ae4d9b9c411..cac2dfb7f7cbed5b62b87387163ecc28f1e3b5f2 100644 GIT binary patch literal 205 zcmV;;05bm{iwFRsfT3Oh1MSw`3W6{gfZ<(=H&E<<*Avk}5Daudm*1Qc(LtfGvEY49 zrg);heA9H9l0BwJ67|T;TU*xbb1lcpcqerT#swkOd?p52@t$7pQ#y^qAjTNKzJp)a z|5VETO-KEmb4!0q{}$%{x~KleFa0(BTbTQ+j`|xfOMl1wH<6z{UC)Q<7VB*To8~|0 z++TaA=--GAx>sY;PBwMN`b>kV{KuP7y;Xm#{eHmM}U~(_AK( zrfkf0hum2?E^`?rm!>hRTy|Ec_ni0r>-TxS-_P^>e$VrKpWmaMDl4|`NbnMqTq@vV z@*rx=73+abMPxC3K|fetnZ1+*b{ugc)n+(ZkIQ9Oc@2S2#)rEVtTh&%8UbB>6F;IK zd$%$DX=410lFDMbHol2-Gv!lTo-;-Gc^U0aP_#}y?r?CHhiGeo@0K%~7FYDk{g1jq zvYHesRDI`#zV3HN@udz0Zup(#sxm4a^Y$yD9fRLimOQ!D+de(g@;c{FUZH!>Z5_@6 z1&lFk{ltW5fw@`YjqAfB)8i9Azi0t4Tc(zadlot#I;sR)=Xxp!1|KrH((b)8i5n8| zW%ix%V`K~pN;wn0j@=Er%y7!q_7qMs`HE!BI;ty`1~OjTa{N3cc;|O?Z_8lm?d?5Y zy+D;^JoDmjRi-3NuIx#(ON-lVOctU?f_ZXlFV$2tuCzrrZEYZ31M&0*5P5^|X%cj;~SJhAy{sfp^8{>Q|91%xRBqq_@@3cw?TNO3Il^ z1ga~v83d|H%?QWd_e2G&<_xz1M%$i*ms557k#AB7&Cn{Z6RfEHiF|O1Tv^~P;#E4~ za;LoDWQA&?0AJfy-#A?d08M$6Q(Zy|Z5!RB*9jA2?&WdOx#ecBdz}K_N0gppzll86 zZVz!LRx%=`AtOCM6?_0>uEf&O5l^YlEoV#5m;XxFa}fe>D6&V>?g&<~H7;-r-9YJv zGm*i-NkeWp?|U2B5SUo)fqyyf+qII&GP+kH|{nWUk- zVwi)}y;rSv#J;(ypw;AGS8c$LY!h(B2s=08x#L8QZPILWMicHUWDncs*6N|=hi3~U zB)RI7lh7E=r6#9+ZFN~NPB`S%2fs(ye6c|zv%V5>1q~LHZyX~(7iF5cOn}A33FJeU z36>S!lF;oq)9L?%*u)V}LkanjIM`zZ#$x145x`ut{hroF9fBpbJ^y)FioH_2{@fAB zC7zyzG1g-b2@<5Nah-&?#FMUz_2(h6Myx|>x2-G`Odi>5x`S(idYk$~`d1ULt!|!{ zeS(P71vp{*48imDFx*6Avw8CF{on1=9k>99bN#bOm0uXiE}GyS_iSb0Hv9Ol#NR)( zC%_)}FF}G_wc+l>KVT-8!L6RY`O`%R(al#Ah-HXmU7Gbjb;(z%nxa=4SuAVOr~n!6 z2hJq)0bA*z!q24tb|Z;{I>XNRA4EGTx;IU*AC=5embrI=m`MvvTmi>qb|*aTGyD-G zbolH5P8U?rZ)CPi5LaLiGW(shZJ;|yxMT9Ur%=`+Phd-DB~Pi&DZ}FxGVRgfoj{w` zrcRjcSX6Q+_q5Y*n5py zd^Os?`DIu!NeCiXpIWt9z3sqj{t2hcCvPQ`% zx4E-&Wvtk!~+A{VoCD>_q_Yri=VUflpro- z7oWZWwaLDKIZkMcmJK@tqWa9mXA&x@Nh75%uxc)ddvYBhqojW@`-Z?498;b71uW|O zD#Ie`7W)d0Wi}qoRa+6*x$fG_gK~M$vvuFf*nqBaqgoY}_A84hVqXbWW9jWh)hc4} zxwA5|BAzYc{|w3>U>OFe#tSCt>>CvCg53B)co#^P+k{*8GGG&fV8kVV(~rx=;FR5`MfPH8R3(Y4C8b^PJaAXE|xKPGxGVrB}SpaZDLl3 zaKEhBH{<%|!ZpF<^p(@Z8hC9~R0s0m_Oas(BZUV^GvlYUVx+Rc#@J&L-=`=6<}o#g zcJ+*~FoV9R9F`$&Sr4M&7;qio`F?OVBO2vgk&4h~X{}?yU#(4;otoTI z9=buz|K?^4*uD0Eft$A~2Yr}gFk5!<(?m%RN%ejAI_zR+I;{HlEia^MMm0kJ#51pw zkoDtk6fmGD<%xzKe=*2)qKlPd49n`BugXu0)r9JR2D1b0zEFzLE4|-$-GAx>sY;PBwMN`b>kV{KuP7y;Xm#{eHmM}U~(_AK( zrfkf0hum2?E^`?rm!>hRTy|Ec_ni0r>-TxS-_P^>e$VrKpWmaMDl4|`NbnMqTq@vV z@*rx=73+abMPxC3K|fetnZ1+*b{ugc)n+(ZkIQ9Oc@2S2#)rEVtTh&%8UbB>6F;IK zd$%$DX=410lFDMbHol2-Gv!lTo-;-Gc^U0aP_#}y?r?CHhiGeo@0K%~7FYDk{g1jq zvYHesRDI`#zV3HN@udz0Zup(#sxm4a^Y$yD9fRLimOQ!D+de(g@;c{FUZH!>Z5_@6 z1&lFk{ltW5fw@`YjqAfB)8i9Azi0t4Tc(zadlot#I;sR)=Xxp!1|KrH((b)8i5n8| zW%ix%V`K~pN;wn0j@=Er%y7!q_7qMs`HE!BI;ty`1~OjTa{N3cc;|O?Z_8lm?d?5Y zy+D;^JoDmjRi-3NuIx#(ON-lVOctU?f_ZXlFV$2tuCzrrZEYZ31M&0*5P5^|X%cj;~SJhAy{sfp^8{>Q|91%xRBqq_@@3cw?TNO3Il^ z1ga~v83d|H%?QWd_e2G&<_xz1M%$i*ms557k#AB7&Cn{Z6RfEHiF|O1Tv^~P;#E4~ za;LoDWQA&?0AJfy-#A?d08M$6Q(Zy|Z5!RB*9jA2?&WdOx#ecBdz}K_N0gppzll86 zZVz!LRx%=`AtOCM6?_0>uEf&O5l^YlEoV#5m;XxFa}fe>D6&V>?g&<~H7;-r-9YJv zGm*i-NkeWp?|U2B5SUo)fqyyf+qII&GP+kH|{nWUk- zVwi)}y;rSv#J;(ypw;AGS8c$LY!h(B2s=08x#L8QZPILWMicHUWDncs*6N|=hi3~U zB)RI7lh7E=r6#9+ZFN~NPB`S%2fs(ye6c|zv%V5>1q~LHZyX~(7iF5cOn}A33FJeU z36>S!lF;oq)9L?%*u)V}LkanjIM`zZ#$x145x`ut{hroF9fBpbJ^y)FioH_2{@fAB zC7zyzG1g-b2@<5Nah-&?#FMUz_2(h6Myx|>x2-G`Odi>5x`S(idYk$~`d1ULt!|!{ zeS(P71vp{*48imDFx*6Avw8CF{on1=9k>99bN#bOm0uXiE}GyS_iSb0Hv9Ol#NR)( zC%_)}FF}G_wc+l>KVT-8!L6RY`O`%R(al#Ah-HXmU7Gbjb;(z%nxa=4SuAVOr~n!6 z2hJq)0bA*z!q24tb|Z;{I>XNRA4EGTx;IU*AC=5embrI=m`MvvTmi>qb|*aTGyD-G zbolH5P8U?rZ)CPi5LaLiGW(shZJ;|yxMT9Ur%=`+Phd-DB~Pi&DZ}FxGVRgfoj{w` zrcRjcSX6Q+_q5Y*n5py zd^Os?`DIu!NeCiXpIWt9z3sqj{t2hcCvPQ`% zx4E-&Wvtk!~+A{VoCD>_q_Yri=VUflpro- z7oWZWwaLDKIZkMcmJK@tqWa9mXA&x@Nh75%uxc)ddvYBhqojW@`-Z?498;b71uW|O zD#Ie`7W)d0Wi}qoRa+6*x$fG_gK~M$vvuFf*nqBaqgoY}_A84hVqXbWW9jWh)hc4} zxwA5|BAzYc{|w3>U>OFe#tSCt>>CvCg53B)co#^P+k{*8GGG&fV8kVV(~rx=;FR5`MfPH8R3(Y4C8b^PJaAXE|xKPGxGVrB}SpaZDLl3 zaKEhBH{<%|!ZpF<^p(@Z8hC9~R0s0m_Oas(BZUV^GvlYUVx+Rc#@J&L-=`=6<}o#g zcJ+*~FoV9R9F`$&Sr4M&7;qio`F?OVBO2vgk&4h~X{}?yU#(4;otoTI z9=buz|K?^4*uD0Eft$A~2Yr}gFk5!<(?m%RN%ejAI_zR+I;{HlEia^MMm0kJ#51pw zkoDtk6fmGD<%xzKe=*2)qKlPd49n`BugXu0)r9JR2D1b0zEFzLE4|-$