Merge branch 'master' into IPv6

This commit is contained in:
Jonathan Naylor 2020-06-17 16:29:05 +01:00
commit d715ea6b4a
52 changed files with 2177 additions and 300 deletions

201
Conf.cpp
View file

@ -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
@ -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) :
@ -82,6 +83,7 @@ m_dmrNetwork1TGRewrites(),
m_dmrNetwork1PCRewrites(),
m_dmrNetwork1TypeRewrites(),
m_dmrNetwork1SrcRewrites(),
m_dmrNetwork1TGDynRewrites(),
m_dmrNetwork1IdRewrites(),
m_dmrNetwork1PassAllPC(),
m_dmrNetwork1PassAllTG(),
@ -99,6 +101,7 @@ m_dmrNetwork2TGRewrites(),
m_dmrNetwork2PCRewrites(),
m_dmrNetwork2TypeRewrites(),
m_dmrNetwork2SrcRewrites(),
m_dmrNetwork2TGDynRewrites(),
m_dmrNetwork2IdRewrites(),
m_dmrNetwork2PassAllPC(),
m_dmrNetwork2PassAllTG(),
@ -116,6 +119,7 @@ m_dmrNetwork3TGRewrites(),
m_dmrNetwork3PCRewrites(),
m_dmrNetwork3TypeRewrites(),
m_dmrNetwork3SrcRewrites(),
m_dmrNetwork3TGDynRewrites(),
m_dmrNetwork3IdRewrites(),
m_dmrNetwork3PassAllPC(),
m_dmrNetwork3PassAllTG(),
@ -133,6 +137,7 @@ m_dmrNetwork4TGRewrites(),
m_dmrNetwork4PCRewrites(),
m_dmrNetwork4TypeRewrites(),
m_dmrNetwork4SrcRewrites(),
m_dmrNetwork4TGDynRewrites(),
m_dmrNetwork4IdRewrites(),
m_dmrNetwork4PassAllPC(),
m_dmrNetwork4PassAllTG(),
@ -150,6 +155,7 @@ m_dmrNetwork5TGRewrites(),
m_dmrNetwork5PCRewrites(),
m_dmrNetwork5TypeRewrites(),
m_dmrNetwork5SrcRewrites(),
m_dmrNetwork5TGDynRewrites(),
m_dmrNetwork5IdRewrites(),
m_dmrNetwork5PassAllPC(),
m_dmrNetwork5PassAllTG(),
@ -167,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)
{
}
@ -211,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;
@ -376,13 +386,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) {
@ -400,6 +412,31 @@ bool CConf::read()
rewrite.m_range = ::atoi(p5);
m_dmrNetwork1SrcRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "TGDynRewrite", 12U) == 0) {
std::vector<char*> 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* 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);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discPC = ::atoi(p3);
rewrite.m_statusPC = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
for (std::vector<char*>::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) {
char* rfId = ::strtok(value, ", ");
char* netId = ::strtok(NULL, " \r\n");
@ -471,13 +508,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) {
@ -495,6 +534,31 @@ bool CConf::read()
rewrite.m_range = ::atoi(p5);
m_dmrNetwork2SrcRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "TGDynRewrite", 12U) == 0) {
std::vector<char*> 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* 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);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discPC = ::atoi(p3);
rewrite.m_statusPC = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
for (std::vector<char*>::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) {
char* rfId = ::strtok(value, ", ");
char* netId = ::strtok(NULL, " \r\n");
@ -566,13 +630,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) {
@ -590,6 +656,31 @@ bool CConf::read()
rewrite.m_range = ::atoi(p5);
m_dmrNetwork3SrcRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "TGDynRewrite", 12U) == 0) {
std::vector<char*> 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* 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);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discPC = ::atoi(p3);
rewrite.m_statusPC = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
for (std::vector<char*>::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) {
char* rfId = ::strtok(value, ", ");
char* netId = ::strtok(NULL, " \r\n");
@ -661,13 +752,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) {
@ -685,6 +778,31 @@ bool CConf::read()
rewrite.m_range = ::atoi(p5);
m_dmrNetwork4SrcRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "TGDynRewrite", 12U) == 0) {
std::vector<char*> 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* 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);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discPC = ::atoi(p3);
rewrite.m_statusPC = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
for (std::vector<char*>::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) {
char* rfId = ::strtok(value, ", ");
char* netId = ::strtok(NULL, " \r\n");
@ -756,13 +874,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) {
@ -780,6 +900,31 @@ bool CConf::read()
rewrite.m_range = ::atoi(p5);
m_dmrNetwork5SrcRewrites.push_back(rewrite);
}
} else if (::strncmp(key, "TGDynRewrite", 12U) == 0) {
std::vector<char*> 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* 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);
rewrite.m_fromTG = ::atoi(p2);
rewrite.m_discPC = ::atoi(p3);
rewrite.m_statusPC = ::atoi(p4);
rewrite.m_toTG = ::atoi(p5);
rewrite.m_range = ::atoi(p6);
for (std::vector<char*>::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) {
char* rfId = ::strtok(value, ", ");
char* netId = ::strtok(NULL, " \r\n");
@ -796,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);
}
}
@ -1080,6 +1230,11 @@ std::vector<CSrcRewriteStruct> CConf::getDMRNetwork1SrcRewrites() const
return m_dmrNetwork1SrcRewrites;
}
std::vector<CTGDynRewriteStruct> CConf::getDMRNetwork1TGDynRewrites() const
{
return m_dmrNetwork1TGDynRewrites;
}
std::vector<CIdRewriteStruct> CConf::getDMRNetwork1IdRewrites() const
{
return m_dmrNetwork1IdRewrites;
@ -1168,6 +1323,11 @@ std::vector<CSrcRewriteStruct> CConf::getDMRNetwork2SrcRewrites() const
return m_dmrNetwork2SrcRewrites;
}
std::vector<CTGDynRewriteStruct> CConf::getDMRNetwork2TGDynRewrites() const
{
return m_dmrNetwork2TGDynRewrites;
}
std::vector<CIdRewriteStruct> CConf::getDMRNetwork2IdRewrites() const
{
return m_dmrNetwork2IdRewrites;
@ -1256,6 +1416,11 @@ std::vector<CSrcRewriteStruct> CConf::getDMRNetwork3SrcRewrites() const
return m_dmrNetwork3SrcRewrites;
}
std::vector<CTGDynRewriteStruct> CConf::getDMRNetwork3TGDynRewrites() const
{
return m_dmrNetwork3TGDynRewrites;
}
std::vector<CIdRewriteStruct> CConf::getDMRNetwork3IdRewrites() const
{
return m_dmrNetwork3IdRewrites;
@ -1344,6 +1509,11 @@ std::vector<CSrcRewriteStruct> CConf::getDMRNetwork4SrcRewrites() const
return m_dmrNetwork4SrcRewrites;
}
std::vector<CTGDynRewriteStruct> CConf::getDMRNetwork4TGDynRewrites() const
{
return m_dmrNetwork4TGDynRewrites;
}
std::vector<CIdRewriteStruct> CConf::getDMRNetwork4IdRewrites() const
{
return m_dmrNetwork4IdRewrites;
@ -1432,6 +1602,11 @@ std::vector<CSrcRewriteStruct> CConf::getDMRNetwork5SrcRewrites() const
return m_dmrNetwork5SrcRewrites;
}
std::vector<CTGDynRewriteStruct> CConf::getDMRNetwork5TGDynRewrites() const
{
return m_dmrNetwork5TGDynRewrites;
}
std::vector<CIdRewriteStruct> CConf::getDMRNetwork5IdRewrites() const
{
return m_dmrNetwork5IdRewrites;
@ -1446,3 +1621,13 @@ std::vector<unsigned int> CConf::getDMRNetwork5PassAllTG() const
{
return m_dmrNetwork5PassAllTG;
}
bool CConf::getDynamicTGControlEnabled() const
{
return m_dynamicTGControlEnabled;
}
unsigned int CConf::getDynamicTGControlPort() const
{
return m_dynamicTGControlPort;
}

170
Conf.h
View file

@ -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
@ -43,6 +43,7 @@ struct CTypeRewriteStruct {
unsigned int m_fromTG;
unsigned int m_toSlot;
unsigned int m_toId;
unsigned int m_range;
};
struct CSrcRewriteStruct {
@ -53,6 +54,16 @@ struct CSrcRewriteStruct {
unsigned int m_range;
};
struct CTGDynRewriteStruct {
unsigned int m_slot;
unsigned int m_fromTG;
unsigned int m_discPC;
unsigned int m_statusPC;
unsigned int m_toTG;
unsigned int m_range;
std::vector<unsigned int> m_exclTGs;
};
struct CIdRewriteStruct {
unsigned int m_rfId;
unsigned int m_netId;
@ -111,13 +122,14 @@ public:
std::string getDMRNetwork1Options() const;
bool getDMRNetwork1Location() const;
bool getDMRNetwork1Debug() const;
std::vector<CTGRewriteStruct> getDMRNetwork1TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork1PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork1TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork1SrcRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork1IdRewrites() const;
std::vector<unsigned int> getDMRNetwork1PassAllPC() const;
std::vector<unsigned int> getDMRNetwork1PassAllTG() const;
std::vector<CTGRewriteStruct> getDMRNetwork1TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork1PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork1TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork1SrcRewrites() const;
std::vector<CTGDynRewriteStruct> getDMRNetwork1TGDynRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork1IdRewrites() const;
std::vector<unsigned int> getDMRNetwork1PassAllPC() const;
std::vector<unsigned int> getDMRNetwork1PassAllTG() const;
// The DMR Network 2 section
bool getDMRNetwork2Enabled() const;
@ -130,13 +142,14 @@ public:
std::string getDMRNetwork2Options() const;
bool getDMRNetwork2Location() const;
bool getDMRNetwork2Debug() const;
std::vector<CTGRewriteStruct> getDMRNetwork2TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork2PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork2TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork2SrcRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork2IdRewrites() const;
std::vector<unsigned int> getDMRNetwork2PassAllPC() const;
std::vector<unsigned int> getDMRNetwork2PassAllTG() const;
std::vector<CTGRewriteStruct> getDMRNetwork2TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork2PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork2TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork2SrcRewrites() const;
std::vector<CTGDynRewriteStruct> getDMRNetwork2TGDynRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork2IdRewrites() const;
std::vector<unsigned int> getDMRNetwork2PassAllPC() const;
std::vector<unsigned int> getDMRNetwork2PassAllTG() const;
// The DMR Network 3 section
bool getDMRNetwork3Enabled() const;
@ -149,13 +162,14 @@ public:
std::string getDMRNetwork3Options() const;
bool getDMRNetwork3Location() const;
bool getDMRNetwork3Debug() const;
std::vector<CTGRewriteStruct> getDMRNetwork3TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork3PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork3TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork3SrcRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork3IdRewrites() const;
std::vector<unsigned int> getDMRNetwork3PassAllPC() const;
std::vector<unsigned int> getDMRNetwork3PassAllTG() const;
std::vector<CTGRewriteStruct> getDMRNetwork3TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork3PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork3TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork3SrcRewrites() const;
std::vector<CTGDynRewriteStruct> getDMRNetwork3TGDynRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork3IdRewrites() const;
std::vector<unsigned int> getDMRNetwork3PassAllPC() const;
std::vector<unsigned int> getDMRNetwork3PassAllTG() const;
// The DMR Network 4 section
bool getDMRNetwork4Enabled() const;
@ -168,13 +182,14 @@ public:
std::string getDMRNetwork4Options() const;
bool getDMRNetwork4Location() const;
bool getDMRNetwork4Debug() const;
std::vector<CTGRewriteStruct> getDMRNetwork4TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork4PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork4TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork4SrcRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork4IdRewrites() const;
std::vector<unsigned int> getDMRNetwork4PassAllPC() const;
std::vector<unsigned int> getDMRNetwork4PassAllTG() const;
std::vector<CTGRewriteStruct> getDMRNetwork4TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork4PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork4TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork4SrcRewrites() const;
std::vector<CTGDynRewriteStruct> getDMRNetwork4TGDynRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork4IdRewrites() const;
std::vector<unsigned int> getDMRNetwork4PassAllPC() const;
std::vector<unsigned int> getDMRNetwork4PassAllTG() const;
// The DMR Network 5 section
bool getDMRNetwork5Enabled() const;
@ -187,13 +202,14 @@ public:
std::string getDMRNetwork5Options() const;
bool getDMRNetwork5Location() const;
bool getDMRNetwork5Debug() const;
std::vector<CTGRewriteStruct> getDMRNetwork5TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork5PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork5TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork5SrcRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork5IdRewrites() const;
std::vector<unsigned int> getDMRNetwork5PassAllPC() const;
std::vector<unsigned int> getDMRNetwork5PassAllTG() const;
std::vector<CTGRewriteStruct> getDMRNetwork5TGRewrites() const;
std::vector<CPCRewriteStruct> getDMRNetwork5PCRewrites() const;
std::vector<CTypeRewriteStruct> getDMRNetwork5TypeRewrites() const;
std::vector<CSrcRewriteStruct> getDMRNetwork5SrcRewrites() const;
std::vector<CTGDynRewriteStruct> getDMRNetwork5TGDynRewrites() const;
std::vector<CIdRewriteStruct> getDMRNetwork5IdRewrites() const;
std::vector<unsigned int> getDMRNetwork5PassAllPC() const;
std::vector<unsigned int> getDMRNetwork5PassAllTG() const;
// The XLX Network section
bool getXLXNetworkEnabled() const;
@ -212,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;
@ -254,13 +274,14 @@ private:
std::string m_dmrNetwork1Options;
bool m_dmrNetwork1Location;
bool m_dmrNetwork1Debug;
std::vector<CTGRewriteStruct> m_dmrNetwork1TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork1PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork1TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork1SrcRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork1IdRewrites;
std::vector<unsigned int> m_dmrNetwork1PassAllPC;
std::vector<unsigned int> m_dmrNetwork1PassAllTG;
std::vector<CTGRewriteStruct> m_dmrNetwork1TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork1PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork1TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork1SrcRewrites;
std::vector<CTGDynRewriteStruct> m_dmrNetwork1TGDynRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork1IdRewrites;
std::vector<unsigned int> m_dmrNetwork1PassAllPC;
std::vector<unsigned int> m_dmrNetwork1PassAllTG;
bool m_dmrNetwork2Enabled;
std::string m_dmrNetwork2Name;
@ -272,13 +293,14 @@ private:
std::string m_dmrNetwork2Options;
bool m_dmrNetwork2Location;
bool m_dmrNetwork2Debug;
std::vector<CTGRewriteStruct> m_dmrNetwork2TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork2PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork2TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork2SrcRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork2IdRewrites;
std::vector<unsigned int> m_dmrNetwork2PassAllPC;
std::vector<unsigned int> m_dmrNetwork2PassAllTG;
std::vector<CTGRewriteStruct> m_dmrNetwork2TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork2PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork2TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork2SrcRewrites;
std::vector<CTGDynRewriteStruct> m_dmrNetwork2TGDynRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork2IdRewrites;
std::vector<unsigned int> m_dmrNetwork2PassAllPC;
std::vector<unsigned int> m_dmrNetwork2PassAllTG;
bool m_dmrNetwork3Enabled;
std::string m_dmrNetwork3Name;
@ -290,13 +312,14 @@ private:
std::string m_dmrNetwork3Options;
bool m_dmrNetwork3Location;
bool m_dmrNetwork3Debug;
std::vector<CTGRewriteStruct> m_dmrNetwork3TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork3PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork3TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork3SrcRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork3IdRewrites;
std::vector<unsigned int> m_dmrNetwork3PassAllPC;
std::vector<unsigned int> m_dmrNetwork3PassAllTG;
std::vector<CTGRewriteStruct> m_dmrNetwork3TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork3PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork3TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork3SrcRewrites;
std::vector<CTGDynRewriteStruct> m_dmrNetwork3TGDynRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork3IdRewrites;
std::vector<unsigned int> m_dmrNetwork3PassAllPC;
std::vector<unsigned int> m_dmrNetwork3PassAllTG;
bool m_dmrNetwork4Enabled;
std::string m_dmrNetwork4Name;
@ -308,13 +331,14 @@ private:
std::string m_dmrNetwork4Options;
bool m_dmrNetwork4Location;
bool m_dmrNetwork4Debug;
std::vector<CTGRewriteStruct> m_dmrNetwork4TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork4PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork4TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork4SrcRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork4IdRewrites;
std::vector<unsigned int> m_dmrNetwork4PassAllPC;
std::vector<unsigned int> m_dmrNetwork4PassAllTG;
std::vector<CTGRewriteStruct> m_dmrNetwork4TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork4PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork4TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork4SrcRewrites;
std::vector<CTGDynRewriteStruct> m_dmrNetwork4TGDynRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork4IdRewrites;
std::vector<unsigned int> m_dmrNetwork4PassAllPC;
std::vector<unsigned int> m_dmrNetwork4PassAllTG;
bool m_dmrNetwork5Enabled;
std::string m_dmrNetwork5Name;
@ -326,13 +350,14 @@ private:
std::string m_dmrNetwork5Options;
bool m_dmrNetwork5Location;
bool m_dmrNetwork5Debug;
std::vector<CTGRewriteStruct> m_dmrNetwork5TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork5PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork5TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork5SrcRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork5IdRewrites;
std::vector<unsigned int> m_dmrNetwork5PassAllPC;
std::vector<unsigned int> m_dmrNetwork5PassAllTG;
std::vector<CTGRewriteStruct> m_dmrNetwork5TGRewrites;
std::vector<CPCRewriteStruct> m_dmrNetwork5PCRewrites;
std::vector<CTypeRewriteStruct> m_dmrNetwork5TypeRewrites;
std::vector<CSrcRewriteStruct> m_dmrNetwork5SrcRewrites;
std::vector<CTGDynRewriteStruct> m_dmrNetwork5TGDynRewrites;
std::vector<CIdRewriteStruct> m_dmrNetwork5IdRewrites;
std::vector<unsigned int> m_dmrNetwork5PassAllPC;
std::vector<unsigned int> m_dmrNetwork5PassAllTG;
bool m_xlxNetworkEnabled;
unsigned int m_xlxNetworkId;
@ -349,6 +374,9 @@ private:
bool m_xlxNetworkDebug;
bool m_xlxNetworkUserControl;
char m_xlxNetworkModule;
bool m_dynamicTGControlEnabled;
unsigned int m_dynamicTGControlPort;
};
#endif

View file

@ -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
@ -27,10 +27,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"
@ -71,7 +71,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)
{
@ -178,7 +178,10 @@ m_dmr1Passalls(),
m_dmr2Passalls(),
m_dmr3Passalls(),
m_dmr4Passalls(),
m_dmr5Passalls()
m_dmr5Passalls(),
m_dynVoices(),
m_dynRF(),
m_socket(NULL)
{
m_status = new DMRGW_STATUS[3U];
m_status[1U] = DMRGWS_NONE;
@ -199,10 +202,10 @@ CDMRGateway::~CDMRGateway()
delete *it;
for (std::vector<CRewrite*>::iterator it = m_dmr2NetRewrites.begin(); it != m_dmr2NetRewrites.end(); ++it)
delete *it;
delete *it;
for (std::vector<CRewrite*>::iterator it = m_dmr2RFRewrites.begin(); it != m_dmr2RFRewrites.end(); ++it)
delete *it;
delete *it;
for (std::vector<CRewrite*>::iterator it = m_dmr2SrcRewrites.begin(); it != m_dmr2SrcRewrites.end(); ++it)
delete *it;
@ -249,6 +252,9 @@ CDMRGateway::~CDMRGateway()
for (std::vector<CRewrite*>::iterator it = m_dmr5Passalls.begin(); it != m_dmr5Passalls.end(); ++it)
delete *it;
for (std::vector<CDynVoice*>::iterator it = m_dynVoices.begin(); it != m_dynVoices.end(); ++it)
delete* it;
delete m_rptRewrite;
delete m_xlxRewrite;
@ -368,6 +374,32 @@ int CDMRGateway::run()
bool ruleTrace = m_conf.getRuleTrace();
LogInfo("Rule trace: %s", ruleTrace ? "yes" : "no");
if (m_conf.getXLXNetworkEnabled()) {
ret = createXLXNetwork();
if (!ret)
return 1;
}
CXLXVoice* xlxVoice = NULL;
if (m_conf.getVoiceEnabled()) {
std::string language = m_conf.getVoiceLanguage();
std::string directory = m_conf.getVoiceDirectory();
LogInfo("Voice Parameters");
LogInfo(" Enabled: yes");
LogInfo(" Language: %s", language.c_str());
LogInfo(" Directory: %s", directory.c_str());
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;
}
}
}
if (m_conf.getDMRNetwork1Enabled()) {
ret = createDMRNetwork1();
if (!ret)
@ -398,8 +430,8 @@ int CDMRGateway::run()
return 1;
}
if (m_conf.getXLXNetworkEnabled()) {
ret = createXLXNetwork();
if (m_conf.getDynamicTGControlEnabled()) {
bool ret = createDynamicTGControl();
if (!ret)
return 1;
}
@ -407,24 +439,6 @@ int CDMRGateway::run()
unsigned int rfTimeout = m_conf.getRFTimeout();
unsigned int netTimeout = m_conf.getNetTimeout();
CVoice* voice = NULL;
if (m_conf.getVoiceEnabled() && m_xlxNetwork != NULL) {
std::string language = m_conf.getVoiceLanguage();
std::string directory = m_conf.getVoiceDirectory();
LogInfo("Voice Parameters");
LogInfo(" Enabled: yes");
LogInfo(" Language: %s", language.c_str());
LogInfo(" Directory: %s", directory.c_str());
voice = new CVoice(directory, language, m_repeater->getId(), m_xlxSlot, m_xlxTG);
bool ret = voice->open();
if (!ret) {
delete voice;
voice = NULL;
}
}
CTimer* timer[3U];
timer[1U] = new CTimer(1000U);
timer[2U] = new CTimer(1000U);
@ -466,18 +480,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;
@ -489,8 +503,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();
@ -521,11 +535,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);
}
}
}
@ -578,16 +592,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();
}
}
}
@ -613,19 +627,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<CRewrite*>::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);
@ -636,18 +650,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<CRewrite*>::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);
@ -659,18 +673,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<CRewrite*>::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);
@ -682,18 +696,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<CRewrite*>::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);
@ -705,18 +719,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<CRewrite*>::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);
@ -728,17 +742,17 @@ int CDMRGateway::run()
}
}
if (!rewritten) {
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork1 != NULL) {
for (std::vector<CRewrite*>::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);
@ -750,17 +764,17 @@ int CDMRGateway::run()
}
}
if (!rewritten) {
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork2 != NULL) {
for (std::vector<CRewrite*>::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);
@ -772,17 +786,17 @@ int CDMRGateway::run()
}
}
if (!rewritten) {
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork3 != NULL) {
for (std::vector<CRewrite*>::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);
@ -794,17 +808,17 @@ int CDMRGateway::run()
}
}
if (!rewritten) {
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork4 != NULL) {
for (std::vector<CRewrite*>::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);
@ -816,17 +830,17 @@ int CDMRGateway::run()
}
}
if (!rewritten) {
if (result == RESULT_UNMATCHED) {
if (m_dmrNetwork5 != NULL) {
for (std::vector<CRewrite*>::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);
@ -838,7 +852,7 @@ int CDMRGateway::run()
}
}
if (!rewritten && trace)
if (result == RESULT_UNMATCHED && trace)
LogDebug("Rule Trace,\tnot matched so rejected");
}
}
@ -895,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<CRewriteDynTGRF*>::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);
@ -943,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<CRewriteDynTGRF*>::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);
@ -991,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<CRewriteDynTGRF*>::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);
@ -1039,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<CRewriteDynTGRF*>::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);
@ -1087,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<CRewriteDynTGRF*>::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);
@ -1109,8 +1133,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;
@ -1119,6 +1143,15 @@ int CDMRGateway::run()
}
}
for (std::vector<CDynVoice*>::iterator it = m_dynVoices.begin(); it != m_dynVoices.end(); ++it) {
ret = (*it)->read(data);
if (ret)
m_repeater->write(data);
}
if (m_socket != NULL)
processDynamicTGControl();
unsigned int ms = stopWatch.elapsed();
stopWatch.start();
@ -1147,8 +1180,11 @@ int CDMRGateway::run()
if (m_xlxReflectors != NULL)
m_xlxReflectors->clock(ms);
if (voice != NULL)
voice->clock(ms);
if (xlxVoice != NULL)
xlxVoice->clock(ms);
for (std::vector<CDynVoice*>::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);
@ -1162,7 +1198,7 @@ int CDMRGateway::run()
CThread::sleep(10U);
}
delete voice;
delete xlxVoice;
m_repeater->close();
delete m_repeater;
@ -1197,6 +1233,11 @@ int CDMRGateway::run()
delete m_xlxNetwork;
}
if (m_socket != NULL) {
m_socket->close();
delete m_socket;
}
delete timer[1U];
delete timer[2U];
@ -1314,9 +1355,12 @@ bool CDMRGateway::createDMRNetwork1()
std::vector<CTypeRewriteStruct> typeRewrites = m_conf.getDMRNetwork1TypeRewrites();
for (std::vector<CTypeRewriteStruct>::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);
}
@ -1333,6 +1377,33 @@ bool CDMRGateway::createDMRNetwork1()
m_dmr1NetRewrites.push_back(rewrite);
}
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork1TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::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) (%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()) {
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, (*it).m_exclTGs, netRewriteDynTG, voice);
m_dmr1RFRewrites.push_back(rfRewriteDynTG);
m_dmr1NetRewrites.push_back(netRewriteDynTG);
m_dynRF.push_back(rfRewriteDynTG);
}
std::vector<CIdRewriteStruct> idRewrites = m_conf.getDMRNetwork1IdRewrites();
for (std::vector<CIdRewriteStruct>::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) {
LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId);
@ -1452,9 +1523,12 @@ bool CDMRGateway::createDMRNetwork2()
std::vector<CTypeRewriteStruct> typeRewrites = m_conf.getDMRNetwork2TypeRewrites();
for (std::vector<CTypeRewriteStruct>::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);
}
@ -1471,6 +1545,33 @@ bool CDMRGateway::createDMRNetwork2()
m_dmr2NetRewrites.push_back(rewrite);
}
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork2TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::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) (%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()) {
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, (*it).m_exclTGs, netRewriteDynTG, voice);
m_dmr2RFRewrites.push_back(rfRewriteDynTG);
m_dmr2NetRewrites.push_back(netRewriteDynTG);
m_dynRF.push_back(rfRewriteDynTG);
}
std::vector<CIdRewriteStruct> idRewrites = m_conf.getDMRNetwork2IdRewrites();
for (std::vector<CIdRewriteStruct>::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) {
LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId);
@ -1590,9 +1691,12 @@ bool CDMRGateway::createDMRNetwork3()
std::vector<CTypeRewriteStruct> typeRewrites = m_conf.getDMRNetwork3TypeRewrites();
for (std::vector<CTypeRewriteStruct>::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);
}
@ -1609,6 +1713,33 @@ bool CDMRGateway::createDMRNetwork3()
m_dmr3NetRewrites.push_back(rewrite);
}
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork3TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::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) (%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()) {
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, (*it).m_exclTGs, netRewriteDynTG, voice);
m_dmr3RFRewrites.push_back(rfRewriteDynTG);
m_dmr3NetRewrites.push_back(netRewriteDynTG);
m_dynRF.push_back(rfRewriteDynTG);
}
std::vector<CIdRewriteStruct> idRewrites = m_conf.getDMRNetwork3IdRewrites();
for (std::vector<CIdRewriteStruct>::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) {
LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId);
@ -1728,9 +1859,12 @@ bool CDMRGateway::createDMRNetwork4()
std::vector<CTypeRewriteStruct> typeRewrites = m_conf.getDMRNetwork4TypeRewrites();
for (std::vector<CTypeRewriteStruct>::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);
}
@ -1747,6 +1881,33 @@ bool CDMRGateway::createDMRNetwork4()
m_dmr4NetRewrites.push_back(rewrite);
}
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork4TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::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) (%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()) {
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, (*it).m_exclTGs, netRewriteDynTG, voice);
m_dmr4RFRewrites.push_back(rfRewriteDynTG);
m_dmr4NetRewrites.push_back(netRewriteDynTG);
m_dynRF.push_back(rfRewriteDynTG);
}
std::vector<CIdRewriteStruct> idRewrites = m_conf.getDMRNetwork4IdRewrites();
for (std::vector<CIdRewriteStruct>::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) {
LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId);
@ -1866,9 +2027,12 @@ bool CDMRGateway::createDMRNetwork5()
std::vector<CTypeRewriteStruct> typeRewrites = m_conf.getDMRNetwork5TypeRewrites();
for (std::vector<CTypeRewriteStruct>::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);
}
@ -1885,6 +2049,33 @@ bool CDMRGateway::createDMRNetwork5()
m_dmr5NetRewrites.push_back(rewrite);
}
std::vector<CTGDynRewriteStruct> dynRewrites = m_conf.getDMRNetwork5TGDynRewrites();
for (std::vector<CTGDynRewriteStruct>::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) (%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()) {
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, (*it).m_exclTGs, netRewriteDynTG, voice);
m_dmr5RFRewrites.push_back(rfRewriteDynTG);
m_dmr5NetRewrites.push_back(netRewriteDynTG);
m_dynRF.push_back(rfRewriteDynTG);
}
std::vector<CIdRewriteStruct> idRewrites = m_conf.getDMRNetwork5IdRewrites();
for (std::vector<CIdRewriteStruct>::const_iterator it = idRewrites.begin(); it != idRewrites.end(); ++it) {
LogInfo(" Rewrite Id: %u <-> %u", (*it).m_rfId, (*it).m_netId);
@ -1991,6 +2182,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);
@ -2233,3 +2440,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<CRewriteDynTGRF*>::iterator it = m_dynRF.begin(); it != m_dynRF.end(); ++it)
(*it)->tgChange(slot, tg);
} else {
LogWarning("Unknown dynamic TG control message: %s", buffer);
}
}

