Files
qt5-legatus-legacy/Lts/Proxies/Buildings/BuildingControlUnit/main_handler.cpp
T
2026-08-13 18:33:10 +02:00

367 lines
13 KiB
C++
Executable File

/**
* @RDE_HEADER@
* main for BuildingControlUnit
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-01-27
*/
#include "main_handler.h"
#include <QWebSocket>
#include "VWM/vwm_types.h"
#include "bcu_xml_reader.h"
#include <settings.h>
#include "ControlEffects/xmlreader.h"
namespace BuildingControlUnit
{
MainHandler::MainHandler()
: QObject()
, m_bsmApi(nullptr)
, m_jsonApi(nullptr)
, m_vwmApi(nullptr)
, m_handelEffectsBsm(nullptr)
, m_handleHttpRequest(nullptr)
, m_bsmFlash(BEO_Auto)
, m_logger(getLogger("MainHandler"))
{}
MainHandler::~MainHandler()
{
cleanup();
}
bool MainHandler::init(const QString &ammuXml,
const QString &bldCfgXml,
const QString &vwmXml,
unsigned short listenPort,
const bool initBuilding,
const QString &controlEffectsCfg)
{
NOTICE_LOG(m_logger) << "----------------------------------------------------";
NOTICE_LOG(m_logger) << "-- start BuildingControlUnit --";
NOTICE_LOG(m_logger) << "----------------------------------------------------";
cleanup();
BuildingBsmConfig bsmConfig;
if (!parseBuildingConfigXml(bldCfgXml, bsmConfig, m_egcuConfig))
return false;
m_bsmApi = new BSM::Api(this);
//m_egcuApi = new EGCU::Api(this);
m_jsonApi = new Json::Api(this);
m_vwmApi = new VWM::Api(this);
m_handleHttpRequest = new HandleHttpRequest(Settings::useHttpQueue(), this);
m_bsmFlash = BEO_Auto;
if (m_egcuConfig.egcus.size() == 1 && m_egcuConfig.egcus.first().roomIds.isEmpty())
{
auto &egcu = m_egcuConfig.egcus.first();
const auto &bldg = m_vwmApi->building();
m_egcuConfig.egcus.reserve(bldg.rooms().size());
for (const auto &room : bldg.rooms())
egcu.roomIds.append(room.id());
}
if (!m_vwmApi->init(ammuXml, vwmXml, bsmConfig, initBuilding))
{
ERROR_LOG(m_logger) << "Can not initialize VWM API - aborting";
return false;
}
if (!m_jsonApi->init(listenPort))
{
ERROR_LOG(m_logger) << "Can not initialize Json API - aborting";
return false;
}
if (!m_bsmApi->init(bsmConfig))
{
ERROR_LOG(m_logger) << "Can not initialize BSM API - aborting";
return false;
}
m_handelEffectsVec.clear();
for ( int i = 0; i < m_egcuConfig.egcus.size(); i++)
{
NOTICE_LOG(m_logger) << "new BuildingControlUnit::HandelEffects " << m_egcuConfig.egcus[i].hostname;
BuildingControlUnit::HandelEffects *handleEffectsEgcu = new BuildingControlUnit::HandelEffects(this, m_egcuConfig.egcus[i].hostname);
handleEffectsEgcu->init(controlEffectsCfg, m_egcuConfig.egcus[i].hostname, ET_Relay);
connect(handleEffectsEgcu, &HandelEffects::newHttpRequest, m_handleHttpRequest, &HandleHttpRequest::enqueue);
connect(handleEffectsEgcu, &HandelEffects::sendRelayState, m_jsonApi, &Json::Api::onRelayState);
connect(m_handleHttpRequest, &HandleHttpRequest::egcuReply, handleEffectsEgcu, &HandelEffects::handleEgcuReply);
//connect(m_handleHttpRequest, &HandleHttpRequest::newEgcuConnection, this, &MainHandler::setInitialOverrides);
m_handelEffectsVec.append(handleEffectsEgcu);
}
m_handelEffectsBsm = new BuildingControlUnit::HandelEffects(this, QStringLiteral("BSMs"));
m_handelEffectsBsm->init(controlEffectsCfg, QString(), ET_BsmFlash);
connect(m_handelEffectsBsm, &HandelEffects::triggerAllFlashlights, m_bsmApi, &BSM::Api::triggerFlashlights);
connect(m_bsmApi, &BSM::Api::opticalShot, m_vwmApi, &VWM::Api::onHitOptical);
connect(m_bsmApi, &BSM::Api::opticalShotOC, m_vwmApi, &VWM::Api::onHitOpticalOC);
connect(m_vwmApi, &VWM::Api::hitResult, this, &MainHandler::onHitResult);
connect(m_vwmApi, &VWM::Api::unknownDirectHit, this, &MainHandler::onUnknownDirectHit);
connect(m_jsonApi, &Json::Api::damageStateRequest, m_vwmApi, &VWM::Api::onHitEcc);
connect(m_jsonApi, &Json::Api::setContaminationStateRequest,m_vwmApi, &VWM::Api::onSetContaminationState);
connect(m_jsonApi, &Json::Api::resetContaminationRequest, m_vwmApi, &VWM::Api::onResetContaminations);
connect(m_jsonApi, &Json::Api::setFortifyFactorRequest, m_vwmApi, &VWM::Api::onFortifyFactorRequest);
connect(m_jsonApi, &Json::Api::relayStatesRequest, m_vwmApi, &VWM::Api::onRelayStatesRequest);
connect(m_jsonApi, &Json::Api::centralEffectSimulationHit, m_vwmApi, &VWM::Api::onHitCes);
connect(m_jsonApi, &Json::Api::centralEffectSimulationHit3D,m_vwmApi, &VWM::Api::onHitCes3D_Evaluation);
connect(m_jsonApi, &Json::Api::bsmTriggerFlashlightRequest, m_bsmApi, &BSM::Api::triggerFlashlight);
connect(m_jsonApi, &Json::Api::getBsmConfiguration, m_bsmApi, &BSM::Api::getBsmConfiguration);
connect(m_jsonApi, &Json::Api::getBsmBitTimeout, m_bsmApi, &BSM::Api::getBsmBitTimeout);
connect(m_jsonApi, &Json::Api::getBsmTechnicalStatus, m_bsmApi, &BSM::Api::getBsmTechnicalStatus);
// for debug purposes
connect(m_jsonApi, &Json::Api::simulateBSMHit, m_vwmApi, &VWM::Api::onHitOptical);
connect(m_jsonApi, &Json::Api::setEffectStatesRequest, m_vwmApi, &VWM::Api::onSetEffectStatesRequest);
connect(m_bsmApi, &BSM::Api::bsmStateChanged, m_jsonApi, &Json::Api::onBsmState);
connect(m_vwmApi, &VWM::Api::hitResult, m_jsonApi, &Json::Api::onHitResult);
connect(m_jsonApi, &Json::Api::webSocketConnected, this, &MainHandler::webSocketSendInitialData);
connect(m_jsonApi, &Json::Api::setEffectStatesRequest, this, &MainHandler::onSetEffectStatesRequest);
connect(m_jsonApi, &Json::Api::switchRelayRequest, this, &MainHandler::onSwitchRelayRequest);
connect(m_vwmApi, &VWM::Api::newOverrides, this, &MainHandler::onSetEffectStatesRequest);
m_vwmApi->sendOverrides();
onHitResult(m_vwmApi->lastHitResult(), m_vwmApi->contaminationStates(), false);
// Set initial Overrides:
//setInitialOverrides();
return true;
}
void MainHandler::setInitialOverrides(const QString &hostname)
{
DEBUG_LOG(m_logger) << "setInitialOverrides m_handelEffectsVec.size()=" << m_handelEffectsVec.size();
// Set initial Overrides:
for ( int i = 0; i < m_handelEffectsVec.size(); i++)
{
QString hostnameLocal = m_handelEffectsVec.at(i)->hostname();
const QVector<BcuEffectState> effectStates = m_handelEffectsVec.at(i)->getOverrides();
DEBUG_LOG(m_logger) << "setInitialOverrides host=" << hostnameLocal
<< " effectStates.size=" << effectStates.size();
for (int j = 0; j < effectStates.size(); j++)
DEBUG_LOG(m_logger) << "setInitialOverrides j=" << j
<< " id=" << effectStates[j].id
<< " type=" << effectStates[j].type
<< " override=" << effectStates[j].effectOverride;
NOTICE_LOG(m_logger) << "'" << hostname << "'"
<< " '" << hostnameLocal << "'";
if ( hostname.toLower() == hostnameLocal.toLower())
{
onSetEffectStatesRequest(hostnameLocal, effectStates);
const QString segment = hostname ;
const qint64 stateTime = QDateTime::currentMSecsSinceEpoch();;
const qint64 offlineTime = QDateTime::currentMSecsSinceEpoch();
m_jsonApi->sendEffectOverrides(segment, stateTime, offlineTime, effectStates, nullptr);
}
}
}
void MainHandler::onHitResult(const HitResult &result, const QMap<int, ContaminationState> &contaminationStates, bool playSound)
{
Q_UNUSED(contaminationStates)
const VWM::Charge charge = m_vwmApi->chargeFromChargeTypeId(result.chargeTypeId);
DEBUG_LOG(m_logger) << "onHitResult chargeTypeId=" << result.chargeTypeId
<< " result.effectSoundId=" << result.effectSoundId
<< " damagePercentNew=" << result.damagePercentNew
<< " destructiveFactor=" << charge.destructiveFactor;
if (Settings::laserRangeCode() == result.chargeTypeId)
return;
if (playSound)
{
for (HandelEffects *he : qAsConst(m_handelEffectsVec))
{
DEBUG_LOG(m_logger) << "playHitSound @EGCU " << he->hostname() << ", SoundId: " << result.effectSoundId;
he->playHitSound(result.effectSoundId);
}
}
DEBUG_LOG(m_logger) << "HitResult: " << result;
if (result.sensorId != 0 && result.originatorId != 0 && m_bsmFlash != BEO_Off && charge.destructiveFactor > 1 )
{
DEBUG_LOG(m_logger) << "BSM Flash";
m_bsmApi->triggerFlashlight(result.sensorId);
m_bsmApi->triggerFlashlightPulse(result.sensorId, // ??? Woher kommt der Hostname? Es blitzt ja bei trigger Flashlight Patric: Wenn Hosname Leer ist ruft er die Funktion getSocketForBsm auf
QString(),
Settings::numberOfFlashes(),
Settings::pauseDuration(),
Settings::choppedConfiguration(),
Settings::flashDuration());
}
else
DEBUG_LOG(m_logger) << "Kein BSM Flash";
// only once on state change (to not trigger it more than once)
//if (result.damagePercentOld < Settings::fireThreshold() &&
// result.damagePercentNew > Settings::fireThreshold())
// Each Segment
QVector<int> segmentDamage = getSegmentDamage(result.rooms, result.damagePercentNew);
for (int i = 0; i < m_egcuConfig.egcus.size(); i++)
{
DEBUG_LOG(m_logger) << "segmentDamage.size=" << segmentDamage.size();
if ( i < segmentDamage.size() )
{
DEBUG_LOG(m_logger) << "segmentDamage[" << i <<"]=" << segmentDamage[i];
m_handelEffectsVec[i]->startEffects(segmentDamage[i]);
}
else
DEBUG_LOG(m_logger) << "No segment Damage for egcu:" << m_egcuConfig.egcus[i].hostname;
}
m_handelEffectsBsm->startEffects(result.damagePercentNew);
}
void MainHandler::onUnknownDirectHit(int sensorId)
{
// unknown dus code - double flash
m_bsmApi->triggerFlashlight(sensorId);
m_bsmApi->triggerFlashlight(sensorId);
}
void MainHandler::onSetEffectStatesRequest(const QString &hostname, const QVector<BcuEffectState> &effectStates)
{
DEBUG_LOG(m_logger) << "1 BSM flash hostname='" << hostname
<< "' isEmpty:"<< hostname.isEmpty()
<<" isNull:" << hostname.isNull();
m_effectStates.insert(hostname, effectStates);
if (hostname.isEmpty())
{
m_bsmFlash = BEO_Auto;
DEBUG_LOG(m_logger) << "2 BSM flash =" << m_bsmFlash;
m_handelEffectsBsm->setOverrides(effectStates);
for ( int i = 0; i < effectStates.size(); i++)
{
DEBUG_LOG(m_logger) << "3 BSM flash =" << m_bsmFlash;
if ( effectStates.at(i).type == BET_BsmFlash)
{
m_bsmFlash = effectStates.at(i).effectOverride;
DEBUG_LOG(m_logger) << "4 BSM flash =" << m_bsmFlash;
break;
}
}
return;
}
for (HandelEffects* hes : qAsConst(m_handelEffectsVec))
{
if (hes->hostname() != hostname)
continue;
hes->setOverrides(effectStates);
}
}
void MainHandler::onSwitchRelayRequest(const QString &hostname, const SwitchRelayValues &switchRelayValues)
{
for ( int i = 0; i < m_handelEffectsVec.size(); i++)
{
if (m_handelEffectsVec[i]->hostname() == hostname )
{
DEBUG_LOG(m_logger) << "switchRelay "
<< " id=" << switchRelayValues.id
<< " bcuRelayState=" << switchRelayValues.bcuRelayState;
m_handelEffectsVec[i]->switchRelay(switchRelayValues);
}
}
}
void MainHandler::webSocketSendInitialData(QWebSocket *ws)
{
m_jsonApi->sendBsmState(m_bsmApi->bsmStates(), ws);
m_jsonApi->sendHitResult(m_vwmApi->lastHitResult(), m_vwmApi->contaminationStates(), ws);
}
QVector<int> MainHandler::getAffectedRoomIds(const QVector<HitRoom> &allHitRooms) const
{
QVector<int> ret;
for (const HitRoom &hr : allHitRooms)
{
if (hr.remainingEffectPercent == 0)
continue;
ret += hr.roomId;
}
return ret;
}
int MainHandler::getHitRoomId(const QVector<HitRoom> &allHitRooms) const
{
for (const HitRoom &hr : allHitRooms)
{
if (hr.directHit)
return hr.roomId;
}
return 0;
}
QVector<int> MainHandler::getSegmentDamage(const QVector<HitRoom> &allHitRooms, const int damagePercentNew) const
{
QVector<int> result;
if (m_egcuConfig.egcus.size() == 0)
return result;
result.reserve(m_egcuConfig.egcus.size());
// every egcu is responsible for one segment
for (const Egcu &egcu : qAsConst(m_egcuConfig.egcus))
{
int damagePercentSegment = 0;
for (const HitRoom &hr : allHitRooms)
{
if (egcu.roomIds.contains(hr.roomId))
damagePercentSegment += hr.damagePercent;
}
// Can only occur when roomIds.size() > 0
if (damagePercentNew == 0)
result.append(0);
else if (damagePercentNew == 100)
result.append(100);
else
{
int averageDamage = 0;
if (egcu.roomIds.size() > 0 )
averageDamage = damagePercentSegment / egcu.roomIds.size();
result.append(averageDamage);
INFO_LOG(m_logger) << "getSegmentDamage[" << egcu.hostname << "]=" << averageDamage;
}
}
return result;
}
void MainHandler::flashBuildingDestructionIndicator(int egcu)
{
// Todo: What's this?
ERROR_LOG(m_logger) << "TODO flashBuildingDestructionIndicator egcu=" << egcu;
// Building Destruction Indicator
//RelayHardwareConfig hwCfg; // TODO Config TBD
//hwCfg.cntRepeat = 0;
//hwCfg.damage = 100;
//hwCfg.durationDelay = 0;
//hwCfg.durationPulses = 500;
//hwCfg.relayNumber = 0;
//m_egcuApi->startHardware(hwCfg, egcu);
}
void MainHandler::cleanup()
{
delete m_bsmApi;
//delete m_egcuApi;
delete m_jsonApi;
delete m_vwmApi;
}
} // BuildingControlUnit