From 816c132c46586f9acdbbe9e40abb51d6ac340029 Mon Sep 17 00:00:00 2001 From: Martin Lukas Date: Mon, 2 Sep 2024 09:31:42 +0200 Subject: [PATCH] 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