View file

@ -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
@ -20,10 +20,14 @@
#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"
#include "Timer.h"
#include "Conf.h"
@ -104,6 +108,9 @@ private:
std::vector<CRewrite*> m_dmr3Passalls;
std::vector<CRewrite*> m_dmr4Passalls;
std::vector<CRewrite*> m_dmr5Passalls;
std::vector<CDynVoice*> m_dynVoices;
std::vector<CRewriteDynTGRF*> m_dynRF;
CUDPSocket* m_socket;
bool createMMDVM();
bool createDMRNetwork1();
@ -112,6 +119,7 @@ private:
bool createDMRNetwork4();
bool createDMRNetwork5();
bool createXLXNetwork();
bool createDynamicTGControl();
bool linkXLX(unsigned int number);
void unlinkXLX();
@ -124,6 +132,7 @@ private:
void processRadioPosition();
void processTalkerAlias();
void processHomePosition();
void processDynamicTGControl();
};
#endif

View file

@ -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 90-999999 to TG9 to emulate reflector behaviour
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
@ -134,3 +136,7 @@ TGRewrite=2,11,2,11,1
Password=PASSWORD
Location=0
Debug=0
[Dynamic TG Control]
Enabled=1
Port=3769

View file

@ -22,32 +22,32 @@
<ProjectGuid>{862A3182-C71A-4B01-B58D-5F0725927A56}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>DMRGateway</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
@ -166,6 +166,7 @@
<ClInclude Include="DMRLC.h" />
<ClInclude Include="DMRNetwork.h" />
<ClInclude Include="DMRSlotType.h" />
<ClInclude Include="DynVoice.h" />
<ClInclude Include="Golay2087.h" />
<ClInclude Include="Hamming.h" />
<ClInclude Include="Log.h" />
@ -177,6 +178,8 @@
<ClInclude Include="RepeaterProtocol.h" />
<ClInclude Include="Rewrite.h" />
<ClInclude Include="RewriteDstId.h" />
<ClInclude Include="RewriteDynTGNet.h" />
<ClInclude Include="RewriteDynTGRF.h" />
<ClInclude Include="RewritePC.h" />
<ClInclude Include="RewriteSrc.h" />
<ClInclude Include="RewriteSrcId.h" />
@ -192,7 +195,7 @@
<ClInclude Include="UDPSocket.h" />
<ClInclude Include="Utils.h" />
<ClInclude Include="Version.h" />
<ClInclude Include="Voice.h" />
<ClInclude Include="XLXVoice.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="BPTC19696.cpp" />
@ -208,6 +211,7 @@
<ClCompile Include="DMRLC.cpp" />
<ClCompile Include="DMRNetwork.cpp" />
<ClCompile Include="DMRSlotType.cpp" />
<ClCompile Include="DynVoice.cpp" />
<ClCompile Include="Golay2087.cpp" />
<ClCompile Include="Hamming.cpp" />
<ClCompile Include="Log.cpp" />
@ -219,6 +223,8 @@
<ClCompile Include="RepeaterProtocol.cpp" />
<ClCompile Include="Rewrite.cpp" />
<ClCompile Include="RewriteDstId.cpp" />
<ClCompile Include="RewriteDynTGNet.cpp" />
<ClCompile Include="RewriteDynTGRF.cpp" />
<ClCompile Include="RewritePC.cpp" />
<ClCompile Include="RewriteSrc.cpp" />
<ClCompile Include="RewriteSrcId.cpp" />
@ -232,7 +238,7 @@
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="Utils.cpp" />
<ClCompile Include="Voice.cpp" />
<ClCompile Include="XLXVoice.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -95,9 +95,6 @@
<ClInclude Include="QR1676.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Voice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RewriteTG.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -134,6 +131,18 @@
<ClInclude Include="Reflectors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RewriteDynTGNet.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RewriteDynTGRF.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="XLXVoice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DynVoice.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Conf.cpp">
@ -211,9 +220,6 @@
<ClCompile Include="QR1676.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Voice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RewriteTG.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -250,5 +256,17 @@
<ClCompile Include="Reflectors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RewriteDynTGNet.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RewriteDynTGRF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XLXVoice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DynVoice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

