367 lines
13 KiB
C++
Executable File
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
|