added session finished event

This commit is contained in:
Boernsman 2021-01-13 14:32:41 +01:00
parent 0803221e68
commit 5b38c6c9bc
5 changed files with 209 additions and 71 deletions

View File

@ -113,9 +113,9 @@ void IntegrationPluginKeba::setupThing(ThingSetupInfo *info)
KeContact *keba = new KeContact(address, this); KeContact *keba = new KeContact(address, this);
connect(keba, &KeContact::reachableChanged, this, &IntegrationPluginKeba::onConnectionChanged); connect(keba, &KeContact::reachableChanged, this, &IntegrationPluginKeba::onConnectionChanged);
connect(keba, &KeContact::commandExecuted, this, &IntegrationPluginKeba::onCommandExecuted); connect(keba, &KeContact::commandExecuted, this, &IntegrationPluginKeba::onCommandExecuted);
connect(keba, &KeContact::reportOneReceived, this, &IntegrationPluginKeba::onReportOneReceived);
connect(keba, &KeContact::reportTwoReceived, this, &IntegrationPluginKeba::onReportTwoReceived); connect(keba, &KeContact::reportTwoReceived, this, &IntegrationPluginKeba::onReportTwoReceived);
connect(keba, &KeContact::reportThreeReceived, this, &IntegrationPluginKeba::onReportThreeReceived); connect(keba, &KeContact::reportThreeReceived, this, &IntegrationPluginKeba::onReportThreeReceived);
connect(keba, &KeContact::report1XXReceived, this, &IntegrationPluginKeba::onReport1XXReceived);
connect(keba, &KeContact::broadcastReceived, this, &IntegrationPluginKeba::onBroadcastReceived); connect(keba, &KeContact::broadcastReceived, this, &IntegrationPluginKeba::onBroadcastReceived);
if (!keba->init()){ if (!keba->init()){
qCWarning(dcKebaKeContact()) << "Cannot bind to port" << 7090; qCWarning(dcKebaKeContact()) << "Cannot bind to port" << 7090;
@ -316,12 +316,7 @@ void IntegrationPluginKeba::onReportTwoReceived(const KeContact::ReportTwo &repo
if (!thing) if (!thing)
return; return;
thing->setStateValue() qCDebug(dcKebaKeContact()) << "Report 2 received for" << thing->name() << "Serial number:" << thing->stateValue(wallboxSerialnumberStateTypeId).toString();
thing->setStateValue(wallboxPowerStateTypeId, reportTwo.enableUser);
thing->setStateValue(wallboxError1StateTypeId, reportTwo.error1);
thing->setStateValue(wallboxError2StateTypeId, reportTwo.error2);
qCDebug(dcKebaKeContact()) << "Report 2 recieved for" << thing->name();
qCDebug(dcKebaKeContact()) << " - State:" << reportTwo.state; qCDebug(dcKebaKeContact()) << " - State:" << reportTwo.state;
qCDebug(dcKebaKeContact()) << " - Error 1:" << reportTwo.error1; qCDebug(dcKebaKeContact()) << " - Error 1:" << reportTwo.error1;
qCDebug(dcKebaKeContact()) << " - Error 2:" << reportTwo.error2; qCDebug(dcKebaKeContact()) << " - Error 2:" << reportTwo.error2;
@ -341,14 +336,24 @@ void IntegrationPluginKeba::onReportTwoReceived(const KeContact::ReportTwo &repo
qCDebug(dcKebaKeContact()) << " - Serial number:" << reportTwo.serialNumber; qCDebug(dcKebaKeContact()) << " - Serial number:" << reportTwo.serialNumber;
qCDebug(dcKebaKeContact()) << " - Uptime:" << reportTwo.seconds; qCDebug(dcKebaKeContact()) << " - Uptime:" << reportTwo.seconds;
if (reportTwo.serialNumber == thing->stateValue(wallboxSerialnumberStateTypeId).toString()) {
setDeviceState(thing, reportTwo.state);
setDevicePlugState(thing, reportTwo.plugState);
thing->setStateValue(wallboxPowerStateTypeId, reportTwo.enableUser);
thing->setStateValue(wallboxError1StateTypeId, reportTwo.error1);
thing->setStateValue(wallboxError2StateTypeId, reportTwo.error2);
//thing->setStateValue(wallboxMaxChargingCurrentAmpereStateTypeId, reportTwo.maxCurrent); //thing->setStateValue(wallboxMaxChargingCurrentAmpereStateTypeId, reportTwo.maxCurrent);
thing->setStateValue(wallboxMaxChargingCurrentPercentStateTypeId, reportTwo.maxCurrentPercentage); thing->setStateValue(wallboxMaxChargingCurrentPercentStateTypeId, reportTwo.maxCurrentPercentage);
//thing->setStateValue(wallboxCurrentHardwareLimitationStateTypeId, reportTwo.currentHardwareLimitation); //thing->setStateValue(wallboxCurrentHardwareLimitationStateTypeId, reportTwo.currentHardwareLimitation);
thing->setStateValue(wallboxOutputX2StateTypeId, reportTwo.output);
thing->setStateValue(wallboxInputStateTypeId, reportTwo.input);
setDeviceState(thing, reportTwo.state); thing->setStateValue(wallboxUptimeStateTypeId, reportTwo.seconds);
setDevicePlugState(thing, reportTwo.plugState); } else {
qCWarning(dcKebaKeContact()) << "Received report but the serial number didn't match";
}
} }
void IntegrationPluginKeba::onReportThreeReceived(const KeContact::ReportThree &reportThree) void IntegrationPluginKeba::onReportThreeReceived(const KeContact::ReportThree &reportThree)
@ -358,16 +363,77 @@ void IntegrationPluginKeba::onReportThreeReceived(const KeContact::ReportThree &
if (!thing) if (!thing)
return; return;
thing->setStateValue(wallboxCurrentPhase1EventTypeId, reportThree.CurrentPhase1); qCDebug(dcKebaKeContact()) << "Report 3 received for" << thing->name() << "Serial number:" << thing->stateValue(wallboxSerialnumberStateTypeId).toString();
thing->setStateValue(wallboxCurrentPhase2EventTypeId, reportThree.CurrentPhase2); qCDebug(dcKebaKeContact()) << " - Current phase 1:" << reportThree.currentPhase1 << "[mA]";
thing->setStateValue(wallboxCurrentPhase3EventTypeId, reportThree.CurrentPhase3); qCDebug(dcKebaKeContact()) << " - Current phase 2:" << reportThree.currentPhase2 << "[mA]";
thing->setStateValue(wallboxVoltagePhase1EventTypeId, reportThree.VoltagePhase1); qCDebug(dcKebaKeContact()) << " - Current phase 3:" << reportThree.currentPhase3 << "[mA]";
thing->setStateValue(wallboxVoltagePhase2EventTypeId, reportThree.VoltagePhase2); qCDebug(dcKebaKeContact()) << " - Voltage phase 1:" << reportThree.voltagePhase1 << "[V]";
thing->setStateValue(wallboxVoltagePhase3EventTypeId, reportThree.VoltagePhase3); qCDebug(dcKebaKeContact()) << " - Voltage phase 2:" << reportThree.voltagePhase2 << "[V]";
thing->setStateValue(wallboxPowerConsumptionStateTypeId, reportThree.Power); qCDebug(dcKebaKeContact()) << " - Voltage phase 3:" << reportThree.voltagePhase3 << "[V]";
thing->setStateValue(wallboxSessionEnergyStateTypeId, reportThree.EnergySession); //TODO check state name qCDebug(dcKebaKeContact()) << " - Power consumption:" << reportThree.power << "[W]";
thing->setStateValue(wallboxPowerFactorStateTypeId, reportThree.PowerFactor); qCDebug(dcKebaKeContact()) << " - Energy session" << reportThree.energySession << "[Wh]";
thing->setStateValue(wallboxTotalEnergyConsumedStateTypeId, reportThree.EnergyTotal); qCDebug(dcKebaKeContact()) << " - Energy total" << reportThree.energyTotal << "[Wh]";
qCDebug(dcKebaKeContact()) << " - Serial number" << reportThree.serialNumber;
qCDebug(dcKebaKeContact()) << " - Uptime" << reportThree.seconds;
if (reportThree.serialNumber == thing->stateValue(wallboxSerialnumberStateTypeId).toString()) {
thing->setStateValue(wallboxCurrentPhase1EventTypeId, reportThree.currentPhase1);
thing->setStateValue(wallboxCurrentPhase2EventTypeId, reportThree.currentPhase2);
thing->setStateValue(wallboxCurrentPhase3EventTypeId, reportThree.currentPhase3);
thing->setStateValue(wallboxVoltagePhase1EventTypeId, reportThree.voltagePhase1);
thing->setStateValue(wallboxVoltagePhase2EventTypeId, reportThree.voltagePhase2);
thing->setStateValue(wallboxVoltagePhase3EventTypeId, reportThree.voltagePhase3);
thing->setStateValue(wallboxPowerConsumptionStateTypeId, reportThree.power);
thing->setStateValue(wallboxSessionEnergyStateTypeId, reportThree.energySession);
thing->setStateValue(wallboxPowerFactorStateTypeId, reportThree.powerFactor);
thing->setStateValue(wallboxTotalEnergyConsumedStateTypeId, reportThree.energyTotal);
} else {
qCWarning(dcKebaKeContact()) << "Received report but the serial number didn't match";
}
}
void IntegrationPluginKeba::onReport1XXReceived(int reportNumber, const KeContact::Report1XX &report)
{
KeContact *keba = static_cast<KeContact *>(sender());
Thing *thing = myThings().findById(m_kebaDevices.key(keba));
if (!thing)
return;
qCDebug(dcKebaKeContact()) << "Report" << reportNumber << "received for" << thing->name() << "Serial number:" << thing->stateValue(wallboxSerialnumberStateTypeId).toString();
qCDebug(dcKebaKeContact()) << " - Session Id" << report.sessionId;
qCDebug(dcKebaKeContact()) << " - Curr HW" << report.currHW;
qCDebug(dcKebaKeContact()) << " - Energy start" << report.startEnergy;
qCDebug(dcKebaKeContact()) << " - Energy present" << report.ePres;
qCDebug(dcKebaKeContact()) << " - Start time" << report.startTime;
qCDebug(dcKebaKeContact()) << " - End time" << report.endTime;
qCDebug(dcKebaKeContact()) << " - Stop reason" << report.stopReason;
qCDebug(dcKebaKeContact()) << " - RFID Tag" << report.rfidTag;
qCDebug(dcKebaKeContact()) << " - RFID Class" << report.rfidClass;
qCDebug(dcKebaKeContact()) << " - Serial number" << report.serialNumber;
qCDebug(dcKebaKeContact()) << " - Uptime" << report.seconds;
// Report 101 is the lastest finished session
if (reportNumber == 101) {
if (report.serialNumber == thing->stateValue(wallboxSerialnumberStateTypeId).toString()) {
if (!m_lastSessionId.contains(thing->id())) {
m_lastSessionId.insert(thing->id(), report.sessionId);
} else {
if (m_lastSessionId.value(thing->id()) != report.sessionId) {
qCDebug(dcKebaKeContact()) << "New session id receivd";
Event event;
event.setThingId(thing->id());
ParamList params;
//params << Param(wallboxSessio);
event.setParams(params);
emitEvent(event);
}
}
} else {
qCWarning(dcKebaKeContact()) << "Received report but the serial number didn't match";
}
} else {
qCWarning(dcKebaKeContact()) << "Received unhandled report" << reportNumber;
}
} }
void IntegrationPluginKeba::onBroadcastReceived(KeContact::BroadcastType type, const QVariant &content) void IntegrationPluginKeba::onBroadcastReceived(KeContact::BroadcastType type, const QVariant &content)

View File

@ -67,6 +67,8 @@ private:
Discovery *m_discovery = nullptr; Discovery *m_discovery = nullptr;
QHash<ThingId, KeContact *> m_kebaDevices; QHash<ThingId, KeContact *> m_kebaDevices;
QHash<ThingId, int> m_lastSessionId;
QHash<KeContact *, ThingSetupInfo *> m_asyncSetup; QHash<KeContact *, ThingSetupInfo *> m_asyncSetup;
QHash<QUuid, ThingActionInfo *> m_asyncActions; QHash<QUuid, ThingActionInfo *> m_asyncActions;
QHash<ThingId, QDateTime> m_chargingSessionStartTime; QHash<ThingId, QDateTime> m_chargingSessionStartTime;
@ -77,9 +79,9 @@ private:
private slots: private slots:
void onConnectionChanged(bool status); void onConnectionChanged(bool status);
void onCommandExecuted(QUuid requestId, bool success); void onCommandExecuted(QUuid requestId, bool success);
void onReportOneReceived(const KeContact::ReportOne &reportOne);
void onReportTwoReceived(const KeContact::ReportTwo &reportTwo); void onReportTwoReceived(const KeContact::ReportTwo &reportTwo);
void onReportThreeReceived(const KeContact::ReportThree &reportThree); void onReportThreeReceived(const KeContact::ReportThree &reportThree);
void onReport1XXReceived(int reportNumber, const KeContact::Report1XX &report);
void onBroadcastReceived(KeContact::BroadcastType type, const QVariant &content); void onBroadcastReceived(KeContact::BroadcastType type, const QVariant &content);
}; };