349
DynVoice.cpp Normal file
View file

@ -0,0 +1,349 @@
/*
* 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 <cstring>
#include <cstdlib>
#include <sys/stat.h>
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, unsigned int slot, unsigned int tg) :
m_indxFile(),
m_ambeFile(),
m_id(id),
m_slot(slot),
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
m_lc.setFLCO(FLCO_GROUP);
m_lc.setSrcId(id);
m_lc.setDstId(tg);
m_embeddedLC.setLC(m_lc);
}
CDynVoice::~CDynVoice()
{
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
for (std::unordered_map<std::string, CDynPositions*>::iterator it = m_positions.begin(); it != m_positions.end(); ++it)
delete it->second;
m_data.clear();
m_positions.clear();
delete[] m_ambe;
}
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<std::string> words;
if (m_positions.count("linkedto") == 0U)
words.push_back("linked");
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<std::string> words;
words.push_back("notlinked");
createVoice(words);
}
void CDynVoice::abort()
{
for (std::vector<CDMRData*>::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<std::string>& words)
{
unsigned int ambeLength = 0U;
for (std::vector<std::string>::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<std::string>::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<CDMRData*>::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<CDMRData*>::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);
}

81
DynVoice.h Normal file
View file

@ -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 <string>
#include <vector>
#include <unordered_map>
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, unsigned int slot, unsigned int tg);
~CDynVoice();
bool open();
void linkedTo(unsigned int number);
void unlinked();
bool read(CDMRData& data);
void abort();
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<std::string, CDynPositions*> m_positions;
std::vector<CDMRData*> m_data;
std::vector<CDMRData*>::const_iterator m_it;
void createHeaderTerminator(unsigned char type);
void createVoice(const std::vector<std::string>& words);
};
#endif

View file

@ -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
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

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

67
RewriteDynTGNet.cpp Normal file
View file

@ -0,0 +1,67 @@
/*
* 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 <cstdio>
#include <cassert>
CRewriteDynTGNet::CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int toTG) :
CRewrite(),
m_name(name),
m_slot(slot),
m_toTG(toTG),
m_currentTG(0U)
{
assert(slot == 1U || slot == 2U);
}
CRewriteDynTGNet::~CRewriteDynTGNet()
{
}
PROCESS_RESULT 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_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 RESULT_UNMATCHED;
}
data.setDstId(m_toTG);
processMessage(data);
if (trace)
LogDebug("Rule Trace,\tRewriteDynTGNet from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_currentTG);
return RESULT_MATCHED;
}
void CRewriteDynTGNet::setCurrentTG(unsigned int currentTG)
{
m_currentTG = currentTG;
}

43
RewriteDynTGNet.h Normal file
View file

@ -0,0 +1,43 @@
/*
* 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 <string>
class CRewriteDynTGNet : public CRewrite {
public:
CRewriteDynTGNet(const std::string& name, unsigned int slot, unsigned int toTG);
virtual ~CRewriteDynTGNet();
virtual PROCESS_RESULT process(CDMRData& data, bool trace);
void setCurrentTG(unsigned int tg);
private:
std::string m_name;
unsigned int m_slot;
unsigned int m_toTG;
unsigned int m_currentTG;
};
#endif

180
RewriteDynTGRF.cpp Normal file
View file

@ -0,0 +1,180 @@
/*
* 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 <cstdio>
#include <cassert>
#include <algorithm>
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<unsigned int>& exclTGs, CRewriteDynTGNet* rewriteNet, CDynVoice* voice) :
CRewrite(),
m_name(name),
m_slot(slot),
m_fromTGStart(fromTG),
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);
}
CRewriteDynTGRF::~CRewriteDynTGRF()
{
}
PROCESS_RESULT CRewriteDynTGRF::process(CDMRData& data, bool trace)
{
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) {
if (trace)
LogDebug("Rule Trace,\tRewriteDynTGRF from %s Slot=%u Dst=TG%u: matched", m_name.c_str(), m_slot, m_toTG);
if (m_currentTG != 0U) {
data.setDstId(m_currentTG);
processMessage(data);
return RESULT_MATCHED;
} else {
return RESULT_IGNORED;
}
}
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);
if (m_currentTG != 0U) {
data.setFLCO(FLCO_GROUP);
processMessage(data);
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;
}
}
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 (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);
return RESULT_UNMATCHED;
}
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);
else
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);
processMessage(data);
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 (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);
else
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;
}
void CRewriteDynTGRF::tgChange(unsigned int slot, unsigned int tg)
{
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_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;
m_rewriteNet->setCurrentTG(tg);
if (m_voice != NULL)
m_voice->linkedTo(tg);
}
return;
}
}
void CRewriteDynTGRF::stopVoice(unsigned int slot)
{
if (slot == m_slot && m_voice != NULL)
m_voice->abort();
}

57
RewriteDynTGRF.h Normal file
View file

@ -0,0 +1,57 @@
/*
* 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 "DynVoice.h"
#include "Rewrite.h"
#include "DMRData.h"
#include "RewriteDynTGNet.h"
#include <string>
#include <vector>
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, const std::vector<unsigned int>& exclTGs, CRewriteDynTGNet* rewriteNet, CDynVoice* voice);
virtual ~CRewriteDynTGRF();
virtual PROCESS_RESULT process(CDMRData& data, bool trace);
void stopVoice(unsigned int slot);
void tgChange(unsigned int slot, 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_discPC;
unsigned int m_statusPC;
std::vector<unsigned int> m_exclTGs;
CRewriteDynTGNet* m_rewriteNet;
CDynVoice* m_voice;
unsigned int m_currentTG;
};
#endif

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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
@ -24,13 +24,15 @@
#include <cstdio>
#include <cassert>
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);
@ -40,29 +42,43 @@ 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();
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);
return false;
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_toIdStart) {
unsigned int newDstId = dstId + m_toIdStart - m_fromTGStart;
data.setDstId(newDstId);
}
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 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);
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_toIdEnd);
}
return true;
return RESULT_MATCHED;
}

View file

@ -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
@ -26,17 +26,19 @@
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 bool process(CDMRData& data, bool trace);
virtual PROCESS_RESULT process(CDMRData& data, bool trace);
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;
};

View file

@ -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 = "20200421";
#endif

View file

@ -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

View file

@ -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,13 +35,13 @@ 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),
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),
@ -63,12 +63,12 @@ m_it()
#endif
}
CVoice::~CVoice()
CXLXVoice::~CXLXVoice()
{
for (std::vector<CDMRData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
delete *it;
for (std::unordered_map<std::string, CPositions*>::iterator it = m_positions.begin(); it != m_positions.end(); ++it)
for (std::unordered_map<std::string, CXLXPositions*>::iterator it = m_positions.begin(); it != m_positions.end(); ++it)
delete it->second;
m_data.clear();
@ -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) {
@ -115,7 +115,7 @@ bool CVoice::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;
@ -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<std::string> words;
words.push_back("notlinked");
@ -166,12 +166,12 @@ void CVoice::unlinked()
createVoice(words);
}
void CVoice::createVoice(const std::vector<std::string>& words)
void CXLXVoice::createVoice(const std::vector<std::string>& words)
{
unsigned int ambeLength = 0U;
for (std::vector<std::string>::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 CVoice::createVoice(const std::vector<std::string>& words)
unsigned int pos = SILENCE_LENGTH * AMBE_LENGTH;
for (std::vector<std::string>::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 CVoice::createVoice(const std::vector<std::string>& words)
delete[] ambeData;
m_status = VS_WAITING;
m_status = XLXVS_WAITING;
m_timer.start();
}
bool CVoice::read(CDMRData& data)
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 CVoice::read(CDMRData& data)
delete *it;
m_data.clear();
m_timer.stop();
m_status = VS_NONE;
m_status = XLXVS_NONE;
}
return true;
@ -300,20 +300,20 @@ 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()) {
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;
}
}
}
void CVoice::createHeaderTerminator(unsigned char type)
void CXLXVoice::createHeaderTerminator(unsigned char type)
{
CDMRData* data = new CDMRData;

View file

@ -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"
@ -29,21 +29,21 @@
#include <vector>
#include <unordered_map>
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;
};
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();
@ -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<std::string, CPositions*> m_positions;
std::unordered_map<std::string, CXLXPositions*> m_positions;
std::vector<CDMRData*> m_data;
std::vector<CDMRData*>::const_iterator m_it;

21
scripts/install-linker.sh Normal file
View file

@ -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

View file

@ -0,0 +1,14 @@
[Unit]
Description=relinker service
After=multi-user.target
[Service]
Type=idle
ExecStart=/bin/bash /opt/script/relink-repeater.sh
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,12 @@
[Unit]
Description=relinkerhot service
After=multi-user.target
[Service]
Type=idle
ExecStart=/bin/bash /opt/script/relink-hotspot.sh
[Install]
WantedBy=multi-user.target

213
scripts/opt/script/README Normal file
View file

@ -0,0 +1,213 @@
DMR SUDO Reflector - TG
This is the first release version of the relinker scripts 3.2
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
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
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
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
6. 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
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
tail -f /var/log/script/checkBMAPI.log
Have fun
73,
Jon G4TSN
jon@g4tsn.com

View file

@ -0,0 +1,142 @@
#!/bin/bash
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
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
}
while :
do
check_BM_API
echo
$checkslot1
$checkslot2
$slot1notlinked
$slot2notlinked
echo
sleep $slowdown
done

View file

@ -0,0 +1,143 @@
#!/bin/bash
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
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
}
while :
do
check_BM_API
echo
$checkslot1
$checkslot2
$slot1notlinked
$slot2notlinked
echo
sleep $slowdown
done

View file

@ -0,0 +1,20 @@
#!/usr/bin/bash
repeater=235192
call=GB3IN
defaultslot1=23590
defaultslot2=91
minrelinktimerslot1=30
minrelinktimerslot2=30
slowdown=0
checkslot1=check_status_slot1
checkslot2=check_status_slot2
slot1notlinked=check_if_nothing_linked_slot1
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

View file

@ -0,0 +1,15 @@
#!/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
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

Binary file not shown.

View file

View file

View file

@ -0,0 +1 @@
Linked to 23590

View file

@ -0,0 +1 @@
Linked to 91

View file

View file

@ -0,0 +1 @@
"dynamicSubscriptions":[],"timedSubscriptions":[],"clusters":[]}

View file

@ -0,0 +1 @@
"dynamicSubscriptions":[],"timedSubscriptions":[],"clusters":[]}

View file