diff --git a/src/host/Host.Config.cpp b/src/host/Host.Config.cpp
new file mode 100644
index 00000000..ecd4f04f
--- /dev/null
+++ b/src/host/Host.Config.cpp
@@ -0,0 +1,787 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+//
+// Based on code from the MMDVMHost project. (https://github.com/g4klx/MMDVMHost)
+// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+//
+/*
+* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL
+*
+* 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 "Defines.h"
+#include "modem/port/ModemNullPort.h"
+#include "modem/port/UARTPort.h"
+#include "modem/port/PseudoPTYPort.h"
+#include "modem/port/UDPPort.h"
+#include "network/UDPSocket.h"
+#include "host/Host.h"
+#include "HostMain.h"
+
+using namespace network;
+using namespace modem;
+using namespace lookups;
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Reads basic configuration parameters from the YAML configuration file.
+///
+bool Host::readParams()
+{
+ yaml::Node modemConf = m_conf["system"]["modem"];
+
+ yaml::Node modemProtocol = modemConf["protocol"];
+ std::string portType = modemProtocol["type"].as("null");
+
+ yaml::Node udpProtocol = modemProtocol["udp"];
+ std::string udpMode = udpProtocol["mode"].as("master");
+
+ bool udpMasterMode = false;
+ std::transform(portType.begin(), portType.end(), portType.begin(), ::tolower);
+ if ((portType == UART_PORT || portType == PTY_PORT) && g_remoteModemMode) {
+ udpMasterMode = true;
+ }
+
+ yaml::Node protocolConf = m_conf["protocols"];
+#if defined(ENABLE_DMR)
+ m_dmrEnabled = protocolConf["dmr"]["enable"].as(false);
+#else
+ m_dmrEnabled = false; // hardcode to false when no DMR support is compiled in
+#endif // defined(ENABLE_DMR)
+#if defined(ENABLE_P25)
+ m_p25Enabled = protocolConf["p25"]["enable"].as(false);
+#else
+ m_p25Enabled = false; // hardcode to false when no P25 support is compiled in
+#endif // defined(ENABLE_P25)
+#if defined(ENABLE_NXDN)
+ m_nxdnEnabled = protocolConf["nxdn"]["enable"].as(false);
+#else
+ m_nxdnEnabled = false; // hardcode to false when no NXDN support is compiled in
+#endif // defined(ENABLE_NXDN)
+
+ yaml::Node systemConf = m_conf["system"];
+ m_duplex = systemConf["duplex"].as(true);
+ bool simplexSameFreq = systemConf["simplexSameFrequency"].as(false);
+
+ m_timeout = systemConf["timeout"].as(120U);
+ m_rfModeHang = systemConf["rfModeHang"].as(10U);
+ m_rfTalkgroupHang = systemConf["rfTalkgroupHang"].as(10U);
+ m_netModeHang = systemConf["netModeHang"].as(3U);
+ if (!systemConf["modeHang"].isNone()) {
+ m_rfModeHang = m_netModeHang = systemConf["modeHang"].as();
+ }
+
+ m_activeTickDelay = (uint8_t)systemConf["activeTickDelay"].as(5U);
+ if (m_activeTickDelay < 1U)
+ m_activeTickDelay = 1U;
+ m_idleTickDelay = (uint8_t)systemConf["idleTickDelay"].as(5U);
+ if (m_idleTickDelay < 1U)
+ m_idleTickDelay = 1U;
+
+ m_identity = systemConf["identity"].as();
+ m_fixedMode = systemConf["fixedMode"].as(false);
+
+ if (m_identity.length() > 8) {
+ std::string identity = m_identity;
+ m_identity = identity.substr(0, 8);
+
+ ::LogWarning(LOG_HOST, "System Identity \"%s\" is too long; truncating to 8 characters, \"%s\".", identity.c_str(), m_identity.c_str());
+ }
+
+ int8_t lto = (int8_t)systemConf["localTimeOffset"].as(0);
+
+ removeLockFile();
+
+ LogInfo("General Parameters");
+ if (!udpMasterMode) {
+ LogInfo(" DMR: %s", m_dmrEnabled ? "enabled" : "disabled");
+ LogInfo(" P25: %s", m_p25Enabled ? "enabled" : "disabled");
+ LogInfo(" NXDN: %s", m_nxdnEnabled ? "enabled" : "disabled");
+ LogInfo(" Duplex: %s", m_duplex ? "yes" : "no");
+ if (!m_duplex) {
+ LogInfo(" Simplex Same Frequency: %s", simplexSameFreq ? "yes" : "no");
+ }
+ LogInfo(" Active Tick Delay: %ums", m_activeTickDelay);
+ LogInfo(" Idle Tick Delay: %ums", m_idleTickDelay);
+ LogInfo(" Timeout: %us", m_timeout);
+ LogInfo(" RF Mode Hang: %us", m_rfModeHang);
+ LogInfo(" RF Talkgroup Hang: %us", m_rfTalkgroupHang);
+ LogInfo(" Net Mode Hang: %us", m_netModeHang);
+ LogInfo(" Identity: %s", m_identity.c_str());
+ LogInfo(" Fixed Mode: %s", m_fixedMode ? "yes" : "no");
+ LogInfo(" Lock Filename: %s", g_lockFile.c_str());
+ LogInfo(" Local Time Offset: %dh", lto);
+
+ yaml::Node systemInfo = systemConf["info"];
+ m_latitude = systemInfo["latitude"].as(0.0F);
+ m_longitude = systemInfo["longitude"].as(0.0F);
+ m_height = systemInfo["height"].as(0);
+ m_power = systemInfo["power"].as(0U);
+ m_location = systemInfo["location"].as();
+
+ LogInfo("System Info Parameters");
+ LogInfo(" Latitude: %fdeg N", m_latitude);
+ LogInfo(" Longitude: %fdeg E", m_longitude);
+ LogInfo(" Height: %um", m_height);
+ LogInfo(" Power: %uW", m_power);
+ LogInfo(" Location: \"%s\"", m_location.c_str());
+
+ // try to load bandplan identity table
+ std::string idenLookupFile = systemConf["iden_table"]["file"].as();
+ uint32_t idenReloadTime = systemConf["iden_table"]["time"].as(0U);
+
+ if (idenLookupFile.length() <= 0U) {
+ ::LogError(LOG_HOST, "No bandplan identity table? This must be defined!");
+ return false;
+ }
+
+ LogInfo("Iden Table Lookups");
+ LogInfo(" File: %s", idenLookupFile.length() > 0U ? idenLookupFile.c_str() : "None");
+ if (idenReloadTime > 0U)
+ LogInfo(" Reload: %u mins", idenReloadTime);
+
+ m_idenTable = new IdenTableLookup(idenLookupFile, idenReloadTime);
+ m_idenTable->read();
+
+ /*
+ ** Channel Configuration
+ */
+ yaml::Node rfssConfig = systemConf["config"];
+ m_channelId = (uint8_t)rfssConfig["channelId"].as(0U);
+ if (m_channelId > 15U) { // clamp to 15
+ m_channelId = 15U;
+ }
+
+ IdenTable entry = m_idenTable->find(m_channelId);
+ if (entry.baseFrequency() == 0U) {
+ ::LogError(LOG_HOST, "Channel Id %u has an invalid base frequency.", m_channelId);
+ return false;
+ }
+
+ m_channelNo = (uint32_t)::strtoul(rfssConfig["channelNo"].as("1").c_str(), NULL, 16);
+ if (m_channelNo == 0U) { // clamp to 1
+ m_channelNo = 1U;
+ }
+ if (m_channelNo > 4095U) { // clamp to 4095
+ m_channelNo = 4095U;
+ }
+
+ if (entry.txOffsetMhz() == 0U) {
+ ::LogError(LOG_HOST, "Channel Id %u has an invalid Tx offset.", m_channelId);
+ return false;
+ }
+
+ uint32_t calcSpace = (uint32_t)(entry.chSpaceKhz() / 0.125);
+ float calcTxOffset = entry.txOffsetMhz() * 1000000;
+
+ m_txFrequency = (uint32_t)((entry.baseFrequency() + ((calcSpace * 125) * m_channelNo)));
+ m_rxFrequency = (uint32_t)(m_txFrequency + calcTxOffset);
+
+ if (calcTxOffset < 0.0f && m_rxFrequency < entry.baseFrequency()) {
+ ::LogWarning(LOG_HOST, "Channel Id %u Channel No $%04X has an invalid frequency. Rx Frequency (%u) is less then the base frequency (%u), this may result in incorrect trunking behavior.", m_channelId, m_channelNo,
+ m_rxFrequency, entry.baseFrequency());
+ }
+
+ if (!m_duplex && simplexSameFreq) {
+ m_rxFrequency = m_txFrequency;
+ }
+
+ /*
+ ** Control Channel
+ */
+ {
+ yaml::Node controlCh = rfssConfig["controlCh"];
+
+ std::string restApiAddress = controlCh["restAddress"].as("");
+ uint16_t restApiPort = (uint16_t)controlCh["restPort"].as(REST_API_DEFAULT_PORT);
+ std::string restApiPassword = controlCh["restPassword"].as();
+
+ VoiceChData data = VoiceChData(m_channelId, m_channelNo, restApiAddress, restApiPort, restApiPassword);
+ m_controlChData = data;
+
+ if (!m_controlChData.address().empty() && m_controlChData.port() > 0) {
+ ::LogInfoEx(LOG_HOST, "Control Channel REST API Address %s:%u", m_controlChData.address().c_str(), m_controlChData.port());
+ } else {
+ ::LogInfoEx(LOG_HOST, "No Control Channel REST API Configured, CC notify disabled");
+ }
+ }
+
+ /*
+ ** Voice Channels
+ */
+ yaml::Node& voiceChList = rfssConfig["voiceChNo"];
+
+ if (voiceChList.size() == 0U) {
+ ::LogError(LOG_HOST, "No voice channel list defined!");
+ return false;
+ }
+
+ for (size_t i = 0; i < voiceChList.size(); i++) {
+ yaml::Node& channel = voiceChList[i];
+
+ uint8_t chId = (uint8_t)channel["channelId"].as(255U);
+
+ // special case default handling for if the channelId field is missing from the
+ // configuration
+ if (chId == 255U) {
+ chId = m_channelId;
+ }
+
+ if (chId > 15U) { // clamp to 15
+ chId = 15U;
+ }
+
+ uint32_t chNo = (uint32_t)::strtoul(channel["channelNo"].as("1").c_str(), NULL, 16);
+ if (chNo == 0U) { // clamp to 1
+ chNo = 1U;
+ }
+ if (chNo > 4095U) { // clamp to 4095
+ chNo = 4095U;
+ }
+
+ std::string restApiAddress = channel["restAddress"].as("127.0.0.1");
+ uint16_t restApiPort = (uint16_t)channel["restPort"].as(REST_API_DEFAULT_PORT);
+ std::string restApiPassword = channel["restPassword"].as();
+
+ ::LogInfoEx(LOG_HOST, "Voice Channel Id %u Channel No $%04X REST API Address %s:%u", chId, chNo, restApiAddress.c_str(), restApiPort);
+
+ VoiceChData data = VoiceChData(chId, chNo, restApiAddress, restApiPort, restApiPassword);
+ m_voiceChData[chNo] = data;
+ m_voiceChNo.push_back(chNo);
+ }
+
+ std::string strVoiceChNo = "";
+ for (auto it = m_voiceChNo.begin(); it != m_voiceChNo.end(); ++it) {
+ uint32_t chNo = ::atoi(std::to_string(*it).c_str());
+ ::lookups::VoiceChData voiceChData = m_voiceChData[chNo];
+
+ char hexStr[29];
+
+ ::sprintf(hexStr, "$%01X.%01X (%u.%u)", voiceChData.chId(), chNo, voiceChData.chId(), chNo);
+
+ strVoiceChNo.append(std::string(hexStr));
+ strVoiceChNo.append(",");
+ }
+ strVoiceChNo.erase(strVoiceChNo.find_last_of(","));
+
+ /*
+ ** Site Parameters
+ */
+ m_siteId = (uint8_t)::strtoul(rfssConfig["siteId"].as("1").c_str(), NULL, 16);
+ m_siteId = p25::P25Utils::siteId(m_siteId);
+
+ m_dmrColorCode = rfssConfig["colorCode"].as(2U);
+ m_dmrColorCode = dmr::DMRUtils::colorCode(m_dmrColorCode);
+
+ m_dmrNetId = (uint32_t)::strtoul(rfssConfig["dmrNetId"].as("1").c_str(), NULL, 16);
+ m_dmrNetId = dmr::DMRUtils::netId(m_dmrNetId, dmr::SITE_MODEL_TINY);
+
+ m_p25NAC = (uint32_t)::strtoul(rfssConfig["nac"].as("293").c_str(), NULL, 16);
+ m_p25NAC = p25::P25Utils::nac(m_p25NAC);
+
+ uint32_t p25TxNAC = (uint32_t)::strtoul(rfssConfig["txNAC"].as("F7E").c_str(), NULL, 16);
+ if (p25TxNAC == m_p25NAC) {
+ LogWarning(LOG_HOST, "Only use txNAC when split NAC operations are needed. nac and txNAC should not be the same!");
+ }
+
+ m_p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as("BB800").c_str(), NULL, 16);
+ m_p25NetId = p25::P25Utils::netId(m_p25NetId);
+ if (m_p25NetId == 0xBEE00) {
+ ::fatal("error 4\n");
+ }
+
+ m_sysId = (uint32_t)::strtoul(rfssConfig["sysId"].as("001").c_str(), NULL, 16);
+ m_sysId = p25::P25Utils::sysId(m_sysId);
+
+ m_p25RfssId = (uint8_t)::strtoul(rfssConfig["rfssId"].as("1").c_str(), NULL, 16);
+ m_p25RfssId = p25::P25Utils::rfssId(m_p25RfssId);
+
+ m_nxdnRAN = rfssConfig["ran"].as(1U);
+
+ m_authoritative = rfssConfig["authoritative"].as(true);
+
+ LogInfo("System Config Parameters");
+ LogInfo(" Authoritative: %s", m_authoritative ? "yes" : "no");
+ if (m_authoritative) {
+ m_supervisor = rfssConfig["supervisor"].as(false);
+ LogInfo(" Supervisor: %s", m_supervisor ? "yes" : "no");
+ }
+ LogInfo(" RX Frequency: %uHz", m_rxFrequency);
+ LogInfo(" TX Frequency: %uHz", m_txFrequency);
+ LogInfo(" Base Frequency: %uHz", entry.baseFrequency());
+ LogInfo(" TX Offset: %fMHz", entry.txOffsetMhz());
+ LogInfo(" Bandwidth: %fKHz", entry.chBandwidthKhz());
+ LogInfo(" Channel Spacing: %fKHz", entry.chSpaceKhz());
+ LogInfo(" Channel Id: %u", m_channelId);
+ LogInfo(" Channel No.: $%04X (%u)", m_channelNo, m_channelNo);
+ LogInfo(" Voice Channel No(s).: %s", strVoiceChNo.c_str());
+ LogInfo(" Site Id: $%02X", m_siteId);
+ LogInfo(" System Id: $%03X", m_sysId);
+ LogInfo(" DMR Color Code: %u", m_dmrColorCode);
+ LogInfo(" DMR Network Id: $%05X", m_dmrNetId);
+ LogInfo(" P25 NAC: $%03X", m_p25NAC);
+
+ if (p25TxNAC != 0xF7EU && p25TxNAC != m_p25NAC) {
+ LogInfo(" P25 Tx NAC: $%03X", p25TxNAC);
+ }
+
+ LogInfo(" P25 Network Id: $%05X", m_p25NetId);
+ LogInfo(" P25 RFSS Id: $%02X", m_p25RfssId);
+ LogInfo(" NXDN RAN: %u", m_nxdnRAN);
+
+ if (!m_authoritative) {
+ m_supervisor = false;
+ LogWarning(LOG_HOST, "Host is non-authoritative! This requires REST API to handle permit TG for VCs and grant TG for CCs!");
+ }
+ }
+ else {
+ LogInfo(" Modem Remote Control: yes");
+ }
+
+ return true;
+}
+
+///
+/// Initializes the modem DSP.
+///
+bool Host::createModem()
+{
+ yaml::Node protocolConf = m_conf["protocols"];
+
+ yaml::Node dmrProtocol = protocolConf["dmr"];
+ uint32_t dmrQueueSize = dmrProtocol["queueSize"].as(24U);
+
+ // clamp queue size to no less then 24 and no greater the 100
+ if (dmrQueueSize < 24U) {
+ LogWarning(LOG_HOST, "DMR queue size must be greater then 24 frames, defaulting to 24 frames!");
+ dmrQueueSize = 24U;
+ }
+ if (dmrQueueSize > 100U) {
+ LogWarning(LOG_HOST, "DMR queue size must be less then 100 frames, defaulting to 100 frames!");
+ dmrQueueSize = 100U;
+ }
+ if (dmrQueueSize > 60U) {
+ LogWarning(LOG_HOST, "DMR queue size is excessive, >60 frames!");
+ }
+
+ m_dmrQueueSizeBytes = dmrQueueSize * (dmr::DMR_FRAME_LENGTH_BYTES * 5U);
+
+ yaml::Node p25Protocol = protocolConf["p25"];
+ uint32_t p25QueueSize = p25Protocol["queueSize"].as(12U);
+
+ // clamp queue size to no less then 12 and no greater the 100 frames
+ if (p25QueueSize < 12U) {
+ LogWarning(LOG_HOST, "P25 queue size must be greater then 12 frames, defaulting to 12 frames!");
+ p25QueueSize = 12U;
+ }
+ if (p25QueueSize > 50U) {
+ LogWarning(LOG_HOST, "P25 queue size must be less then 50 frames, defaulting to 50 frames!");
+ p25QueueSize = 50U;
+ }
+ if (p25QueueSize > 30U) {
+ LogWarning(LOG_HOST, "P25 queue size is excessive, >30 frames!");
+ }
+
+ m_p25QueueSizeBytes = p25QueueSize * p25::P25_LDU_FRAME_LENGTH_BYTES;
+
+ yaml::Node nxdnProtocol = protocolConf["nxdn"];
+ uint32_t nxdnQueueSize = nxdnProtocol["queueSize"].as(31U);
+
+ // clamp queue size to no less then 31 and no greater the 50 frames
+ if (nxdnQueueSize < 31U) {
+ LogWarning(LOG_HOST, "NXDN queue size must be greater then 31 frames, defaulting to 31 frames!");
+ nxdnQueueSize = 31U;
+ }
+ if (nxdnQueueSize > 50U) {
+ LogWarning(LOG_HOST, "NXDN queue size must be less then 50 frames, defaulting to 50 frames!");
+ nxdnQueueSize = 50U;
+ }
+
+ m_nxdnQueueSizeBytes = nxdnQueueSize * nxdn::NXDN_FRAME_LENGTH_BYTES;
+
+ yaml::Node modemConf = m_conf["system"]["modem"];
+
+ yaml::Node modemProtocol = modemConf["protocol"];
+ std::string portType = modemProtocol["type"].as("null");
+ yaml::Node uartProtocol = modemProtocol["uart"];
+ std::string uartPort = uartProtocol["port"].as();
+ uint32_t uartSpeed = uartProtocol["speed"].as(115200);
+
+ bool rxInvert = modemConf["rxInvert"].as(false);
+ bool txInvert = modemConf["txInvert"].as(false);
+ bool pttInvert = modemConf["pttInvert"].as(false);
+ bool dcBlocker = modemConf["dcBlocker"].as(true);
+ bool cosLockout = modemConf["cosLockout"].as(false);
+ uint8_t fdmaPreamble = (uint8_t)modemConf["fdmaPreamble"].as(80U);
+ uint8_t dmrRxDelay = (uint8_t)modemConf["dmrRxDelay"].as(7U);
+ uint8_t p25CorrCount = (uint8_t)modemConf["p25CorrCount"].as(4U);
+ int rxDCOffset = modemConf["rxDCOffset"].as(0);
+ int txDCOffset = modemConf["txDCOffset"].as(0);
+
+ yaml::Node hotspotParams = modemConf["hotspot"];
+
+ int dmrDiscBWAdj = hotspotParams["dmrDiscBWAdj"].as(0);
+ int p25DiscBWAdj = hotspotParams["p25DiscBWAdj"].as(0);
+ int nxdnDiscBWAdj = hotspotParams["nxdnDiscBWAdj"].as(0);
+ int dmrPostBWAdj = hotspotParams["dmrPostBWAdj"].as(0);
+ int p25PostBWAdj = hotspotParams["p25PostBWAdj"].as(0);
+ int nxdnPostBWAdj = hotspotParams["nxdnPostBWAdj"].as(0);
+ ADF_GAIN_MODE adfGainMode = (ADF_GAIN_MODE)hotspotParams["adfGainMode"].as(0U);
+ bool afcEnable = hotspotParams["afcEnable"].as(false);
+ uint8_t afcKI = (uint8_t)hotspotParams["afcKI"].as(11U);
+ uint8_t afcKP = (uint8_t)hotspotParams["afcKP"].as(4U);
+ uint8_t afcRange = (uint8_t)hotspotParams["afcRange"].as(1U);
+ int rxTuning = hotspotParams["rxTuning"].as(0);
+ int txTuning = hotspotParams["txTuning"].as(0);
+ uint8_t rfPower = (uint8_t)hotspotParams["rfPower"].as(100U);
+
+ yaml::Node repeaterParams = modemConf["repeater"];
+
+ int dmrSymLevel3Adj = repeaterParams["dmrSymLvl3Adj"].as(0);
+ int dmrSymLevel1Adj = repeaterParams["dmrSymLvl1Adj"].as(0);
+ int p25SymLevel3Adj = repeaterParams["p25SymLvl3Adj"].as(0);
+ int p25SymLevel1Adj = repeaterParams["p25SymLvl1Adj"].as(0);
+ int nxdnSymLevel3Adj = repeaterParams["nxdnSymLvl3Adj"].as(0);
+ int nxdnSymLevel1Adj = repeaterParams["nxdnSymLvl1Adj"].as(0);
+
+ yaml::Node softpotParams = modemConf["softpot"];
+
+ uint8_t rxCoarse = (uint8_t)softpotParams["rxCoarse"].as(127U);
+ uint8_t rxFine = (uint8_t)softpotParams["rxFine"].as(127U);
+ uint8_t txCoarse = (uint8_t)softpotParams["txCoarse"].as(127U);
+ uint8_t txFine = (uint8_t)softpotParams["txFine"].as(127U);
+ uint8_t rssiCoarse = (uint8_t)softpotParams["rssiCoarse"].as(127U);
+ uint8_t rssiFine = (uint8_t)softpotParams["rssiFine"].as(127U);
+
+ uint16_t dmrFifoLength = (uint16_t)modemConf["dmrFifoLength"].as(DMR_TX_BUFFER_LEN);
+ uint16_t p25FifoLength = (uint16_t)modemConf["p25FifoLength"].as(P25_TX_BUFFER_LEN);
+ uint16_t nxdnFifoLength = (uint16_t)modemConf["nxdnFifoLength"].as(NXDN_TX_BUFFER_LEN);
+
+ float rxLevel = modemConf["rxLevel"].as(50.0F);
+ float cwIdTXLevel = modemConf["cwIdTxLevel"].as(50.0F);
+ float dmrTXLevel = modemConf["dmrTxLevel"].as(50.0F);
+ float p25TXLevel = modemConf["p25TxLevel"].as(50.0F);
+ float nxdnTXLevel = modemConf["nxdnTxLevel"].as(50.0F);
+ if (!modemConf["txLevel"].isNone()) {
+ cwIdTXLevel = dmrTXLevel = p25TXLevel = nxdnTXLevel = modemConf["txLevel"].as(50.0F);
+ }
+ bool disableOFlowReset = modemConf["disableOFlowReset"].as(false);
+ bool ignoreModemConfigArea = modemConf["ignoreModemConfigArea"].as(false);
+ bool dumpModemStatus = modemConf["dumpModemStatus"].as(false);
+ bool trace = modemConf["trace"].as(false);
+ bool debug = modemConf["debug"].as(false);
+
+ if (rfPower == 0U) { // clamp to 1
+ rfPower = 1U;
+ }
+ if (rfPower > 100U) { // clamp to 100
+ rfPower = 100U;
+ }
+
+ LogInfo("Modem Parameters");
+ LogInfo(" Port Type: %s", portType.c_str());
+
+ port::IModemPort* modemPort = nullptr;
+ std::transform(portType.begin(), portType.end(), portType.begin(), ::tolower);
+ if (portType == NULL_PORT) {
+ modemPort = new port::ModemNullPort();
+ }
+ else if (portType == UART_PORT || portType == PTY_PORT) {
+ port::SERIAL_SPEED serialSpeed = port::SERIAL_115200;
+ switch (uartSpeed) {
+ case 1200:
+ serialSpeed = port::SERIAL_1200;
+ break;
+ case 2400:
+ serialSpeed = port::SERIAL_2400;
+ break;
+ case 4800:
+ serialSpeed = port::SERIAL_4800;
+ break;
+ case 9600:
+ serialSpeed = port::SERIAL_9600;
+ break;
+ case 19200:
+ serialSpeed = port::SERIAL_19200;
+ break;
+ case 38400:
+ serialSpeed = port::SERIAL_38400;
+ break;
+ case 76800:
+ serialSpeed = port::SERIAL_76800;
+ break;
+ case 230400:
+ serialSpeed = port::SERIAL_230400;
+ break;
+ case 460800:
+ serialSpeed = port::SERIAL_460800;
+ break;
+ default:
+ LogWarning(LOG_HOST, "Unsupported serial speed %u, defaulting to %u", uartSpeed, port::SERIAL_115200);
+ uartSpeed = 115200;
+ case 115200:
+ break;
+ }
+
+ if (portType == PTY_PORT) {
+ modemPort = new port::UARTPort(uartPort, serialSpeed, false);
+ LogInfo(" PTY Port: %s", uartPort.c_str());
+ LogInfo(" PTY Speed: %u", uartSpeed);
+ }
+ else {
+ modemPort = new port::UARTPort(uartPort, serialSpeed, true);
+ LogInfo(" UART Port: %s", uartPort.c_str());
+ LogInfo(" UART Speed: %u", uartSpeed);
+ }
+ }
+ else {
+ LogError(LOG_HOST, "Invalid protocol port type, %s!", portType.c_str());
+ return false;
+ }
+
+ if (g_remoteModemMode) {
+ if (portType == UART_PORT || portType == PTY_PORT) {
+ m_modemRemotePort = new port::UDPPort(g_remoteAddress, g_remotePort);
+ m_modemRemote = true;
+ ignoreModemConfigArea = true;
+
+ }
+ else {
+ delete modemPort;
+ modemPort = new port::UDPPort(g_remoteAddress, g_remotePort);
+ m_modemRemote = false;
+ }
+
+ LogInfo(" UDP Mode: %s", m_modemRemote ? "master" : "peer");
+ LogInfo(" UDP Address: %s", g_remoteAddress.c_str());
+ LogInfo(" UDP Port: %u", g_remotePort);
+ }
+
+ if (!m_modemRemote) {
+ LogInfo(" RX Invert: %s", rxInvert ? "yes" : "no");
+ LogInfo(" TX Invert: %s", txInvert ? "yes" : "no");
+ LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no");
+ LogInfo(" DC Blocker: %s", dcBlocker ? "yes" : "no");
+ LogInfo(" COS Lockout: %s", cosLockout ? "yes" : "no");
+ LogInfo(" FDMA Preambles: %u (%.1fms)", fdmaPreamble, float(fdmaPreamble) * 0.2222F);
+ LogInfo(" DMR RX Delay: %u (%.1fms)", dmrRxDelay, float(dmrRxDelay) * 0.0416666F);
+ LogInfo(" P25 Corr. Count: %u (%.1fms)", p25CorrCount, float(p25CorrCount) * 0.667F);
+ LogInfo(" RX DC Offset: %d", rxDCOffset);
+ LogInfo(" TX DC Offset: %d", txDCOffset);
+ LogInfo(" RX Tuning Offset: %dhz", rxTuning);
+ LogInfo(" TX Tuning Offset: %dhz", txTuning);
+ LogInfo(" RX Effective Frequency: %uhz", m_rxFrequency + rxTuning);
+ LogInfo(" TX Effective Frequency: %uhz", m_txFrequency + txTuning);
+ LogInfo(" RX Coarse: %u, Fine: %u", rxCoarse, rxFine);
+ LogInfo(" TX Coarse: %u, Fine: %u", txCoarse, txFine);
+ LogInfo(" RSSI Coarse: %u, Fine: %u", rssiCoarse, rssiFine);
+ LogInfo(" RF Power Level: %u", rfPower);
+ LogInfo(" RX Level: %.1f%%", rxLevel);
+ LogInfo(" CW Id TX Level: %.1f%%", cwIdTXLevel);
+ LogInfo(" DMR TX Level: %.1f%%", dmrTXLevel);
+ LogInfo(" P25 TX Level: %.1f%%", p25TXLevel);
+ LogInfo(" NXDN TX Level: %.1f%%", nxdnTXLevel);
+ LogInfo(" Disable Overflow Reset: %s", disableOFlowReset ? "yes" : "no");
+ LogInfo(" DMR Queue Size: %u (%u bytes)", dmrQueueSize, m_dmrQueueSizeBytes);
+ LogInfo(" P25 Queue Size: %u (%u bytes)", p25QueueSize, m_p25QueueSizeBytes);
+ LogInfo(" NXDN Queue Size: %u (%u bytes)", nxdnQueueSize, m_nxdnQueueSizeBytes);
+ LogInfo(" DMR FIFO Size: %u bytes", dmrFifoLength);
+ LogInfo(" P25 FIFO Size: %u bytes", p25FifoLength);
+ LogInfo(" NXDN FIFO Size: %u bytes", nxdnFifoLength);
+
+ if (ignoreModemConfigArea) {
+ LogInfo(" Ignore Modem Configuration Area: yes");
+ }
+
+ if (dumpModemStatus) {
+ LogInfo(" Dump Modem Status: yes");
+ }
+ }
+
+ if (debug) {
+ LogInfo(" Debug: yes");
+ }
+
+ m_modem = new Modem(modemPort, m_duplex, rxInvert, txInvert, pttInvert, dcBlocker, cosLockout, fdmaPreamble, dmrRxDelay, p25CorrCount,
+ m_dmrQueueSizeBytes, m_p25QueueSizeBytes, m_nxdnQueueSizeBytes, disableOFlowReset, ignoreModemConfigArea, dumpModemStatus, trace, debug);
+ if (!m_modemRemote) {
+ m_modem->setModeParams(m_dmrEnabled, m_p25Enabled, m_nxdnEnabled);
+ m_modem->setLevels(rxLevel, cwIdTXLevel, dmrTXLevel, p25TXLevel, nxdnTXLevel);
+ m_modem->setSymbolAdjust(dmrSymLevel3Adj, dmrSymLevel1Adj, p25SymLevel3Adj, p25SymLevel1Adj, nxdnSymLevel3Adj, nxdnSymLevel1Adj);
+ m_modem->setDCOffsetParams(txDCOffset, rxDCOffset);
+ m_modem->setRFParams(m_rxFrequency, m_txFrequency, rxTuning, txTuning, rfPower, dmrDiscBWAdj, p25DiscBWAdj, nxdnDiscBWAdj, dmrPostBWAdj,
+ p25PostBWAdj, nxdnPostBWAdj, adfGainMode, afcEnable, afcKI, afcKP, afcRange);
+ m_modem->setSoftPot(rxCoarse, rxFine, txCoarse, txFine, rssiCoarse, rssiFine);
+ m_modem->setDMRColorCode(m_dmrColorCode);
+ m_modem->setP25NAC(m_p25NAC);
+ }
+
+ if (m_modemRemote) {
+ m_modem->setOpenHandler(MODEM_OC_PORT_HANDLER_BIND(Host::rmtPortModemOpen, this));
+ m_modem->setCloseHandler(MODEM_OC_PORT_HANDLER_BIND(Host::rmtPortModemClose, this));
+ m_modem->setResponseHandler(MODEM_RESP_HANDLER_BIND(Host::rmtPortModemHandler, this));
+ }
+
+ bool ret = m_modem->open();
+ if (!ret) {
+ delete m_modem;
+ m_modem = nullptr;
+ return false;
+ }
+
+ m_modem->setFifoLength(dmrFifoLength, p25FifoLength, nxdnFifoLength);
+
+ // are we on a protocol version older then 3?
+ if (m_modem->getVersion() < 3U) {
+ if (m_nxdnEnabled) {
+ ::LogError(LOG_HOST, "NXDN is not supported on legacy firmware.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+///
+/// Initializes network connectivity.
+///
+bool Host::createNetwork()
+{
+ yaml::Node networkConf = m_conf["network"];
+ bool netEnable = networkConf["enable"].as(false);
+ bool restApiEnable = networkConf["restEnable"].as(false);
+
+ // dump out if both networking and REST API are disabled
+ if (!netEnable && !restApiEnable) {
+ return true;
+ }
+
+ std::string address = networkConf["address"].as();
+ uint16_t port = (uint16_t)networkConf["port"].as(TRAFFIC_DEFAULT_PORT);
+ uint16_t local = (uint16_t)networkConf["local"].as(0U);
+ std::string restApiAddress = networkConf["restAddress"].as("127.0.0.1");
+ uint16_t restApiPort = (uint16_t)networkConf["restPort"].as(REST_API_DEFAULT_PORT);
+ std::string restApiPassword = networkConf["restPassword"].as();
+ bool restApiDebug = networkConf["restDebug"].as(false);
+ uint32_t id = networkConf["id"].as(1000U);
+ uint32_t jitter = networkConf["talkgroupHang"].as(360U);
+ std::string password = networkConf["password"].as();
+ bool slot1 = networkConf["slot1"].as(true);
+ bool slot2 = networkConf["slot2"].as(true);
+ bool allowActivityTransfer = networkConf["allowActivityTransfer"].as(false);
+ bool allowDiagnosticTransfer = networkConf["allowDiagnosticTransfer"].as(false);
+ bool updateLookup = networkConf["updateLookups"].as(false);
+ bool debug = networkConf["debug"].as(false);
+
+ if (id > 999999999U) {
+ ::LogError(LOG_HOST, "Network Peer ID cannot be greater then 999999999.");
+ return false;
+ }
+
+ if (restApiPassword.length() > 64) {
+ std::string password = restApiPassword;
+ restApiPassword = password.substr(0, 64);
+
+ ::LogWarning(LOG_HOST, "REST API password is too long; truncating to the first 64 characters.");
+ }
+
+ if (restApiPassword.empty() && restApiEnable) {
+ ::LogWarning(LOG_HOST, "REST API password not provided; REST API disabled.");
+ restApiEnable = false;
+ }
+
+ IdenTable entry = m_idenTable->find(m_channelId);
+
+ LogInfo("Network Parameters");
+ LogInfo(" Enabled: %s", netEnable ? "yes" : "no");
+ if (netEnable) {
+ LogInfo(" Peer ID: %u", id);
+ LogInfo(" Address: %s", address.c_str());
+ LogInfo(" Port: %u", port);
+ if (local > 0U)
+ LogInfo(" Local: %u", local);
+ else
+ LogInfo(" Local: random");
+ LogInfo(" DMR Jitter: %ums", jitter);
+ LogInfo(" Slot 1: %s", slot1 ? "enabled" : "disabled");
+ LogInfo(" Slot 2: %s", slot2 ? "enabled" : "disabled");
+ LogInfo(" Allow Activity Log Transfer: %s", allowActivityTransfer ? "yes" : "no");
+ LogInfo(" Allow Diagnostic Log Transfer: %s", allowDiagnosticTransfer ? "yes" : "no");
+ LogInfo(" Update Lookups: %s", updateLookup ? "yes" : "no");
+
+ if (debug) {
+ LogInfo(" Debug: yes");
+ }
+ }
+ LogInfo(" REST API Enabled: %s", restApiEnable ? "yes" : "no");
+ if (restApiEnable) {
+ LogInfo(" REST API Address: %s", restApiAddress.c_str());
+ LogInfo(" REST API Port: %u", restApiPort);
+
+ if (restApiDebug) {
+ LogInfo(" REST API Debug: yes");
+ }
+ }
+
+ // initialize networking
+ if (netEnable) {
+ m_network = new Network(address, port, local, id, password, m_duplex, debug, m_dmrEnabled, m_p25Enabled, m_nxdnEnabled, slot1, slot2, allowActivityTransfer, allowDiagnosticTransfer, updateLookup);
+
+ m_network->setLookups(m_ridLookup, m_tidLookup);
+ m_network->setMetadata(m_identity, m_rxFrequency, m_txFrequency, entry.txOffsetMhz(), entry.chBandwidthKhz(), m_channelId, m_channelNo,
+ m_power, m_latitude, m_longitude, m_height, m_location);
+ if (restApiEnable) {
+ m_network->setRESTAPIData(restApiPassword, restApiPort);
+ }
+
+ m_network->enable(true);
+ bool ret = m_network->open();
+ if (!ret) {
+ delete m_network;
+ m_network = nullptr;
+ LogError(LOG_HOST, "failed to initialize traffic networking!");
+ return false;
+ }
+
+ ::LogSetNetwork(m_network);
+ }
+
+ // initialize network remote command
+ if (restApiEnable) {
+ m_RESTAPI = new RESTAPI(restApiAddress, restApiPort, restApiPassword, this, restApiDebug);
+ m_RESTAPI->setLookups(m_ridLookup, m_tidLookup);
+ bool ret = m_RESTAPI->open();
+ if (!ret) {
+ delete m_RESTAPI;
+ m_RESTAPI = nullptr;
+ LogError(LOG_HOST, "failed to initialize REST API networking! REST API will be unavailable!");
+ // REST API failing isn't fatal -- we'll allow this to return normally
+ }
+ }
+ else {
+ m_RESTAPI = nullptr;
+ }
+
+ return true;
+}
diff --git a/src/host/Host.cpp b/src/host/Host.cpp
index 660d74b4..73bbd7bf 100644
--- a/src/host/Host.cpp
+++ b/src/host/Host.cpp
@@ -32,11 +32,6 @@
#include "Defines.h"
#include "dmr/DMRUtils.h"
#include "p25/P25Utils.h"
-#include "modem/port/ModemNullPort.h"
-#include "modem/port/UARTPort.h"
-#include "modem/port/PseudoPTYPort.h"
-#include "modem/port/UDPPort.h"
-#include "network/UDPSocket.h"
#include "lookups/RSSIInterpolator.h"
#include "host/Host.h"
#include "HostMain.h"
@@ -46,7 +41,6 @@
#include "ThreadFunc.h"
#include "Utils.h"
-using namespace network;
using namespace modem;
using namespace lookups;
@@ -1469,748 +1463,6 @@ int Host::run()
// Private Class Members
// ---------------------------------------------------------------------------
-///
-/// Reads basic configuration parameters from the YAML configuration file.
-///
-bool Host::readParams()
-{
- yaml::Node modemConf = m_conf["system"]["modem"];
-
- yaml::Node modemProtocol = modemConf["protocol"];
- std::string portType = modemProtocol["type"].as("null");
-
- yaml::Node udpProtocol = modemProtocol["udp"];
- std::string udpMode = udpProtocol["mode"].as("master");
-
- bool udpMasterMode = false;
- std::transform(portType.begin(), portType.end(), portType.begin(), ::tolower);
- if ((portType == UART_PORT || portType == PTY_PORT) && g_remoteModemMode) {
- udpMasterMode = true;
- }
-
- yaml::Node protocolConf = m_conf["protocols"];
-#if defined(ENABLE_DMR)
- m_dmrEnabled = protocolConf["dmr"]["enable"].as(false);
-#else
- m_dmrEnabled = false; // hardcode to false when no DMR support is compiled in
-#endif // defined(ENABLE_DMR)
-#if defined(ENABLE_P25)
- m_p25Enabled = protocolConf["p25"]["enable"].as(false);
-#else
- m_p25Enabled = false; // hardcode to false when no P25 support is compiled in
-#endif // defined(ENABLE_P25)
-#if defined(ENABLE_NXDN)
- m_nxdnEnabled = protocolConf["nxdn"]["enable"].as(false);
-#else
- m_nxdnEnabled = false; // hardcode to false when no NXDN support is compiled in
-#endif // defined(ENABLE_NXDN)
-
- yaml::Node systemConf = m_conf["system"];
- m_duplex = systemConf["duplex"].as(true);
- bool simplexSameFreq = systemConf["simplexSameFrequency"].as(false);
-
- m_timeout = systemConf["timeout"].as(120U);
- m_rfModeHang = systemConf["rfModeHang"].as(10U);
- m_rfTalkgroupHang = systemConf["rfTalkgroupHang"].as(10U);
- m_netModeHang = systemConf["netModeHang"].as(3U);
- if (!systemConf["modeHang"].isNone()) {
- m_rfModeHang = m_netModeHang = systemConf["modeHang"].as();
- }
-
- m_activeTickDelay = (uint8_t)systemConf["activeTickDelay"].as(5U);
- if (m_activeTickDelay < 1U)
- m_activeTickDelay = 1U;
- m_idleTickDelay = (uint8_t)systemConf["idleTickDelay"].as(5U);
- if (m_idleTickDelay < 1U)
- m_idleTickDelay = 1U;
-
- m_identity = systemConf["identity"].as();
- m_fixedMode = systemConf["fixedMode"].as(false);
-
- if (m_identity.length() > 8) {
- std::string identity = m_identity;
- m_identity = identity.substr(0, 8);
-
- ::LogWarning(LOG_HOST, "System Identity \"%s\" is too long; truncating to 8 characters, \"%s\".", identity.c_str(), m_identity.c_str());
- }
-
- int8_t lto = (int8_t)systemConf["localTimeOffset"].as(0);
-
- removeLockFile();
-
- LogInfo("General Parameters");
- if (!udpMasterMode) {
- LogInfo(" DMR: %s", m_dmrEnabled ? "enabled" : "disabled");
- LogInfo(" P25: %s", m_p25Enabled ? "enabled" : "disabled");
- LogInfo(" NXDN: %s", m_nxdnEnabled ? "enabled" : "disabled");
- LogInfo(" Duplex: %s", m_duplex ? "yes" : "no");
- if (!m_duplex) {
- LogInfo(" Simplex Same Frequency: %s", simplexSameFreq ? "yes" : "no");
- }
- LogInfo(" Active Tick Delay: %ums", m_activeTickDelay);
- LogInfo(" Idle Tick Delay: %ums", m_idleTickDelay);
- LogInfo(" Timeout: %us", m_timeout);
- LogInfo(" RF Mode Hang: %us", m_rfModeHang);
- LogInfo(" RF Talkgroup Hang: %us", m_rfTalkgroupHang);
- LogInfo(" Net Mode Hang: %us", m_netModeHang);
- LogInfo(" Identity: %s", m_identity.c_str());
- LogInfo(" Fixed Mode: %s", m_fixedMode ? "yes" : "no");
- LogInfo(" Lock Filename: %s", g_lockFile.c_str());
- LogInfo(" Local Time Offset: %dh", lto);
-
- yaml::Node systemInfo = systemConf["info"];
- m_latitude = systemInfo["latitude"].as(0.0F);
- m_longitude = systemInfo["longitude"].as(0.0F);
- m_height = systemInfo["height"].as(0);
- m_power = systemInfo["power"].as(0U);
- m_location = systemInfo["location"].as();
-
- LogInfo("System Info Parameters");
- LogInfo(" Latitude: %fdeg N", m_latitude);
- LogInfo(" Longitude: %fdeg E", m_longitude);
- LogInfo(" Height: %um", m_height);
- LogInfo(" Power: %uW", m_power);
- LogInfo(" Location: \"%s\"", m_location.c_str());
-
- // try to load bandplan identity table
- std::string idenLookupFile = systemConf["iden_table"]["file"].as();
- uint32_t idenReloadTime = systemConf["iden_table"]["time"].as(0U);
-
- if (idenLookupFile.length() <= 0U) {
- ::LogError(LOG_HOST, "No bandplan identity table? This must be defined!");
- return false;
- }
-
- LogInfo("Iden Table Lookups");
- LogInfo(" File: %s", idenLookupFile.length() > 0U ? idenLookupFile.c_str() : "None");
- if (idenReloadTime > 0U)
- LogInfo(" Reload: %u mins", idenReloadTime);
-
- m_idenTable = new IdenTableLookup(idenLookupFile, idenReloadTime);
- m_idenTable->read();
-
- /*
- ** Channel Configuration
- */
- yaml::Node rfssConfig = systemConf["config"];
- m_channelId = (uint8_t)rfssConfig["channelId"].as(0U);
- if (m_channelId > 15U) { // clamp to 15
- m_channelId = 15U;
- }
-
- IdenTable entry = m_idenTable->find(m_channelId);
- if (entry.baseFrequency() == 0U) {
- ::LogError(LOG_HOST, "Channel Id %u has an invalid base frequency.", m_channelId);
- return false;
- }
-
- m_channelNo = (uint32_t)::strtoul(rfssConfig["channelNo"].as("1").c_str(), NULL, 16);
- if (m_channelNo == 0U) { // clamp to 1
- m_channelNo = 1U;
- }
- if (m_channelNo > 4095U) { // clamp to 4095
- m_channelNo = 4095U;
- }
-
- if (entry.txOffsetMhz() == 0U) {
- ::LogError(LOG_HOST, "Channel Id %u has an invalid Tx offset.", m_channelId);
- return false;
- }
-
- uint32_t calcSpace = (uint32_t)(entry.chSpaceKhz() / 0.125);
- float calcTxOffset = entry.txOffsetMhz() * 1000000;
-
- m_txFrequency = (uint32_t)((entry.baseFrequency() + ((calcSpace * 125) * m_channelNo)));
- m_rxFrequency = (uint32_t)(m_txFrequency + calcTxOffset);
-
- if (calcTxOffset < 0.0f && m_rxFrequency < entry.baseFrequency()) {
- ::LogWarning(LOG_HOST, "Channel Id %u Channel No $%04X has an invalid frequency. Rx Frequency (%u) is less then the base frequency (%u), this may result in incorrect trunking behavior.", m_channelId, m_channelNo,
- m_rxFrequency, entry.baseFrequency());
- }
-
- if (!m_duplex && simplexSameFreq) {
- m_rxFrequency = m_txFrequency;
- }
-
- /*
- ** Control Channel
- */
- {
- yaml::Node controlCh = rfssConfig["controlCh"];
-
- std::string restApiAddress = controlCh["restAddress"].as("");
- uint16_t restApiPort = (uint16_t)controlCh["restPort"].as(REST_API_DEFAULT_PORT);
- std::string restApiPassword = controlCh["restPassword"].as();
-
- VoiceChData data = VoiceChData(m_channelId, m_channelNo, restApiAddress, restApiPort, restApiPassword);
- m_controlChData = data;
-
- if (!m_controlChData.address().empty() && m_controlChData.port() > 0) {
- ::LogInfoEx(LOG_HOST, "Control Channel REST API Address %s:%u", m_controlChData.address().c_str(), m_controlChData.port());
- } else {
- ::LogInfoEx(LOG_HOST, "No Control Channel REST API Configured, CC notify disabled");
- }
- }
-
- /*
- ** Voice Channels
- */
- yaml::Node& voiceChList = rfssConfig["voiceChNo"];
-
- if (voiceChList.size() == 0U) {
- ::LogError(LOG_HOST, "No voice channel list defined!");
- return false;
- }
-
- for (size_t i = 0; i < voiceChList.size(); i++) {
- yaml::Node& channel = voiceChList[i];
-
- uint8_t chId = (uint8_t)channel["channelId"].as(255U);
-
- // special case default handling for if the channelId field is missing from the
- // configuration
- if (chId == 255U) {
- chId = m_channelId;
- }
-
- if (chId > 15U) { // clamp to 15
- chId = 15U;
- }
-
- uint32_t chNo = (uint32_t)::strtoul(channel["channelNo"].as("1").c_str(), NULL, 16);
- if (chNo == 0U) { // clamp to 1
- chNo = 1U;
- }
- if (chNo > 4095U) { // clamp to 4095
- chNo = 4095U;
- }
-
- std::string restApiAddress = channel["restAddress"].as("127.0.0.1");
- uint16_t restApiPort = (uint16_t)channel["restPort"].as(REST_API_DEFAULT_PORT);
- std::string restApiPassword = channel["restPassword"].as();
-
- ::LogInfoEx(LOG_HOST, "Voice Channel Id %u Channel No $%04X REST API Address %s:%u", chId, chNo, restApiAddress.c_str(), restApiPort);
-
- VoiceChData data = VoiceChData(chId, chNo, restApiAddress, restApiPort, restApiPassword);
- m_voiceChData[chNo] = data;
- m_voiceChNo.push_back(chNo);
- }
-
- std::string strVoiceChNo = "";
- for (auto it = m_voiceChNo.begin(); it != m_voiceChNo.end(); ++it) {
- uint32_t chNo = ::atoi(std::to_string(*it).c_str());
- ::lookups::VoiceChData voiceChData = m_voiceChData[chNo];
-
- char hexStr[29];
-
- ::sprintf(hexStr, "$%01X.%01X (%u.%u)", voiceChData.chId(), chNo, voiceChData.chId(), chNo);
-
- strVoiceChNo.append(std::string(hexStr));
- strVoiceChNo.append(",");
- }
- strVoiceChNo.erase(strVoiceChNo.find_last_of(","));
-
- /*
- ** Site Parameters
- */
- m_siteId = (uint8_t)::strtoul(rfssConfig["siteId"].as("1").c_str(), NULL, 16);
- m_siteId = p25::P25Utils::siteId(m_siteId);
-
- m_dmrColorCode = rfssConfig["colorCode"].as(2U);
- m_dmrColorCode = dmr::DMRUtils::colorCode(m_dmrColorCode);
-
- m_dmrNetId = (uint32_t)::strtoul(rfssConfig["dmrNetId"].as("1").c_str(), NULL, 16);
- m_dmrNetId = dmr::DMRUtils::netId(m_dmrNetId, dmr::SITE_MODEL_TINY);
-
- m_p25NAC = (uint32_t)::strtoul(rfssConfig["nac"].as("293").c_str(), NULL, 16);
- m_p25NAC = p25::P25Utils::nac(m_p25NAC);
-
- uint32_t p25TxNAC = (uint32_t)::strtoul(rfssConfig["txNAC"].as("F7E").c_str(), NULL, 16);
- if (p25TxNAC == m_p25NAC) {
- LogWarning(LOG_HOST, "Only use txNAC when split NAC operations are needed. nac and txNAC should not be the same!");
- }
-
- m_p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as("BB800").c_str(), NULL, 16);
- m_p25NetId = p25::P25Utils::netId(m_p25NetId);
- if (m_p25NetId == 0xBEE00) {
- ::fatal("error 4\n");
- }
-
- m_sysId = (uint32_t)::strtoul(rfssConfig["sysId"].as("001").c_str(), NULL, 16);
- m_sysId = p25::P25Utils::sysId(m_sysId);
-
- m_p25RfssId = (uint8_t)::strtoul(rfssConfig["rfssId"].as("1").c_str(), NULL, 16);
- m_p25RfssId = p25::P25Utils::rfssId(m_p25RfssId);
-
- m_nxdnRAN = rfssConfig["ran"].as(1U);
-
- m_authoritative = rfssConfig["authoritative"].as(true);
-
- LogInfo("System Config Parameters");
- LogInfo(" Authoritative: %s", m_authoritative ? "yes" : "no");
- if (m_authoritative) {
- m_supervisor = rfssConfig["supervisor"].as(false);
- LogInfo(" Supervisor: %s", m_supervisor ? "yes" : "no");
- }
- LogInfo(" RX Frequency: %uHz", m_rxFrequency);
- LogInfo(" TX Frequency: %uHz", m_txFrequency);
- LogInfo(" Base Frequency: %uHz", entry.baseFrequency());
- LogInfo(" TX Offset: %fMHz", entry.txOffsetMhz());
- LogInfo(" Bandwidth: %fKHz", entry.chBandwidthKhz());
- LogInfo(" Channel Spacing: %fKHz", entry.chSpaceKhz());
- LogInfo(" Channel Id: %u", m_channelId);
- LogInfo(" Channel No.: $%04X (%u)", m_channelNo, m_channelNo);
- LogInfo(" Voice Channel No(s).: %s", strVoiceChNo.c_str());
- LogInfo(" Site Id: $%02X", m_siteId);
- LogInfo(" System Id: $%03X", m_sysId);
- LogInfo(" DMR Color Code: %u", m_dmrColorCode);
- LogInfo(" DMR Network Id: $%05X", m_dmrNetId);
- LogInfo(" P25 NAC: $%03X", m_p25NAC);
-
- if (p25TxNAC != 0xF7EU && p25TxNAC != m_p25NAC) {
- LogInfo(" P25 Tx NAC: $%03X", p25TxNAC);
- }
-
- LogInfo(" P25 Network Id: $%05X", m_p25NetId);
- LogInfo(" P25 RFSS Id: $%02X", m_p25RfssId);
- LogInfo(" NXDN RAN: %u", m_nxdnRAN);
-
- if (!m_authoritative) {
- m_supervisor = false;
- LogWarning(LOG_HOST, "Host is non-authoritative! This requires REST API to handle permit TG for VCs and grant TG for CCs!");
- }
- }
- else {
- LogInfo(" Modem Remote Control: yes");
- }
-
- return true;
-}
-
-///
-/// Initializes the modem DSP.
-///
-bool Host::createModem()
-{
- yaml::Node protocolConf = m_conf["protocols"];
-
- yaml::Node dmrProtocol = protocolConf["dmr"];
- uint32_t dmrQueueSize = dmrProtocol["queueSize"].as(24U);
-
- // clamp queue size to no less then 24 and no greater the 100
- if (dmrQueueSize < 24U) {
- LogWarning(LOG_HOST, "DMR queue size must be greater then 24 frames, defaulting to 24 frames!");
- dmrQueueSize = 24U;
- }
- if (dmrQueueSize > 100U) {
- LogWarning(LOG_HOST, "DMR queue size must be less then 100 frames, defaulting to 100 frames!");
- dmrQueueSize = 100U;
- }
- if (dmrQueueSize > 60U) {
- LogWarning(LOG_HOST, "DMR queue size is excessive, >60 frames!");
- }
-
- m_dmrQueueSizeBytes = dmrQueueSize * (dmr::DMR_FRAME_LENGTH_BYTES * 5U);
-
- yaml::Node p25Protocol = protocolConf["p25"];
- uint32_t p25QueueSize = p25Protocol["queueSize"].as(12U);
-
- // clamp queue size to no less then 12 and no greater the 100 frames
- if (p25QueueSize < 12U) {
- LogWarning(LOG_HOST, "P25 queue size must be greater then 12 frames, defaulting to 12 frames!");
- p25QueueSize = 12U;
- }
- if (p25QueueSize > 50U) {
- LogWarning(LOG_HOST, "P25 queue size must be less then 50 frames, defaulting to 50 frames!");
- p25QueueSize = 50U;
- }
- if (p25QueueSize > 30U) {
- LogWarning(LOG_HOST, "P25 queue size is excessive, >30 frames!");
- }
-
- m_p25QueueSizeBytes = p25QueueSize * p25::P25_LDU_FRAME_LENGTH_BYTES;
-
- yaml::Node nxdnProtocol = protocolConf["nxdn"];
- uint32_t nxdnQueueSize = nxdnProtocol["queueSize"].as(31U);
-
- // clamp queue size to no less then 31 and no greater the 50 frames
- if (nxdnQueueSize < 31U) {
- LogWarning(LOG_HOST, "NXDN queue size must be greater then 31 frames, defaulting to 31 frames!");
- nxdnQueueSize = 31U;
- }
- if (nxdnQueueSize > 50U) {
- LogWarning(LOG_HOST, "NXDN queue size must be less then 50 frames, defaulting to 50 frames!");
- nxdnQueueSize = 50U;
- }
-
- m_nxdnQueueSizeBytes = nxdnQueueSize * nxdn::NXDN_FRAME_LENGTH_BYTES;
-
- yaml::Node modemConf = m_conf["system"]["modem"];
-
- yaml::Node modemProtocol = modemConf["protocol"];
- std::string portType = modemProtocol["type"].as("null");
- yaml::Node uartProtocol = modemProtocol["uart"];
- std::string uartPort = uartProtocol["port"].as();
- uint32_t uartSpeed = uartProtocol["speed"].as(115200);
-
- bool rxInvert = modemConf["rxInvert"].as(false);
- bool txInvert = modemConf["txInvert"].as(false);
- bool pttInvert = modemConf["pttInvert"].as(false);
- bool dcBlocker = modemConf["dcBlocker"].as(true);
- bool cosLockout = modemConf["cosLockout"].as(false);
- uint8_t fdmaPreamble = (uint8_t)modemConf["fdmaPreamble"].as(80U);
- uint8_t dmrRxDelay = (uint8_t)modemConf["dmrRxDelay"].as(7U);
- uint8_t p25CorrCount = (uint8_t)modemConf["p25CorrCount"].as(4U);
- int rxDCOffset = modemConf["rxDCOffset"].as(0);
- int txDCOffset = modemConf["txDCOffset"].as(0);
-
- yaml::Node hotspotParams = modemConf["hotspot"];
-
- int dmrDiscBWAdj = hotspotParams["dmrDiscBWAdj"].as(0);
- int p25DiscBWAdj = hotspotParams["p25DiscBWAdj"].as(0);
- int nxdnDiscBWAdj = hotspotParams["nxdnDiscBWAdj"].as(0);
- int dmrPostBWAdj = hotspotParams["dmrPostBWAdj"].as(0);
- int p25PostBWAdj = hotspotParams["p25PostBWAdj"].as(0);
- int nxdnPostBWAdj = hotspotParams["nxdnPostBWAdj"].as(0);
- ADF_GAIN_MODE adfGainMode = (ADF_GAIN_MODE)hotspotParams["adfGainMode"].as(0U);
- bool afcEnable = hotspotParams["afcEnable"].as(false);
- uint8_t afcKI = (uint8_t)hotspotParams["afcKI"].as(11U);
- uint8_t afcKP = (uint8_t)hotspotParams["afcKP"].as(4U);
- uint8_t afcRange = (uint8_t)hotspotParams["afcRange"].as(1U);
- int rxTuning = hotspotParams["rxTuning"].as(0);
- int txTuning = hotspotParams["txTuning"].as(0);
- uint8_t rfPower = (uint8_t)hotspotParams["rfPower"].as(100U);
-
- yaml::Node repeaterParams = modemConf["repeater"];
-
- int dmrSymLevel3Adj = repeaterParams["dmrSymLvl3Adj"].as(0);
- int dmrSymLevel1Adj = repeaterParams["dmrSymLvl1Adj"].as(0);
- int p25SymLevel3Adj = repeaterParams["p25SymLvl3Adj"].as(0);
- int p25SymLevel1Adj = repeaterParams["p25SymLvl1Adj"].as(0);
- int nxdnSymLevel3Adj = repeaterParams["nxdnSymLvl3Adj"].as(0);
- int nxdnSymLevel1Adj = repeaterParams["nxdnSymLvl1Adj"].as(0);
-
- yaml::Node softpotParams = modemConf["softpot"];
-
- uint8_t rxCoarse = (uint8_t)softpotParams["rxCoarse"].as(127U);
- uint8_t rxFine = (uint8_t)softpotParams["rxFine"].as(127U);
- uint8_t txCoarse = (uint8_t)softpotParams["txCoarse"].as(127U);
- uint8_t txFine = (uint8_t)softpotParams["txFine"].as(127U);
- uint8_t rssiCoarse = (uint8_t)softpotParams["rssiCoarse"].as(127U);
- uint8_t rssiFine = (uint8_t)softpotParams["rssiFine"].as(127U);
-
- uint16_t dmrFifoLength = (uint16_t)modemConf["dmrFifoLength"].as(DMR_TX_BUFFER_LEN);
- uint16_t p25FifoLength = (uint16_t)modemConf["p25FifoLength"].as(P25_TX_BUFFER_LEN);
- uint16_t nxdnFifoLength = (uint16_t)modemConf["nxdnFifoLength"].as(NXDN_TX_BUFFER_LEN);
-
- float rxLevel = modemConf["rxLevel"].as(50.0F);
- float cwIdTXLevel = modemConf["cwIdTxLevel"].as(50.0F);
- float dmrTXLevel = modemConf["dmrTxLevel"].as(50.0F);
- float p25TXLevel = modemConf["p25TxLevel"].as(50.0F);
- float nxdnTXLevel = modemConf["nxdnTxLevel"].as(50.0F);
- if (!modemConf["txLevel"].isNone()) {
- cwIdTXLevel = dmrTXLevel = p25TXLevel = nxdnTXLevel = modemConf["txLevel"].as(50.0F);
- }
- bool disableOFlowReset = modemConf["disableOFlowReset"].as(false);
- bool ignoreModemConfigArea = modemConf["ignoreModemConfigArea"].as(false);
- bool dumpModemStatus = modemConf["dumpModemStatus"].as(false);
- bool trace = modemConf["trace"].as(false);
- bool debug = modemConf["debug"].as(false);
-
- if (rfPower == 0U) { // clamp to 1
- rfPower = 1U;
- }
- if (rfPower > 100U) { // clamp to 100
- rfPower = 100U;
- }
-
- LogInfo("Modem Parameters");
- LogInfo(" Port Type: %s", portType.c_str());
-
- port::IModemPort* modemPort = nullptr;
- std::transform(portType.begin(), portType.end(), portType.begin(), ::tolower);
- if (portType == NULL_PORT) {
- modemPort = new port::ModemNullPort();
- }
- else if (portType == UART_PORT || portType == PTY_PORT) {
- port::SERIAL_SPEED serialSpeed = port::SERIAL_115200;
- switch (uartSpeed) {
- case 1200:
- serialSpeed = port::SERIAL_1200;
- break;
- case 2400:
- serialSpeed = port::SERIAL_2400;
- break;
- case 4800:
- serialSpeed = port::SERIAL_4800;
- break;
- case 9600:
- serialSpeed = port::SERIAL_9600;
- break;
- case 19200:
- serialSpeed = port::SERIAL_19200;
- break;
- case 38400:
- serialSpeed = port::SERIAL_38400;
- break;
- case 76800:
- serialSpeed = port::SERIAL_76800;
- break;
- case 230400:
- serialSpeed = port::SERIAL_230400;
- break;
- case 460800:
- serialSpeed = port::SERIAL_460800;
- break;
- default:
- LogWarning(LOG_HOST, "Unsupported serial speed %u, defaulting to %u", uartSpeed, port::SERIAL_115200);
- uartSpeed = 115200;
- case 115200:
- break;
- }
-
- if (portType == PTY_PORT) {
- modemPort = new port::UARTPort(uartPort, serialSpeed, false);
- LogInfo(" PTY Port: %s", uartPort.c_str());
- LogInfo(" PTY Speed: %u", uartSpeed);
- }
- else {
- modemPort = new port::UARTPort(uartPort, serialSpeed, true);
- LogInfo(" UART Port: %s", uartPort.c_str());
- LogInfo(" UART Speed: %u", uartSpeed);
- }
- }
- else {
- LogError(LOG_HOST, "Invalid protocol port type, %s!", portType.c_str());
- return false;
- }
-
- if (g_remoteModemMode) {
- if (portType == UART_PORT || portType == PTY_PORT) {
- m_modemRemotePort = new port::UDPPort(g_remoteAddress, g_remotePort);
- m_modemRemote = true;
- ignoreModemConfigArea = true;
-
- }
- else {
- delete modemPort;
- modemPort = new port::UDPPort(g_remoteAddress, g_remotePort);
- m_modemRemote = false;
- }
-
- LogInfo(" UDP Mode: %s", m_modemRemote ? "master" : "peer");
- LogInfo(" UDP Address: %s", g_remoteAddress.c_str());
- LogInfo(" UDP Port: %u", g_remotePort);
- }
-
- if (!m_modemRemote) {
- LogInfo(" RX Invert: %s", rxInvert ? "yes" : "no");
- LogInfo(" TX Invert: %s", txInvert ? "yes" : "no");
- LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no");
- LogInfo(" DC Blocker: %s", dcBlocker ? "yes" : "no");
- LogInfo(" COS Lockout: %s", cosLockout ? "yes" : "no");
- LogInfo(" FDMA Preambles: %u (%.1fms)", fdmaPreamble, float(fdmaPreamble) * 0.2222F);
- LogInfo(" DMR RX Delay: %u (%.1fms)", dmrRxDelay, float(dmrRxDelay) * 0.0416666F);
- LogInfo(" P25 Corr. Count: %u (%.1fms)", p25CorrCount, float(p25CorrCount) * 0.667F);
- LogInfo(" RX DC Offset: %d", rxDCOffset);
- LogInfo(" TX DC Offset: %d", txDCOffset);
- LogInfo(" RX Tuning Offset: %dhz", rxTuning);
- LogInfo(" TX Tuning Offset: %dhz", txTuning);
- LogInfo(" RX Effective Frequency: %uhz", m_rxFrequency + rxTuning);
- LogInfo(" TX Effective Frequency: %uhz", m_txFrequency + txTuning);
- LogInfo(" RX Coarse: %u, Fine: %u", rxCoarse, rxFine);
- LogInfo(" TX Coarse: %u, Fine: %u", txCoarse, txFine);
- LogInfo(" RSSI Coarse: %u, Fine: %u", rssiCoarse, rssiFine);
- LogInfo(" RF Power Level: %u", rfPower);
- LogInfo(" RX Level: %.1f%%", rxLevel);
- LogInfo(" CW Id TX Level: %.1f%%", cwIdTXLevel);
- LogInfo(" DMR TX Level: %.1f%%", dmrTXLevel);
- LogInfo(" P25 TX Level: %.1f%%", p25TXLevel);
- LogInfo(" NXDN TX Level: %.1f%%", nxdnTXLevel);
- LogInfo(" Disable Overflow Reset: %s", disableOFlowReset ? "yes" : "no");
- LogInfo(" DMR Queue Size: %u (%u bytes)", dmrQueueSize, m_dmrQueueSizeBytes);
- LogInfo(" P25 Queue Size: %u (%u bytes)", p25QueueSize, m_p25QueueSizeBytes);
- LogInfo(" NXDN Queue Size: %u (%u bytes)", nxdnQueueSize, m_nxdnQueueSizeBytes);
- LogInfo(" DMR FIFO Size: %u bytes", dmrFifoLength);
- LogInfo(" P25 FIFO Size: %u bytes", p25FifoLength);
- LogInfo(" NXDN FIFO Size: %u bytes", nxdnFifoLength);
-
- if (ignoreModemConfigArea) {
- LogInfo(" Ignore Modem Configuration Area: yes");
- }
-
- if (dumpModemStatus) {
- LogInfo(" Dump Modem Status: yes");
- }
- }
-
- if (debug) {
- LogInfo(" Debug: yes");
- }
-
- m_modem = new Modem(modemPort, m_duplex, rxInvert, txInvert, pttInvert, dcBlocker, cosLockout, fdmaPreamble, dmrRxDelay, p25CorrCount,
- m_dmrQueueSizeBytes, m_p25QueueSizeBytes, m_nxdnQueueSizeBytes, disableOFlowReset, ignoreModemConfigArea, dumpModemStatus, trace, debug);
- if (!m_modemRemote) {
- m_modem->setModeParams(m_dmrEnabled, m_p25Enabled, m_nxdnEnabled);
- m_modem->setLevels(rxLevel, cwIdTXLevel, dmrTXLevel, p25TXLevel, nxdnTXLevel);
- m_modem->setSymbolAdjust(dmrSymLevel3Adj, dmrSymLevel1Adj, p25SymLevel3Adj, p25SymLevel1Adj, nxdnSymLevel3Adj, nxdnSymLevel1Adj);
- m_modem->setDCOffsetParams(txDCOffset, rxDCOffset);
- m_modem->setRFParams(m_rxFrequency, m_txFrequency, rxTuning, txTuning, rfPower, dmrDiscBWAdj, p25DiscBWAdj, nxdnDiscBWAdj, dmrPostBWAdj,
- p25PostBWAdj, nxdnPostBWAdj, adfGainMode, afcEnable, afcKI, afcKP, afcRange);
- m_modem->setSoftPot(rxCoarse, rxFine, txCoarse, txFine, rssiCoarse, rssiFine);
- m_modem->setDMRColorCode(m_dmrColorCode);
- m_modem->setP25NAC(m_p25NAC);
- }
-
- if (m_modemRemote) {
- m_modem->setOpenHandler(MODEM_OC_PORT_HANDLER_BIND(Host::rmtPortModemOpen, this));
- m_modem->setCloseHandler(MODEM_OC_PORT_HANDLER_BIND(Host::rmtPortModemClose, this));
- m_modem->setResponseHandler(MODEM_RESP_HANDLER_BIND(Host::rmtPortModemHandler, this));
- }
-
- bool ret = m_modem->open();
- if (!ret) {
- delete m_modem;
- m_modem = nullptr;
- return false;
- }
-
- m_modem->setFifoLength(dmrFifoLength, p25FifoLength, nxdnFifoLength);
-
- // are we on a protocol version older then 3?
- if (m_modem->getVersion() < 3U) {
- if (m_nxdnEnabled) {
- ::LogError(LOG_HOST, "NXDN is not supported on legacy firmware.");
- return false;
- }
- }
-
- return true;
-}
-
-///
-/// Initializes network connectivity.
-///
-bool Host::createNetwork()
-{
- yaml::Node networkConf = m_conf["network"];
- bool netEnable = networkConf["enable"].as(false);
- bool restApiEnable = networkConf["restEnable"].as(false);
-
- // dump out if both networking and REST API are disabled
- if (!netEnable && !restApiEnable) {
- return true;
- }
-
- std::string address = networkConf["address"].as();
- uint16_t port = (uint16_t)networkConf["port"].as(TRAFFIC_DEFAULT_PORT);
- uint16_t local = (uint16_t)networkConf["local"].as(0U);
- std::string restApiAddress = networkConf["restAddress"].as("127.0.0.1");
- uint16_t restApiPort = (uint16_t)networkConf["restPort"].as(REST_API_DEFAULT_PORT);
- std::string restApiPassword = networkConf["restPassword"].as();
- bool restApiDebug = networkConf["restDebug"].as(false);
- uint32_t id = networkConf["id"].as(1000U);
- uint32_t jitter = networkConf["talkgroupHang"].as(360U);
- std::string password = networkConf["password"].as();
- bool slot1 = networkConf["slot1"].as(true);
- bool slot2 = networkConf["slot2"].as(true);
- bool allowActivityTransfer = networkConf["allowActivityTransfer"].as(false);
- bool allowDiagnosticTransfer = networkConf["allowDiagnosticTransfer"].as(false);
- bool updateLookup = networkConf["updateLookups"].as(false);
- bool debug = networkConf["debug"].as(false);
-
- if (id > 999999999U) {
- ::LogError(LOG_HOST, "Network Peer ID cannot be greater then 999999999.");
- return false;
- }
-
- if (restApiPassword.length() > 64) {
- std::string password = restApiPassword;
- restApiPassword = password.substr(0, 64);
-
- ::LogWarning(LOG_HOST, "REST API password is too long; truncating to the first 64 characters.");
- }
-
- if (restApiPassword.empty() && restApiEnable) {
- ::LogWarning(LOG_HOST, "REST API password not provided; REST API disabled.");
- restApiEnable = false;
- }
-
- IdenTable entry = m_idenTable->find(m_channelId);
-
- LogInfo("Network Parameters");
- LogInfo(" Enabled: %s", netEnable ? "yes" : "no");
- if (netEnable) {
- LogInfo(" Peer ID: %u", id);
- LogInfo(" Address: %s", address.c_str());
- LogInfo(" Port: %u", port);
- if (local > 0U)
- LogInfo(" Local: %u", local);
- else
- LogInfo(" Local: random");
- LogInfo(" DMR Jitter: %ums", jitter);
- LogInfo(" Slot 1: %s", slot1 ? "enabled" : "disabled");
- LogInfo(" Slot 2: %s", slot2 ? "enabled" : "disabled");
- LogInfo(" Allow Activity Log Transfer: %s", allowActivityTransfer ? "yes" : "no");
- LogInfo(" Allow Diagnostic Log Transfer: %s", allowDiagnosticTransfer ? "yes" : "no");
- LogInfo(" Update Lookups: %s", updateLookup ? "yes" : "no");
-
- if (debug) {
- LogInfo(" Debug: yes");
- }
- }
- LogInfo(" REST API Enabled: %s", restApiEnable ? "yes" : "no");
- if (restApiEnable) {
- LogInfo(" REST API Address: %s", restApiAddress.c_str());
- LogInfo(" REST API Port: %u", restApiPort);
-
- if (restApiDebug) {
- LogInfo(" REST API Debug: yes");
- }
- }
-
- // initialize networking
- if (netEnable) {
- m_network = new Network(address, port, local, id, password, m_duplex, debug, m_dmrEnabled, m_p25Enabled, m_nxdnEnabled, slot1, slot2, allowActivityTransfer, allowDiagnosticTransfer, updateLookup);
-
- m_network->setLookups(m_ridLookup, m_tidLookup);
- m_network->setMetadata(m_identity, m_rxFrequency, m_txFrequency, entry.txOffsetMhz(), entry.chBandwidthKhz(), m_channelId, m_channelNo,
- m_power, m_latitude, m_longitude, m_height, m_location);
- if (restApiEnable) {
- m_network->setRESTAPIData(restApiPassword, restApiPort);
- }
-
- m_network->enable(true);
- bool ret = m_network->open();
- if (!ret) {
- delete m_network;
- m_network = nullptr;
- LogError(LOG_HOST, "failed to initialize traffic networking!");
- return false;
- }
-
- ::LogSetNetwork(m_network);
- }
-
- // initialize network remote command
- if (restApiEnable) {
- m_RESTAPI = new RESTAPI(restApiAddress, restApiPort, restApiPassword, this, restApiDebug);
- m_RESTAPI->setLookups(m_ridLookup, m_tidLookup);
- bool ret = m_RESTAPI->open();
- if (!ret) {
- delete m_RESTAPI;
- m_RESTAPI = nullptr;
- LogError(LOG_HOST, "failed to initialize REST API networking! REST API will be unavailable!");
- // REST API failing isn't fatal -- we'll allow this to return normally
- }
- }
- else {
- m_RESTAPI = nullptr;
- }
-
- return true;
-}
-
///
///
///
diff --git a/src/host/Host.h b/src/host/Host.h
index 07423a3b..aa12a1b4 100644
--- a/src/host/Host.h
+++ b/src/host/Host.h
@@ -165,13 +165,6 @@ private:
friend class RESTAPI;
RESTAPI* m_RESTAPI;
- /// Reads basic configuration parameters from the INI.
- bool readParams();
- /// Initializes the modem DSP.
- bool createModem();
- /// Initializes network connectivity.
- bool createNetwork();
-
/// Modem port open callback.
bool rmtPortModemOpen(modem::Modem* modem);
/// Modem port close callback.
@@ -187,7 +180,15 @@ private:
/// Helper to remove the state lock file.
void removeLockFile() const;
- /** Digital Mobile Radio */
+ /** (Host.Config.cpp) */
+ /// Reads basic configuration parameters from the INI.
+ bool readParams();
+ /// Initializes the modem DSP.
+ bool createModem();
+ /// Initializes network connectivity.
+ bool createNetwork();
+
+ /** Digital Mobile Radio (Host.DMR.cpp) */
/// Helper to interrupt a running DMR beacon.
void interruptDMRBeacon(dmr::Control* control);
@@ -200,7 +201,7 @@ private:
/// Helper to write DMR slot 2 frames to modem.
void writeFramesDMR2(dmr::Control* control, std::function&& afterWriteCallback);
- /** Project 25 */
+ /** Project 25 (Host.P25.cpp) */
/// Helper to interrupt a running P25 control channel.
void interruptP25Control(p25::Control* control);
@@ -209,7 +210,7 @@ private:
/// Helper to write P25 frames to modem.
void writeFramesP25(p25::Control* control, std::function&& afterWriteCallback);
- /** Next Generation Digital Narrowband */
+ /** Next Generation Digital Narrowband (Host.NXDN.cpp) */
/// Helper to interrupt a running NXDN control channel.
void interruptNXDNControl(nxdn::Control* control);