/** * 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 "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 : qAsConst(aesToBeDeleted)) { if (m_aesDtc->dangerArea(id).isCentral()) continue; if (m_aesDtc->dangerArea(id).effectStateId().underlying() > 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(ied.type().underlying()); 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(ied.tacticalState().underlying()); 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