/** * Handler for aes data received transparent by the oc-laptop * $Id$ * $HeadURL$ * $Author$ * Created by Philipp Dassow, NLST, 18-04-2018 */ #include "handler_oc_aes_data.h" #include #include #include #include "settings.h" namespace OcSituationClient { HandlerOcAesData::HandlerOcAesData(MainHandler *mainHandler, QObject *parent) : QObject(parent) , m_dds(mainHandler->dds()) , m_aesDtc(mainHandler->aesDtc()) , m_aesFtc(mainHandler->aesFtc()) , m_gimDtc(mainHandler->gimDtc()) , m_tabDts(mainHandler->tabDts()) , m_tabocDtc(mainHandler->tabocDtc()) , m_utmCoord(LtsCoordTrans::UtmCoordinate::fromMgrs(Settings::baseCoord())) , m_logger(getLogger("HandlerOcAesData")) {} HandlerOcAesData::~HandlerOcAesData() {} bool HandlerOcAesData::init() { // AES DTC enable if (!m_aesDtc->enableDangerArea()) { ERROR_LOG(m_logger) << "Enabling AES Data-Topics failed."; return false; } // AES FTC enable if (!m_aesFtc->enableDangerAreaModify() || !m_aesFtc->enableDangerAreaRemove()) { ERROR_LOG(m_logger) << "Enabling AES Function-Topics failed."; return false; } // GIM DTC enable if (!m_gimDtc->enableIed()) { ERROR_LOG(m_logger) << "Enabling GIM Data-Topics failed."; return false; } // TAB DTS enable if (!m_tabDts->enableDefinitionIed()) { ERROR_LOG(m_logger) << "Enabling TAB DTS Data-Topics failed."; return false; } // TABOC DTC enable if (!m_tabocDtc->enableSpecificsExercise()) { ERROR_LOG(m_logger) << "Enabling TABOC Data-Topics failed."; return false; } connect(m_tabocDtc.get(), &TrainingAreaBaseOC::Interface::Dtc::specificsExerciseChanged, this, &HandlerOcAesData::onSpecificsExerciseChanged); auto cb = [this](const TrainingAreaBaseOC::SpecificsExercise & specificsExercise) { onSpecificsExerciseChanged(specificsExercise, DataModification::eAdded); }; m_tabocDtc->specificsExercises(cb); return true; } void HandlerOcAesData::process(const QByteArray &data) { DEBUG_LOG(m_logger) << "Compressed binary data: " << data.toHex(' '); QByteArray uncompressed = MainHandler::tryUncompress(data, true); DEBUG_LOG(m_logger) << "Uncompressed binary data: " << uncompressed.toHex(' '); OcSituation::AesType aesType; LtsUtils::get1Byte(uncompressed, aesType); size_t pos = 1; // first byte is aesType switch (aesType) { case OcSituation::AesType::DangerArea: { handleDangerAreas(uncompressed, pos); break; } case OcSituation::AesType::Ied: { handleIeds(uncompressed, pos); break; } case OcSituation::AesType::IedPositions: { handleIedPositions(uncompressed, pos); break; } default: { WARNING_LOG(m_logger) << "Aes type: " << aesType << " is currently not handled."; } } } void HandlerOcAesData::onDangerAreaModifyReply(const Core::FunctionReplyObject &reply) { if (reply.error()) ERROR_LOG(m_logger) << "Danger area modify failed: " << reply.translated(); else DEBUG_LOG(m_logger) << "Danger area modify successfull. Id: " << reply.id(); } void HandlerOcAesData::onDangerAreaRemoveReply(const Core::FunctionReplyObject &reply) { if (reply.error()) ERROR_LOG(m_logger) << "Danger area remove failed: " << reply.translated(); else DEBUG_LOG(m_logger) << "Danger area remove successfull. Id: " << reply.id(); } void HandlerOcAesData::handleDangerAreas(const QByteArray &data, size_t pos) { INFO_LOG(m_logger) << "Got new danger area data"; DEBUG_LOG(m_logger) << "Binary data: " << data.toHex(' '); QList aesToBeDeleted = m_aesDtc->dangerAreas().keys(); int cnt; LtsUtils::get1Byte(data, pos, cnt); AreaEffectSimulation::DangerAreaModifyRequest req; uint64_t tmp; int x = 0, y = 0; req.chargeTypeId = 311; // danger area for (int i = 0; i < cnt; ++i) { LtsUtils::get2Byte(data, pos, tmp); req.id = tmp; req.name = data.mid(pos, 8).toStdString(); pos += 8; LtsUtils::get4Byte(data, pos, tmp); if (tmp > 0) req.effectStart = dds::core::optional(tmp * 1000); else req.effectStart = dds::core::optional(); size_t segmentCnt = 0; LtsUtils::get1Byte(data, pos, segmentCnt); std::vector segments; segments.reserve(segmentCnt); for (size_t j = 0; j < segmentCnt; ++j) { LtsUtils::get3Byte(data, pos, y); LtsUtils::get3Byte(data, pos, x); segments.emplace_back(relativeFromGeoPosition(x, y)); } req.segments = segments; DEBUG_LOG(m_logger) << (aesToBeDeleted.contains(req.id) ? "Modifying " : "Creating ") << "danger area: " << req; aesToBeDeleted.removeAll(req.id); // item was created/modified -> does not need to be deleted req.id = req.id * -1; // inverted id to mark as for oc m_aesFtc->dangerAreaModifyRequest(req, this); } for (int id : std::as_const(aesToBeDeleted)) { if (m_aesDtc->dangerArea(id).isCentral) continue; if (m_aesDtc->dangerArea(id).effectStateId > AreaEffectSimulation::AesEffectState::EsRemoved) { DEBUG_LOG(m_logger) << "Removing danger area id: " << id; m_aesFtc->dangerAreaRemoveRequest(Core::RemoveElementRequest(id), this); } } } void HandlerOcAesData::handleIeds(const QByteArray &data, size_t pos) { INFO_LOG(m_logger) << "Got new ied data"; DEBUG_LOG(m_logger) << "Binary data: " << data.toHex(' '); int cnt; LtsUtils::get1Byte(data, pos, cnt); TrainingAreaBase::DefinitionIed def; unsigned long tmp; int x = 0, y = 0; def.pairingState = 1; // not paired in OC application for (int i = 0; i < cnt; ++i) { LtsUtils::get2Byte(data, pos, tmp); def.iedId = tmp; LtsUtils::get1Byte(data, pos, tmp); def.type = tmp; LtsUtils::get1Byte(data, pos, tmp); def.tautWireTrigger = (tmp >> 3) & 0x01; def.lightBarrierTrigger = (tmp >> 2) & 0x01; def.switchTrigger = (tmp >> 1) & 0x01; def.remoteTrigger = (tmp >> 0) & 0x01; LtsUtils::get1Byte(data, pos, tmp); def.explosiveForce = tmp; LtsUtils::get1Byte(data, pos, tmp); def.partyId = tmp; LtsUtils::get1Byte(data, pos, tmp); def.tacticalState = tmp; LtsUtils::get3Byte(data, pos, x); LtsUtils::get3Byte(data, pos, y); def.position = relativeFromGeoPosition(x, y); DEBUG_LOG(m_logger) << "Publishing definition ied: " << def; m_tabDts->publish(def); } } void HandlerOcAesData::handleIedPositions(const QByteArray &data, size_t pos) { INFO_LOG(m_logger) << "Got new ied positions data"; DEBUG_LOG(m_logger) << "Binary data: " << data.toHex(' '); int cnt; LtsUtils::get1Byte(data, pos, cnt); const QMap ieds = m_gimDtc->ieds(); QMap IedEqNumberToDdsId; // iedEqNumber, ddsId for (const auto &ied : ieds) IedEqNumberToDdsId.insert(ied.equipmentNumber, ied.id); TrainingAreaBase::DefinitionIed def; unsigned long eqNumber; int x = 0, y = 0; for (int i = 0; i < cnt; ++i) { LtsUtils::get2Byte(data, pos, eqNumber); const GuezIedManagement::Ied &ied = ieds.value(IedEqNumberToDdsId.value(eqNumber)); def.iedId = eqNumber; def.type = static_cast(ied.type); def.tautWireTrigger = ied.tautWireTrigger; def.lightBarrierTrigger = ied.lightBarrierTrigger; def.switchTrigger = ied.switchTrigger; def.remoteTrigger = ied.remoteTrigger; def.explosiveForce = ied.explosiveForce; def.partyId = ied.partyId; def.tacticalState = static_cast(ied.tacticalState); LtsUtils::get3Byte(data, pos, x); LtsUtils::get3Byte(data, pos, y); def.position = relativeFromGeoPosition(x, y); m_tabDts->publish(def); } } Core::GeoPosition2D HandlerOcAesData::relativeFromGeoPosition(int x, int y) { const QPointF point(m_utmCoord.geographic(x, y)); return Core::GeoPosition2D(point.x(), point.y()); } void HandlerOcAesData::onSpecificsExerciseChanged(const TrainingAreaBaseOC::SpecificsExercise &data, DataModification mod) { if (mod == DataModification::eAdded || mod == DataModification::eModified) m_utmCoord = LtsCoordTrans::UtmCoordinate::fromMgrs(QString::number(data.zone) + QLatin1Char(data.band) + QString::fromStdString(data.square) + QString::number(data.northing).rightJustified(7, QLatin1Char('0')) + QString::number(data.easting).rightJustified(7, QLatin1Char('0'))); } } // namespace OcSituationClient