View File

@ -298,6 +298,38 @@
} }
] ]
} }
],
"eventTypes": [
{
"id": "dac02c37-f051-481a-ae99-1de0885ef37a",
"name": "chargingSessionFinished",
"displayName": "Charging session finished",
"paramTypes": [
{
"id": "33446eae-f2cc-4cf2-af29-b3a45e4b91c0",
"name": "id",
"displayName": "ID",
"type": "int",
"defaultValue": "0"
},
{
"id": "60494d6f-853b-42b8-894e-108a52ed6feb",
"name": "duration",
"displayName": "Duration",
"type": "int",
"unit": "Seconds",
"defaultValue": 0
},
{
"id": "c8de58b6-b671-4fee-b552-d2c14a37a769",
"name": "energy",
"displayName": "Energy",
"type": "double",
"defaultValue": 0.00,
"unit": "KiloWattHour"
}
]
}
] ]
} }
] ]

View File

@ -92,7 +92,7 @@ QUuid KeContact::stop(const QByteArray &rfidToken)
return requestId; return requestId;
} }
void KeContact::setAddress(QHostAddress address) void KeContact::setAddress(const QHostAddress &address)
{ {
m_address = address; m_address = address;
} }
@ -339,19 +339,29 @@ void KeContact::readPendingDatagrams()
QVariantMap data = jsonDoc.toVariant().toMap(); QVariantMap data = jsonDoc.toVariant().toMap();
if(data.contains("ID")) { if(data.contains("ID")) {
int id = data.value("ID").toInt();
if (data.value("ID").toString() == "1") { if (id == 1) {
ReportOne reportOne; ReportOne reportOne;
qCDebug(dcKebaKeContact()) << "Report 1 received"; qCDebug(dcKebaKeContact()) << "Report 1 received";
reportOne.product = data.value("Product").toString(); reportOne.product = data.value("Product").toString();
reportOne.firmware = data.value("Firmware").toString(); reportOne.firmware = data.value("Firmware").toString();
reportOne.serialNumber = data.value("Serial").toString();; reportOne.serialNumber = data.value("Serial").toString();
if (data.contains("COM-module")) {
reportOne.comModule = (data.value("COM-module").toInt() == 1);
} else {
reportOne.comModule = false;
}
if (data.contains("Sec")) {
reportOne.comModule = data.value("Sec").toInt();
} else {
reportOne.comModule = 0;
}
emit reportOneReceived(reportOne); emit reportOneReceived(reportOne);
} else if(data.value("ID").toString() == "2"){ } else if (id == 2) {
ReportTwo reportTwo; ReportTwo reportTwo;
qCDebug(dcKebaKeContact()) << "Report 2 reveiced"; qCDebug(dcKebaKeContact()) << "Report 2 received";
int state = data.value("State").toInt(); int state = data.value("State").toInt();
reportTwo.state = State(state); reportTwo.state = State(state);
reportTwo.error1 = data.value("Error1").toInt(); reportTwo.error1 = data.value("Error1").toInt();
@ -371,22 +381,33 @@ void KeContact::readPendingDatagrams()
reportTwo.seconds = data.value("Sec").toInt(); reportTwo.seconds = data.value("Sec").toInt();
emit reportTwoReceived(reportTwo); emit reportTwoReceived(reportTwo);
} else if(data.value("ID").toString() == "3"){ } else if (id == 3) {
ReportThree reportThree; ReportThree reportThree;
qCDebug(dcKebaKeContact()) << "Report 3 reveiced"; qCDebug(dcKebaKeContact()) << "Report 3 reveiced";
reportThree.CurrentPhase1 = data.value("I1").toInt(); reportThree.currentPhase1 = data.value("I1").toInt()/1000.00;
reportThree.CurrentPhase2 = data.value("I2").toInt(); reportThree.currentPhase2 = data.value("I2").toInt()/1000.00;
reportThree.CurrentPhase3 = data.value("I3").toInt(); reportThree.currentPhase3 = data.value("I3").toInt()/1000.00;
reportThree.VoltagePhase1 = data.value("U1").toInt(); reportThree.voltagePhase1 = data.value("U1").toInt();
reportThree.VoltagePhase2 = data.value("U2").toInt(); reportThree.voltagePhase2 = data.value("U2").toInt();
reportThree.VoltagePhase3 = data.value("U3").toInt(); reportThree.voltagePhase3 = data.value("U3").toInt();
reportThree.Power = data.value("P").toInt(); reportThree.power = data.value("P").toInt()/1000.00;
reportThree.PowerFactor = data.value("PF").toInt()/10; reportThree.powerFactor = data.value("PF").toInt()/10.00;
reportThree.EnergySession = data.value("E pres").toInt()/10000.00; reportThree.energySession = data.value("E pres").toInt()/10000.00;
reportThree.EnergyTotal = data.value("E total").toInt()/10000.00; reportThree.energyTotal = data.value("E total").toInt()/10000.00;
reportThree.SerialNumber = data.value("Serial").toString(); reportThree.serialNumber = data.value("Serial").toString();
reportThree.seconds = data.value("Sec").toInt();
emit reportThreeReceived(reportThree); emit reportThreeReceived(reportThree);
} else if (id >= 100) {
Report1XX report;
report.sessionId = data.value("Session ID").toInt();
report.currHW = data.value("Curr HW").toInt();
//report. = data.value("Curr HW").toInt(); TODO
report.currHW = data.value("Curr HW").toInt();
report.currHW = data.value("Curr HW").toInt();
report.currHW = data.value("Curr HW").toInt();
report.currHW = data.value("Curr HW").toInt();
emit report1XXReceived(id, report);
} }
} else { } else {
if (data.contains("State")) { if (data.contains("State")) {

View File

@ -113,17 +113,32 @@ public:
}; };
struct ReportThree { struct ReportThree {
int VoltagePhase1; //voltage in V int voltagePhase1; //voltage in V
int VoltagePhase2; //voltage in V int voltagePhase2; //voltage in V
int VoltagePhase3; //voltage in V int voltagePhase3; //voltage in V
int CurrentPhase1; //current in mA double currentPhase1; //current in A
int CurrentPhase2; //current in mA double currentPhase2; //current in A
int CurrentPhase3; //current in mA double currentPhase3; //current in A
int Power; //Current power in mW (Real Power). double power; //Current power in W (Real Power).
int PowerFactor; //Power factor in 0,1% (cosphi) double powerFactor; //Power factor in 0,1% (cosphi)
int EnergySession; //Power consumption of the current loading session in 0,1Wh; Reset with new loading session (state = 2). double energySession; //Power consumption of the current loading session in 0,1Wh; Reset with new loading session (state = 2).
int EnergyTotal; //Total power consumption (persistent) without current loading session 0,1Wh; Is summed up after each completed charging session (state = 0). double energyTotal; //Total power consumption (persistent) without current loading session 0,1Wh; Is summed up after each completed charging session (state = 0).
QString SerialNumber; QString serialNumber;
int seconds; //Current system clock since restart of the charging station.
};
struct Report1XX {
int sessionId; // running session counter; not resettable"
int currHW; // maximum charging current of the cable and the charging station setting (equal to report 2)"E
double startEnergy; // total energy value at the beginning of the session"
double ePres; // delivered energy until now (equal to E pres in report 3)"
int startTime; // system time when the session was started (seconds from reboot; NTP implementation is still under progress)"
int endTime; // system time when the session has ended"
int stopReason; // reason for stopping the session (1 = vehicle unplug; 10 = Rfid token)"
QByteArray rfidTag; // RFID Token ID if session started with rfid; hexadecimal; first character is the lowest nibble"
QByteArray rfidClass; // RFID classifier shows the defined color code if the used card is a BMW card (for example “010104” means the white card)"
QString serialNumber; // serial number of the charging station"
int seconds; // current time when the report was generated
}; };
QHostAddress address(); QHostAddress address();
@ -145,6 +160,7 @@ public:
void getReport1(); // Command “report” void getReport1(); // Command “report”
void getReport2(); void getReport2();
void getReport3(); void getReport3();
void getReport1XX(int reportNumber = 100);
// Command “report 1xx” // Command “report 1xx”
@ -176,6 +192,7 @@ signals:
void reportOneReceived(const ReportOne &reportOne); void reportOneReceived(const ReportOne &reportOne);
void reportTwoReceived(const ReportTwo &reportTwo); void reportTwoReceived(const ReportTwo &reportTwo);
void reportThreeReceived(const ReportThree &reportThree); void reportThreeReceived(const ReportThree &reportThree);
void report1XXReceived(int reportNumber, const Report1XX &report);
void broadcastReceived(BroadcastType type, const QVariant &content); void broadcastReceived(BroadcastType type, const QVariant &content);
private slots: private slots: