#include "config_cnr.h" #include #include #include "helper.h" #include #include #include #include #include #include #include #include namespace CombatNetRadio { ConfigCnr::ConfigCnr(int exerciseId, AudioVideoManagement::Interface::Dtc *avmDtc, InfrastructureManagement::Interface::Dtc *ismDtc) : m_exerciseId(exerciseId) , m_avmDtc(avmDtc) , m_ismDtc(ismDtc) , m_loggerJson(getLogger("ConfigCnr.Json")), m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger()) { Q_ASSERT(avmDtc); Q_ASSERT(ismDtc); m_timer.setSingleShot(true); m_timer.setInterval(200); connect(&m_timer, &QTimer::timeout, this, &ConfigCnr::buildConfigCnrData); connect(m_avmDtc, &AudioVideoManagement::Interface::Dtc::activeFrequencyPlanningChanged, this, &ConfigCnr::onActiveFrequencyPlanningChanged); connect(m_avmDtc, &AudioVideoManagement::Interface::Dtc::frequencyPlanningChanged, this, &ConfigCnr::onFrequencyPlanningChanged); connect(m_avmDtc, &AudioVideoManagement::Interface::Dtc::cnrConfigChanged, this, &ConfigCnr::onCnrConfigChanged); buildConfigCnrData(); } const WebSocketInterface::Messages::ConfigCnrMessage::ConfigCnrData &ConfigCnr::data() const { Q_ASSERT(hasActiveFrequencyPlanning()); return m_configCnrData; } void ConfigCnr::buildConfigCnrData() { WebSocketInterface::Messages::ConfigCnrMessage::ConfigCnrData configCnr; boost::optional plan = activePlan(); if (!plan) { m_configCnrData = configCnr; emit changed(); return; } AudioVideoManagement::FrequencySet frequencySet = m_avmDtc->frequencySet(plan->frequencySetId); QMap fsdMap; for (const auto &fsd : std::as_const(frequencySet.data)) fsdMap.insert(fsd.id, fsd); configCnr.setId = plan->frequencySetId; configCnr.time = QDateTime::fromMSecsSinceEpoch(plan->date).toString(Qt::ISODate); configCnr.radioCircuit.reserve(plan->data.size()); for (const auto ¤tData : plan->data) { WebSocketInterface::Messages::ConfigCnrMessage::RadioCircuit radioCircuit; AudioVideoManagement::CnrConfig cnrConfig = m_avmDtc->cnrConfig(currentData.cnrConfigId); AudioVideoManagement::CnrChannel cnrChannel = m_avmDtc->cnrChannel(cnrConfig.cnrChannelId); QVector circuits = AudioVideoManagement::fromJson(currentData.properties); int subCircuitCount = 0; for (AudioVideoManagement::RadioCircuit* circuit : std::as_const(circuits)) { InfrastructureManagement::MainStructureElement radioStation = m_ismDtc->mainStructureElement(circuit->radioStationId); WebSocketInterface::Messages::ConfigCnrMessage::SubRadioCircuit subCircuit; switch (circuit->freqBand) { case AudioVideoManagement::FrequencyBand::VHF: { AudioVideoManagement::RadioCircuitVHF *rcVhf = dynamic_cast(circuit); if (!rcVhf) break; AudioVideoManagement::FrequencySetDataWithId &fsd = fsdMap[rcVhf->freqSetDataId]; subCircuit.agc = false; subCircuit.akw = fsd.akwBundle.is_set() ? fsd.akwBundle.get() : 0; subCircuit.channelSpacing = 0; subCircuit.clipper = false; subCircuit.comsec = fsd.comsec.is_set() ? fsd.comsec.get() : 0; subCircuit.crossbeam = 0; subCircuit.frequency = fsd.frequency * 1000; subCircuit.frequencyBand = static_cast(fsd.frequencyBand); subCircuit.fsb = fsd.fsbBundle.is_set() ? fsd.fsbBundle.get() : 0; subCircuit.modulationType = 0; subCircuit.orientation = 0; subCircuit.ptSig = rcVhf->pilotTone; subCircuit.rcAkw = fsd.akwRadioCircuit.is_set() ? fsd.akwRadioCircuit.get() : 0; subCircuit.rcMode = static_cast(rcVhf->operatingMode); subCircuit.rcSubId = toRcIdString(cnrChannel); subCircuit.rcSubName = rcVhf->name; subCircuit.rcType = 2; subCircuit.squelch = 0; subCircuit.station = stationId(radioStation); break; } case AudioVideoManagement::FrequencyBand::UHF: { AudioVideoManagement::RadioCircuitUHF *rcUhf = dynamic_cast(circuit); if (!rcUhf) break; subCircuit.agc = rcUhf->agc; subCircuit.akw = 0; subCircuit.channelSpacing = static_cast(rcUhf->channelSpacing); subCircuit.clipper = rcUhf->clipper; subCircuit.comsec = 0; subCircuit.crossbeam = 0; subCircuit.frequency = rcUhf->frequency; subCircuit.frequencyBand = 0; subCircuit.fsb = 0; subCircuit.modulationType = static_cast(rcUhf->modulationType); subCircuit.orientation = 0; subCircuit.ptSig = 0; subCircuit.rcAkw = 0; subCircuit.rcMode = 0; subCircuit.rcSubId = toRcIdString(cnrChannel); subCircuit.rcSubName = rcUhf->name; subCircuit.rcType = 3; subCircuit.squelch = rcUhf->squelchDB; subCircuit.station = stationId(radioStation); break; } case AudioVideoManagement::FrequencyBand::HF: { AudioVideoManagement::RadioCircuitHF *rcHf = dynamic_cast(circuit); if (!rcHf) break; subCircuit.agc = 0; subCircuit.akw = 0; subCircuit.channelSpacing = static_cast(rcHf->channelSpacing); subCircuit.clipper = 0; subCircuit.comsec = 0; subCircuit.crossbeam = 0; subCircuit.frequency = rcHf->frequency; subCircuit.frequencyBand = 0; subCircuit.fsb = 0; subCircuit.modulationType = static_cast(rcHf->modulationType); subCircuit.orientation = 0; subCircuit.ptSig = 0; subCircuit.rcAkw = 0; subCircuit.rcMode = 0; subCircuit.rcSubId = toRcIdString(cnrChannel); subCircuit.rcSubName = rcHf->name; subCircuit.rcType = 1; subCircuit.squelch = rcHf->squelch; subCircuit.station = stationId(radioStation); break; } default: break; } if (circuits.count() > 1) subCircuit.rcSubId.append(QChar('A' + subCircuitCount++)); radioCircuit.subCircuits.append(subCircuit); } qDeleteAll(circuits); radioCircuit.rcId = toRcIdString(cnrChannel); radioCircuit.rcName = QString::fromStdString(cnrConfig.radioCircuit); radioCircuit.ssrc = cnrChannel.ssrc; configCnr.radioCircuit.append(radioCircuit); } m_configCnrData = configCnr; emit changed(); } boost::optional ConfigCnr::activePlan() const { AudioVideoManagement::ActiveFrequencyPlanning activePlanning = m_avmDtc->activeFrequencyPlanning(m_exerciseId); if (activePlanning.exerciseId != m_exerciseId) return boost::none; AudioVideoManagement::FrequencyPlanning frequencyPlanning = m_avmDtc->frequencyPlanning(activePlanning.frequencyPlanningId); return frequencyPlanning; } void ConfigCnr::onActiveFrequencyPlanningChanged(const AudioVideoManagement::ActiveFrequencyPlanning &data, DataModification modType) { DEBUG_LOG(m_logger) << Q_FUNC_INFO << ": " << data; Q_UNUSED(modType); if (data.exerciseId == m_exerciseId) m_timer.start(); } void ConfigCnr::onFrequencyPlanningChanged(const AudioVideoManagement::FrequencyPlanning &data, DataModification modType) { DEBUG_LOG(m_logger) << Q_FUNC_INFO << ": " << data; Q_UNUSED(modType); boost::optional plan = activePlan(); if (!plan) return; if (data.id == plan->id || !data.exerciseId.is_set()) m_timer.start(); } void ConfigCnr::onCnrConfigChanged(const AudioVideoManagement::CnrConfig &data, DataModification modType) { DEBUG_LOG(m_logger) << Q_FUNC_INFO << ": " << data; Q_UNUSED(modType); bool isGlobal = !data.exerciseId.is_set(); if ((isGlobal || data.exerciseId.get() == m_exerciseId) && modType != DataModification::eAdded && isInActiveFrequencyPlanning(data)) m_timer.start(); } bool ConfigCnr::isInActiveFrequencyPlanning(const AudioVideoManagement::CnrConfig &data) { if(!data.exerciseId.is_set()) return true; const auto activePlans = m_avmDtc->activeFrequencyPlannings(); for (const AudioVideoManagement::ActiveFrequencyPlanning &activePlan : activePlans) { const auto frequencyPlannings = m_avmDtc->frequencyPlanning(activePlan.frequencyPlanningId); for(const auto &frequencyPlanningData : frequencyPlannings.data) { if(frequencyPlanningData.cnrConfigId == data.id) return true; } } return false; } }