From 276532a68910944fb1ef63dcf149c0f0b4f2af9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Tue, 13 Aug 2024 15:52:00 +0200 Subject: [PATCH 1/5] PCE: Add serial number as paramter --- pcelectric/integrationpluginpcelectric.cpp | 1 + pcelectric/integrationpluginpcelectric.json | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/pcelectric/integrationpluginpcelectric.cpp b/pcelectric/integrationpluginpcelectric.cpp index 421379f..b20d634 100644 --- a/pcelectric/integrationpluginpcelectric.cpp +++ b/pcelectric/integrationpluginpcelectric.cpp @@ -70,6 +70,7 @@ void IntegrationPluginPcElectric::discoverThings(ThingDiscoveryInfo *info) ParamList params; params << Param(ev11ThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress()); + params << Param(ev11ThingSerialNumberParamTypeId, result.serialNumber); // Note: if we discover also the port and modbusaddress, we must fill them in from the discovery here, for now everywhere the defaults... descriptor.setParams(params); info->addThingDescriptor(descriptor); diff --git a/pcelectric/integrationpluginpcelectric.json b/pcelectric/integrationpluginpcelectric.json index eed7855..678a2dc 100644 --- a/pcelectric/integrationpluginpcelectric.json +++ b/pcelectric/integrationpluginpcelectric.json @@ -23,6 +23,13 @@ "type": "QString", "inputType": "MacAddress", "defaultValue": "" + }, + { + "id": "db834ca7-934a-473b-8bd8-c641ff0ea879", + "name":"serialNumber", + "displayName": "Serial number", + "type": "QString", + "defaultValue": "" } ], "settingsTypes": [ From 3f3b9d0e018a2051dbe0713d4ddf11b4e5e87113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Tue, 13 Aug 2024 15:55:47 +0200 Subject: [PATCH 2/5] PCE: Update translations --- ...ff833-a8e0-45cc-a1ef-65f05871f272-de_DE.ts | 108 ++++++++++++------ ...ff833-a8e0-45cc-a1ef-65f05871f272-en_US.ts | 106 ++++++++++++----- 2 files changed, 151 insertions(+), 63 deletions(-) diff --git a/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-de_DE.ts b/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-de_DE.ts index 82ee749..d764620 100644 --- a/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-de_DE.ts +++ b/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-de_DE.ts @@ -4,28 +4,45 @@ IntegrationPluginPcElectric - + The network device discovery is not available. Die Netzwerk Suche ist nicht verfügbar. + + + The MAC address is not known. Please reconfigure the thing. + Die MAC-Adresse ist nicht bekannt. Bitte richte das Gerät erneut ein. + PcElectric - + + 1 + The name of a possible value of StateType {d91f7d96-2599-400a-91da-d164477098b7} of ThingClass ev11 + 1 + + + + 3 + The name of a possible value of StateType {d91f7d96-2599-400a-91da-d164477098b7} of ThingClass ev11 + 3 + + + Active phases The name of the StateType ({bca88c23-e940-40c1-afca-eb511fd17aab}) of ThingClass ev11 Aktive Phasen - + Charging The name of the StateType ({b7972cd7-471a-46bd-ab99-f49997f12309}) of ThingClass ev11 Lädt - - + + Charging enabled The name of the ParamType (ThingClass: ev11, ActionType: power, ID: {c12a7a27-fa56-450c-a1ec-717c868554f2}) ---------- @@ -33,44 +50,65 @@ The name of the StateType ({c12a7a27-fa56-450c-a1ec-717c868554f2}) of ThingClass Laden eingeschalten - + Connected The name of the StateType ({ca8d680c-c2f8-456a-a246-9c6cd64e25a7}) of ThingClass ev11 Verbunden - + + + Desired phase count + The name of the ParamType (ThingClass: ev11, ActionType: desiredPhaseCount, ID: {d91f7d96-2599-400a-91da-d164477098b7}) +---------- +The name of the StateType ({d91f7d96-2599-400a-91da-d164477098b7}) of ThingClass ev11 + Gewünschte Phasenanzahl + + + Enable or disable charging The name of the ActionType ({c12a7a27-fa56-450c-a1ec-717c868554f2}) of ThingClass ev11 Laden starten/stoppen - + + Error + The name of the StateType ({2ea1a53f-b2b0-452d-8060-cdb114db05a7}) of ThingClass ev11 + Fehler + + + Firmware version The name of the StateType ({142b4276-e2e9-4149-adc4-89d9d3e31117}) of ThingClass ev11 Firmware Version - - Hardware version - The name of the StateType ({b6e65baf-6dcd-4db1-a3dc-962a4c33d157}) of ThingClass ev11 - Hardware Version + + Onboard temperature + The name of the StateType ({bb092562-377e-458e-bb8a-735af9036652}) of ThingClass ev11 + Temperatur - + + PCE EV11.3 + The name of the ThingClass ({88d96940-a940-4a07-8176-5e6aba7ca832}) + PCE EV11.3 + + + LED brightness The name of the ParamType (ThingClass: ev11, Type: settings, ID: {3a1329a2-84cc-47b9-a6c2-e96fdfd0c454}) LED Helligkeit - + MAC address The name of the ParamType (ThingClass: ev11, Type: thing, ID: {0a3f8d12-9d33-4ae2-b763-9568f32e8da1}) MAC Adresse - - + + Maximum charging current The name of the ParamType (ThingClass: ev11, ActionType: maxChargingCurrent, ID: {b5bbf23c-06db-463b-bb5c-3aea38e18818}) ---------- @@ -78,37 +116,43 @@ The name of the StateType ({b5bbf23c-06db-463b-bb5c-3aea38e18818}) of ThingClass Maximaler Ladestrom - - Maximum offline charging current - The name of the ParamType (ThingClass: ev11, Type: settings, ID: {93654273-c4d3-4389-a81e-c0f065d9cd92}) - Maximaler Ladestrom offline - - - + PC Electric The name of the plugin PcElectric ({aa7ff833-a8e0-45cc-a1ef-65f05871f272}) PC Electric - + PC Electric GmbH The name of the vendor ({b365937b-f1d6-46bf-9ff1-e787373b8aa6}) PC Electric GmbH - - PCE EV11.X - The name of the ThingClass ({88d96940-a940-4a07-8176-5e6aba7ca832}) - PCE EV11.X - - - + Plugged in The name of the StateType ({50164bbd-9802-4cf6-82de-626b74293a1b}) of ThingClass ev11 Angesteckt - + + Serial number + The name of the ParamType (ThingClass: ev11, Type: thing, ID: {db834ca7-934a-473b-8bd8-c641ff0ea879}) + Seriennummer + + + + Session energy + The name of the StateType ({3da3ee80-e9e7-4237-85a6-b4adcb2f483b}) of ThingClass ev11 + Geladene Energie + + + + Set desired phase count + The name of the ActionType ({d91f7d96-2599-400a-91da-d164477098b7}) of ThingClass ev11 + Setze gewünschte Phasenanzahl + + + Set maximum charging current The name of the ActionType ({b5bbf23c-06db-463b-bb5c-3aea38e18818}) of ThingClass ev11 Setze maximalen Ladestrom diff --git a/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-en_US.ts b/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-en_US.ts index a03f87a..f5e36c2 100644 --- a/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-en_US.ts +++ b/pcelectric/translations/aa7ff833-a8e0-45cc-a1ef-65f05871f272-en_US.ts @@ -4,28 +4,45 @@ IntegrationPluginPcElectric - + The network device discovery is not available. + + + The MAC address is not known. Please reconfigure the thing. + + PcElectric - + + 1 + The name of a possible value of StateType {d91f7d96-2599-400a-91da-d164477098b7} of ThingClass ev11 + + + + + 3 + The name of a possible value of StateType {d91f7d96-2599-400a-91da-d164477098b7} of ThingClass ev11 + + + + Active phases The name of the StateType ({bca88c23-e940-40c1-afca-eb511fd17aab}) of ThingClass ev11 - + Charging The name of the StateType ({b7972cd7-471a-46bd-ab99-f49997f12309}) of ThingClass ev11 - - + + Charging enabled The name of the ParamType (ThingClass: ev11, ActionType: power, ID: {c12a7a27-fa56-450c-a1ec-717c868554f2}) ---------- @@ -33,44 +50,65 @@ The name of the StateType ({c12a7a27-fa56-450c-a1ec-717c868554f2}) of ThingClass - + Connected The name of the StateType ({ca8d680c-c2f8-456a-a246-9c6cd64e25a7}) of ThingClass ev11 - + + + Desired phase count + The name of the ParamType (ThingClass: ev11, ActionType: desiredPhaseCount, ID: {d91f7d96-2599-400a-91da-d164477098b7}) +---------- +The name of the StateType ({d91f7d96-2599-400a-91da-d164477098b7}) of ThingClass ev11 + + + + Enable or disable charging The name of the ActionType ({c12a7a27-fa56-450c-a1ec-717c868554f2}) of ThingClass ev11 - + + Error + The name of the StateType ({2ea1a53f-b2b0-452d-8060-cdb114db05a7}) of ThingClass ev11 + + + + Firmware version The name of the StateType ({142b4276-e2e9-4149-adc4-89d9d3e31117}) of ThingClass ev11 - - Hardware version - The name of the StateType ({b6e65baf-6dcd-4db1-a3dc-962a4c33d157}) of ThingClass ev11 + + Onboard temperature + The name of the StateType ({bb092562-377e-458e-bb8a-735af9036652}) of ThingClass ev11 - + + PCE EV11.3 + The name of the ThingClass ({88d96940-a940-4a07-8176-5e6aba7ca832}) + + + + LED brightness The name of the ParamType (ThingClass: ev11, Type: settings, ID: {3a1329a2-84cc-47b9-a6c2-e96fdfd0c454}) - + MAC address The name of the ParamType (ThingClass: ev11, Type: thing, ID: {0a3f8d12-9d33-4ae2-b763-9568f32e8da1}) - - + + Maximum charging current The name of the ParamType (ThingClass: ev11, ActionType: maxChargingCurrent, ID: {b5bbf23c-06db-463b-bb5c-3aea38e18818}) ---------- @@ -78,37 +116,43 @@ The name of the StateType ({b5bbf23c-06db-463b-bb5c-3aea38e18818}) of ThingClass - - Maximum offline charging current - The name of the ParamType (ThingClass: ev11, Type: settings, ID: {93654273-c4d3-4389-a81e-c0f065d9cd92}) - - - - + PC Electric The name of the plugin PcElectric ({aa7ff833-a8e0-45cc-a1ef-65f05871f272}) - + PC Electric GmbH The name of the vendor ({b365937b-f1d6-46bf-9ff1-e787373b8aa6}) - - PCE EV11.X - The name of the ThingClass ({88d96940-a940-4a07-8176-5e6aba7ca832}) - - - - + Plugged in The name of the StateType ({50164bbd-9802-4cf6-82de-626b74293a1b}) of ThingClass ev11 - + + Serial number + The name of the ParamType (ThingClass: ev11, Type: thing, ID: {db834ca7-934a-473b-8bd8-c641ff0ea879}) + + + + + Session energy + The name of the StateType ({3da3ee80-e9e7-4237-85a6-b4adcb2f483b}) of ThingClass ev11 + + + + + Set desired phase count + The name of the ActionType ({d91f7d96-2599-400a-91da-d164477098b7}) of ThingClass ev11 + + + + Set maximum charging current The name of the ActionType ({b5bbf23c-06db-463b-bb5c-3aea38e18818}) of ThingClass ev11 From 816c132c46586f9acdbbe9e40abb51d6ac340029 Mon Sep 17 00:00:00 2001 From: Martin Lukas Date: Mon, 2 Sep 2024 09:31:42 +0200 Subject: [PATCH 3/5] Add read write for digitalInputMode register Signed-off-by: Martin Lukas --- pcelectric/EV11.3-registers.json | 27 +++++++++++ pcelectric/integrationpluginpcelectric.cpp | 34 +++++++++++++- pcelectric/integrationpluginpcelectric.json | 8 ++++ pcelectric/pcewallbox.cpp | 50 +++++++++++++++++++++ pcelectric/pcewallbox.h | 2 + 5 files changed, 120 insertions(+), 1 deletion(-) diff --git a/pcelectric/EV11.3-registers.json b/pcelectric/EV11.3-registers.json index 518103f..d4c566e 100644 --- a/pcelectric/EV11.3-registers.json +++ b/pcelectric/EV11.3-registers.json @@ -103,6 +103,23 @@ "value": 9 } ] + }, + { + "name": "DigitalInputMode", + "values": [ + { + "key": "EnableCharging", + "value": 0 + }, + { + "key": "EnableChargingInverted", + "value": 1 + }, + { + "key": "PwmS0Enabled", + "value": 2 + } + ] } ], "blocks": [ @@ -329,6 +346,16 @@ "description": "LED brightness", "unit": "%", "access": "WO" + }, + { + "id": "digitalInputMode", + "address": 205, + "size": 1, + "type": "uint16", + "registerType": "holdingRegister", + "description": "Digital input mode", + "enum": "DigitalInputMode", + "access": "WR" } ] } diff --git a/pcelectric/integrationpluginpcelectric.cpp b/pcelectric/integrationpluginpcelectric.cpp index b20d634..5e019dc 100644 --- a/pcelectric/integrationpluginpcelectric.cpp +++ b/pcelectric/integrationpluginpcelectric.cpp @@ -329,7 +329,7 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) thing->setStateMaxValue(ev11MaxChargingCurrentStateTypeId, connection->maxChargingCurrentDip() / 1000); thing->setStateValue(ev11PluggedInStateTypeId, connection->chargingState() >= PceWallbox::ChargingStateB1 && - connection->chargingState() < PceWallbox::ChargingStateError); + connection->chargingState() < PceWallbox::ChargingStateError); thing->setStateValue(ev11ChargingStateTypeId, connection->chargingState() == PceWallbox::ChargingStateC2); if (connection->chargingRelayState() != EV11ModbusTcpConnection::ChargingRelayStateNoCharging) { @@ -372,6 +372,18 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) thing->setStateValue(ev11ErrorStateTypeId, "DC Fehlerstromsensor, Fehler."); break; } + + switch (connection->digitalInputMode()) { + case EV11ModbusTcpConnection::DigitalInputModeEnableCharging: + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed"); + break; + case EV11ModbusTcpConnection::DigitalInputModeEnableChargingInverted: + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed inverted"); + break; + case EV11ModbusTcpConnection::DigitalInputModePwmS0Enabled: + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "PWM and S0 signaling"); + break; + } }); connect(thing, &Thing::settingChanged, connection, [thing, connection](const ParamTypeId ¶mTypeId, const QVariant &value){ @@ -387,6 +399,26 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) qCDebug(dcPcElectric()) << "Successfully set led brightness to" << percentage << "%"; }); + } else if (paramTypeId == ev11SettingsDigitalInputModeParamTypeId) { + QString mode = value.toString(); + qCDebug(dcPcElectric()) << "Set Digital input mode" << mode; + EV11ModbusTcpConnection::DigitalInputMode modeValue = EV11ModbusTcpConnection::DigitalInputModeEnableCharging; + + if (mode == "Charging allowed inverted") { + modeValue = EV11ModbusTcpConnection::DigitalInputModeEnableChargingInverted; + } else if (mode == "PWM and S0 signaling") { + modeValue = EV11ModbusTcpConnection::DigitalInputModePwmS0Enabled; + } + + QueuedModbusReply *reply = connection->setDigitalInputMode(modeValue); + connect(reply, &QueuedModbusReply::finished, thing, [reply, modeValue](){ + if (reply->error() != QModbusDevice::NoError) { + qCWarning(dcPcElectric()) << "Could not set digital input mode to" << modeValue << reply->errorString(); + return; + } + + qCDebug(dcPcElectric()) << "Successfully set digital input mode to" << modeValue; + }); } }); diff --git a/pcelectric/integrationpluginpcelectric.json b/pcelectric/integrationpluginpcelectric.json index 678a2dc..e646b41 100644 --- a/pcelectric/integrationpluginpcelectric.json +++ b/pcelectric/integrationpluginpcelectric.json @@ -42,6 +42,14 @@ "maxValue": 100, "unit": "Percentage", "defaultValue": 50 + }, + { + "id": "930e0bf9-0038-436d-9eae-5c0f1cb28825", + "name": "digitalInputMode", + "displayName": "Digital input mode", + "type": "QString", + "defaultValue": "Charging allowed", + "allowedValues": ["Charging allowed", "Charging allowed inverted", "PWM and S0 signaling"] } ], "stateTypes": [ diff --git a/pcelectric/pcewallbox.cpp b/pcelectric/pcewallbox.cpp index dc0b914..25ef7f2 100644 --- a/pcelectric/pcewallbox.cpp +++ b/pcelectric/pcewallbox.cpp @@ -107,6 +107,35 @@ bool PceWallbox::update() sendNextRequest(); }); + enqueueRequest(reply); + + foreach (QueuedModbusReply *r, m_queue) { + if (r->dataUnit().startAddress() == digitalInputModeDataUnit().startAddress()) { + return true; + } + } + + reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, digitalInputModeDataUnit(), this); + connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); + connect(reply, &QueuedModbusReply::finished, this, [this, reply](){ + + if (m_currentReply == reply) + m_currentReply = nullptr; + + if (reply->error() != QModbusDevice::NoError) { + emit updateFinished(); + sendNextRequest(); + return; + } + + const QModbusDataUnit unit = reply->reply()->result(); + const QVector values = unit.values(); + processDigitalInputModeRegisterValues(values); + + emit updateFinished(); + sendNextRequest(); + }); + enqueueRequest(reply); return true; } @@ -151,6 +180,27 @@ QueuedModbusReply *PceWallbox::setLedBrightness(quint16 percentage) return reply; } +QueuedModbusReply *PceWallbox::setDigitalInputMode(DigitalInputMode digitalInputMode) +{ + if (m_aboutToDelete) + return nullptr; + + QueuedModbusReply *reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeWrite, setDigitalInputModeDataUnit(digitalInputMode), this); + + connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); + connect(reply, &QueuedModbusReply::finished, this, [this, reply](){ + if (m_currentReply == reply) + m_currentReply = nullptr; + + sendNextRequest(); + return; + }); + + enqueueRequest(reply, true); + return reply; + +} + void PceWallbox::gracefullDeleteLater() { // Clean up the queue diff --git a/pcelectric/pcewallbox.h b/pcelectric/pcewallbox.h index 9954e59..3a7a150 100644 --- a/pcelectric/pcewallbox.h +++ b/pcelectric/pcewallbox.h @@ -51,6 +51,8 @@ public: QueuedModbusReply *setLedBrightness(quint16 percentage); + QueuedModbusReply *setDigitalInputMode(DigitalInputMode digitalInputMode); + // Note: the modbus implementation of the wallbox gets stuck if a Modbus request has been sent // and we disconnect the socket before the response has arrived. Only a reboot of the wallbox // fixes the broken communication afterwards. This method waits for the current request before closing the From 323019fc05831fdb4ca036d811ba033f7ad9df8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Tue, 1 Oct 2024 15:24:49 +0200 Subject: [PATCH 4/5] PCE: update settings handling, update method and connection behavior --- pcelectric/EV11.3-registers.json | 4 +- pcelectric/integrationpluginpcelectric.cpp | 72 +++++++++----- pcelectric/integrationpluginpcelectric.h | 1 + pcelectric/integrationpluginpcelectric.json | 8 +- pcelectric/pcewallbox.cpp | 100 +++++++++++++------- pcelectric/pcewallbox.h | 4 +- 6 files changed, 126 insertions(+), 63 deletions(-) diff --git a/pcelectric/EV11.3-registers.json b/pcelectric/EV11.3-registers.json index d4c566e..936b0d3 100644 --- a/pcelectric/EV11.3-registers.json +++ b/pcelectric/EV11.3-registers.json @@ -345,7 +345,7 @@ "registerType": "holdingRegister", "description": "LED brightness", "unit": "%", - "access": "WO" + "access": "RW" }, { "id": "digitalInputMode", @@ -355,7 +355,7 @@ "registerType": "holdingRegister", "description": "Digital input mode", "enum": "DigitalInputMode", - "access": "WR" + "access": "RW" } ] } diff --git a/pcelectric/integrationpluginpcelectric.cpp b/pcelectric/integrationpluginpcelectric.cpp index 5e019dc..e86d2a1 100644 --- a/pcelectric/integrationpluginpcelectric.cpp +++ b/pcelectric/integrationpluginpcelectric.cpp @@ -164,6 +164,9 @@ void IntegrationPluginPcElectric::thingRemoved(Thing *thing) connection->deleteLater(); } + if (m_initialUpdate.contains(thing)) + m_initialUpdate.remove(thing); + // Unregister related hardware resources if (m_monitors.contains(thing)) hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing)); @@ -285,6 +288,9 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) PceWallbox *connection = new PceWallbox(monitor->networkDeviceInfo().address(), 502, 1, this); connect(info, &ThingSetupInfo::aborted, connection, &PceWallbox::deleteLater); + if (monitor->networkDeviceInfo().isComplete()) + connection->modbusTcpMaster()->setHostAddress(monitor->networkDeviceInfo().address()); + // Monitor reachability connect(monitor, &NetworkDeviceMonitor::reachableChanged, thing, [=](bool reachable){ if (!thing->setupComplete()) @@ -302,12 +308,13 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) }); // Connection reachability - connect(connection, &PceWallbox::reachableChanged, thing, [thing](bool reachable){ + connect(connection, &PceWallbox::reachableChanged, thing, [this, thing](bool reachable){ qCInfo(dcPcElectric()) << "Reachable changed to" << reachable << "for" << thing; + m_initialUpdate[thing] = true; thing->setStateValue("connected", reachable); }); - connect(connection, &PceWallbox::updateFinished, thing, [thing, connection](){ + connect(connection, &PceWallbox::updateFinished, thing, [this, thing, connection](){ qCDebug(dcPcElectric()) << "Update finished for" << thing; qCDebug(dcPcElectric()) << connection; if (!connection->phaseAutoSwitch()) { @@ -345,51 +352,61 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) thing->setStateValue(ev11ErrorStateTypeId, "Kein Fehler aktiv"); break; case EV11ModbusTcpConnection::ErrorOverheating: - thing->setStateValue(ev11ErrorStateTypeId, "Übertemperatur. Ladevorgang wird automatisch fortgesetzt."); + thing->setStateValue(ev11ErrorStateTypeId, "1: Übertemperatur. Ladevorgang wird automatisch fortgesetzt."); break; case EV11ModbusTcpConnection::ErrorDCFaultCurrent: - thing->setStateValue(ev11ErrorStateTypeId, "DC Fehlerstromsensor ausgelöst."); + thing->setStateValue(ev11ErrorStateTypeId, "2: DC Fehlerstromsensor ausgelöst."); break; case EV11ModbusTcpConnection::ErrorChargingWithVentilation: - thing->setStateValue(ev11ErrorStateTypeId, "Ladeanforderung mit Belüftung."); + thing->setStateValue(ev11ErrorStateTypeId, "3: Ladeanforderung mit Belüftung."); break; case EV11ModbusTcpConnection::ErrorCPErrorEF: - thing->setStateValue(ev11ErrorStateTypeId, "CP Signal, Fehlercode E oder F."); + thing->setStateValue(ev11ErrorStateTypeId, "4: CP Signal, Fehlercode E oder F."); break; case EV11ModbusTcpConnection::ErrorCPErrorBypass: - thing->setStateValue(ev11ErrorStateTypeId, "CP Signal, bypass."); + thing->setStateValue(ev11ErrorStateTypeId, "5: CP Signal, bypass."); break; case EV11ModbusTcpConnection::ErrorCPErrorDiodFault: - thing->setStateValue(ev11ErrorStateTypeId, "CP Signal, Diode defekt."); + thing->setStateValue(ev11ErrorStateTypeId, "6: CP Signal, Diode defekt."); break; case EV11ModbusTcpConnection::ErrorDCFaultCurrentCalibrating: - thing->setStateValue(ev11ErrorStateTypeId, "DC Fehlerstromsensor, Kalibrirung."); + thing->setStateValue(ev11ErrorStateTypeId, "7: DC Fehlerstromsensor, Kalibrirung."); break; case EV11ModbusTcpConnection::ErrorDCFaultCurrentCommunication: - thing->setStateValue(ev11ErrorStateTypeId, "DC Fehlerstromsensor, Kommunikationsfehler."); + thing->setStateValue(ev11ErrorStateTypeId, "8: DC Fehlerstromsensor, Kommunikationsfehler."); break; case EV11ModbusTcpConnection::ErrorDCFaultCurrentError: - thing->setStateValue(ev11ErrorStateTypeId, "DC Fehlerstromsensor, Fehler."); + thing->setStateValue(ev11ErrorStateTypeId, "9: DC Fehlerstromsensor, Fehler."); break; } - switch (connection->digitalInputMode()) { - case EV11ModbusTcpConnection::DigitalInputModeEnableCharging: - thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed"); - break; - case EV11ModbusTcpConnection::DigitalInputModeEnableChargingInverted: - thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed inverted"); - break; - case EV11ModbusTcpConnection::DigitalInputModePwmS0Enabled: - thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "PWM and S0 signaling"); - break; + if (m_initialUpdate.value(thing)) { + + m_initialUpdate[thing] = false; + qCDebug(dcPcElectric()) << "Updating initial settings after connecting..."; + + thing->setSettingValue(ev11SettingsLedBrightnessParamTypeId, connection->ledBrightness()); + + switch (connection->digitalInputMode()) { + case EV11ModbusTcpConnection::DigitalInputModeEnableCharging: + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed"); + break; + case EV11ModbusTcpConnection::DigitalInputModeEnableChargingInverted: + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed inverted"); + break; + case EV11ModbusTcpConnection::DigitalInputModePwmS0Enabled: + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "PWM and S0 signaling"); + break; + } } }); connect(thing, &Thing::settingChanged, connection, [thing, connection](const ParamTypeId ¶mTypeId, const QVariant &value){ + if (paramTypeId == ev11SettingsLedBrightnessParamTypeId) { quint16 percentage = value.toUInt(); - qCDebug(dcPcElectric()) << "Set LED brightness" << percentage << "%"; + + qCDebug(dcPcElectric()) << "Setting LED brightness to" << percentage << "%"; QueuedModbusReply *reply = connection->setLedBrightness(percentage); connect(reply, &QueuedModbusReply::finished, thing, [reply, percentage](){ if (reply->error() != QModbusDevice::NoError) { @@ -401,13 +418,18 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) }); } else if (paramTypeId == ev11SettingsDigitalInputModeParamTypeId) { QString mode = value.toString(); - qCDebug(dcPcElectric()) << "Set Digital input mode" << mode; - EV11ModbusTcpConnection::DigitalInputMode modeValue = EV11ModbusTcpConnection::DigitalInputModeEnableCharging; + qCDebug(dcPcElectric()) << "Setting Digital input mode to" << mode; - if (mode == "Charging allowed inverted") { + EV11ModbusTcpConnection::DigitalInputMode modeValue; + if (mode == "Charging allowed") { + modeValue = EV11ModbusTcpConnection::DigitalInputModeEnableCharging; + } else if (mode == "Charging allowed inverted") { modeValue = EV11ModbusTcpConnection::DigitalInputModeEnableChargingInverted; } else if (mode == "PWM and S0 signaling") { modeValue = EV11ModbusTcpConnection::DigitalInputModePwmS0Enabled; + } else { + qCWarning(dcPcElectric()) << "Unknown mode value" << mode; + return; } QueuedModbusReply *reply = connection->setDigitalInputMode(modeValue); diff --git a/pcelectric/integrationpluginpcelectric.h b/pcelectric/integrationpluginpcelectric.h index 9fb1519..036989b 100644 --- a/pcelectric/integrationpluginpcelectric.h +++ b/pcelectric/integrationpluginpcelectric.h @@ -61,6 +61,7 @@ private: PluginTimer *m_refreshTimer = nullptr; QHash m_connections; QHash m_monitors; + QHash m_initialUpdate; void setupConnection(ThingSetupInfo *info); diff --git a/pcelectric/integrationpluginpcelectric.json b/pcelectric/integrationpluginpcelectric.json index e646b41..82247fe 100644 --- a/pcelectric/integrationpluginpcelectric.json +++ b/pcelectric/integrationpluginpcelectric.json @@ -41,7 +41,7 @@ "minValue": 0, "maxValue": 100, "unit": "Percentage", - "defaultValue": 50 + "defaultValue": 100 }, { "id": "930e0bf9-0038-436d-9eae-5c0f1cb28825", @@ -49,7 +49,11 @@ "displayName": "Digital input mode", "type": "QString", "defaultValue": "Charging allowed", - "allowedValues": ["Charging allowed", "Charging allowed inverted", "PWM and S0 signaling"] + "allowedValues": [ + "Charging allowed", + "Charging allowed inverted", + "PWM and S0 signaling" + ] } ], "stateTypes": [ diff --git a/pcelectric/pcewallbox.cpp b/pcelectric/pcewallbox.cpp index 25ef7f2..0ea2f01 100644 --- a/pcelectric/pcewallbox.cpp +++ b/pcelectric/pcewallbox.cpp @@ -94,8 +94,7 @@ bool PceWallbox::update() m_currentReply = nullptr; if (reply->error() != QModbusDevice::NoError) { - emit updateFinished(); - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); return; } @@ -103,40 +102,76 @@ bool PceWallbox::update() const QVector blockValues = unit.values(); processBlockStatusRegisterValues(blockValues); - emit updateFinished(); - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); }); enqueueRequest(reply); + // Digital input + bool digitalInputAlreadyQueued = false; foreach (QueuedModbusReply *r, m_queue) { if (r->dataUnit().startAddress() == digitalInputModeDataUnit().startAddress()) { - return true; + digitalInputAlreadyQueued = true; + break; } } - reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, digitalInputModeDataUnit(), this); - connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); - connect(reply, &QueuedModbusReply::finished, this, [this, reply](){ + if (!digitalInputAlreadyQueued) { + reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, digitalInputModeDataUnit(), this); + connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); + connect(reply, &QueuedModbusReply::finished, this, [this, reply](){ - if (m_currentReply == reply) - m_currentReply = nullptr; + if (m_currentReply == reply) + m_currentReply = nullptr; - if (reply->error() != QModbusDevice::NoError) { - emit updateFinished(); - sendNextRequest(); - return; + if (reply->error() != QModbusDevice::NoError) { + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); + return; + } + + const QModbusDataUnit unit = reply->reply()->result(); + const QVector values = unit.values(); + processDigitalInputModeRegisterValues(values); + + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); + }); + + enqueueRequest(reply); + } + + + // Led brightness + bool ledBrightnessAlreadyQueued = false; + foreach (QueuedModbusReply *r, m_queue) { + if (r->dataUnit().startAddress() == ledBrightnessDataUnit().startAddress()) { + ledBrightnessAlreadyQueued = true; + break; } + } - const QModbusDataUnit unit = reply->reply()->result(); - const QVector values = unit.values(); - processDigitalInputModeRegisterValues(values); + if (!ledBrightnessAlreadyQueued) { + reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, ledBrightnessDataUnit(), this); + connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); + connect(reply, &QueuedModbusReply::finished, this, [this, reply](){ - emit updateFinished(); - sendNextRequest(); - }); + if (m_currentReply == reply) + m_currentReply = nullptr; - enqueueRequest(reply); + if (reply->error() != QModbusDevice::NoError) { + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); + return; + } + + const QModbusDataUnit unit = reply->reply()->result(); + const QVector values = unit.values(); + processLedBrightnessRegisterValues(values); + + emit updateFinished(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); + }); + + enqueueRequest(reply); + } return true; } @@ -152,7 +187,7 @@ QueuedModbusReply *PceWallbox::setChargingCurrent(quint16 chargingCurrent) if (m_currentReply == reply) m_currentReply = nullptr; - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); return; }); @@ -172,7 +207,7 @@ QueuedModbusReply *PceWallbox::setLedBrightness(quint16 percentage) if (m_currentReply == reply) m_currentReply = nullptr; - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); return; }); @@ -192,7 +227,7 @@ QueuedModbusReply *PceWallbox::setDigitalInputMode(DigitalInputMode digitalInput if (m_currentReply == reply) m_currentReply = nullptr; - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); return; }); @@ -228,7 +263,6 @@ void PceWallbox::sendHeartbeat() QueuedModbusReply *reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeWrite, setHeartbeatDataUnit(m_heartbeat++), this); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); - connect(reply, &QueuedModbusReply::finished, this, [this, reply](){ if (m_currentReply == reply) m_currentReply = nullptr; @@ -239,7 +273,7 @@ void PceWallbox::sendHeartbeat() qCDebug(dcPcElectric()) << "Successfully sent heartbeat to" << m_modbusTcpMaster->hostAddress().toString(); } - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); return; }); @@ -280,13 +314,13 @@ void PceWallbox::sendNextRequest() if (!m_currentReply->reply()) { qCWarning(dcPcElectric()) << "Error occurred while sending" << m_currentReply->requestType() - << ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType()) - << "register:" << m_currentReply->dataUnit().startAddress() - << "length:" << m_currentReply->dataUnit().valueCount() - << "to" << m_modbusTcpMaster->hostAddress().toString() << m_modbusTcpMaster->errorString(); + << ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType()) + << "register:" << m_currentReply->dataUnit().startAddress() + << "length:" << m_currentReply->dataUnit().valueCount() + << "to" << m_modbusTcpMaster->hostAddress().toString() << m_modbusTcpMaster->errorString(); m_currentReply->deleteLater(); m_currentReply = nullptr; - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); return; } @@ -294,7 +328,7 @@ void PceWallbox::sendNextRequest() qCWarning(dcPcElectric()) << "Reply immediatly finished"; m_currentReply->deleteLater(); m_currentReply = nullptr; - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); return; } } @@ -307,7 +341,7 @@ void PceWallbox::enqueueRequest(QueuedModbusReply *reply, bool prepend) m_queue.enqueue(reply); } - sendNextRequest(); + QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); } void PceWallbox::cleanupQueue() diff --git a/pcelectric/pcewallbox.h b/pcelectric/pcewallbox.h index 3a7a150..6650cfd 100644 --- a/pcelectric/pcewallbox.h +++ b/pcelectric/pcewallbox.h @@ -53,6 +53,8 @@ public: QueuedModbusReply *setDigitalInputMode(DigitalInputMode digitalInputMode); + + // Note: the modbus implementation of the wallbox gets stuck if a Modbus request has been sent // and we disconnect the socket before the response has arrived. Only a reboot of the wallbox // fixes the broken communication afterwards. This method waits for the current request before closing the @@ -62,6 +64,7 @@ public: private slots: void sendHeartbeat(); + void sendNextRequest(); private: QTimer m_timer; @@ -70,7 +73,6 @@ private: QQueue m_queue; bool m_aboutToDelete = false; - void sendNextRequest(); void enqueueRequest(QueuedModbusReply *reply, bool prepend = false); void cleanupQueue(); From f84aa052c18a087349c36aafb338be1f109a2391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 2 Oct 2024 10:40:35 +0200 Subject: [PATCH 5/5] Improve digital input settings string --- pcelectric/integrationpluginpcelectric.cpp | 12 ++++++------ pcelectric/integrationpluginpcelectric.json | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pcelectric/integrationpluginpcelectric.cpp b/pcelectric/integrationpluginpcelectric.cpp index e86d2a1..6b4d3bd 100644 --- a/pcelectric/integrationpluginpcelectric.cpp +++ b/pcelectric/integrationpluginpcelectric.cpp @@ -389,13 +389,13 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) switch (connection->digitalInputMode()) { case EV11ModbusTcpConnection::DigitalInputModeEnableCharging: - thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed"); + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "0 | Charging allowed"); break; case EV11ModbusTcpConnection::DigitalInputModeEnableChargingInverted: - thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "Charging allowed inverted"); + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "1 | Charging allowed inverted"); break; case EV11ModbusTcpConnection::DigitalInputModePwmS0Enabled: - thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "PWM and S0 signaling"); + thing->setSettingValue(ev11SettingsDigitalInputModeParamTypeId, "2 | PWM and S0 signaling"); break; } } @@ -421,11 +421,11 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info) qCDebug(dcPcElectric()) << "Setting Digital input mode to" << mode; EV11ModbusTcpConnection::DigitalInputMode modeValue; - if (mode == "Charging allowed") { + if (mode == "0 | Charging allowed") { modeValue = EV11ModbusTcpConnection::DigitalInputModeEnableCharging; - } else if (mode == "Charging allowed inverted") { + } else if (mode == "1 | Charging allowed inverted") { modeValue = EV11ModbusTcpConnection::DigitalInputModeEnableChargingInverted; - } else if (mode == "PWM and S0 signaling") { + } else if (mode == "2 | PWM and S0 signaling") { modeValue = EV11ModbusTcpConnection::DigitalInputModePwmS0Enabled; } else { qCWarning(dcPcElectric()) << "Unknown mode value" << mode; diff --git a/pcelectric/integrationpluginpcelectric.json b/pcelectric/integrationpluginpcelectric.json index 82247fe..4f0e0a3 100644 --- a/pcelectric/integrationpluginpcelectric.json +++ b/pcelectric/integrationpluginpcelectric.json @@ -48,11 +48,11 @@ "name": "digitalInputMode", "displayName": "Digital input mode", "type": "QString", - "defaultValue": "Charging allowed", + "defaultValue": "0 | Charging allowed", "allowedValues": [ - "Charging allowed", - "Charging allowed inverted", - "PWM and S0 signaling" + "0 | Charging allowed", + "1 | Charging allowed inverted", + "2 | PWM and S0 signaling" ] } ],