From 84c13bc562075a69057f18dc6f6fe90c4c0e7422 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 28 Jul 2022 13:43:24 +0200 Subject: [PATCH 1/3] Schrack: Workaround occational random values in Register 507 (min charging current) --- schrack/integrationpluginschrack.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/schrack/integrationpluginschrack.cpp b/schrack/integrationpluginschrack.cpp index a7e99fa..7d574a5 100644 --- a/schrack/integrationpluginschrack.cpp +++ b/schrack/integrationpluginschrack.cpp @@ -137,6 +137,11 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) connect(cionConnection, &CionModbusRtuConnection::minChargingCurrentChanged, thing, [=](quint16 minChargingCurrent){ qCDebug(dcSchrack()) << "Minimum charging current changed:" << minChargingCurrent; + if (minChargingCurrent > 32) { + // Apparently this register occationally holds random values... As a quick'n dirty workaround we'll ignore everything > 32 + qCWarning(dcSchrack()) << "Detected a bogus min charging current register value (reg. 507) of" << minChargingCurrent << ". Ignoring it..."; + return; + } thing->setStateMinValue(cionMaxChargingCurrentStateTypeId, minChargingCurrent); }); From 93b31ce127d8a6a35d136139d0491bfc6d398b50 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 3 Aug 2022 13:00:53 +0200 Subject: [PATCH 2/3] Scrack: Improve debug prints --- schrack/cion-registers.json | 4 ++-- schrack/integrationpluginschrack.cpp | 18 ++++++++++-------- schrack/integrationpluginschrack.h | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/schrack/cion-registers.json b/schrack/cion-registers.json index a796b9b..d255ca1 100644 --- a/schrack/cion-registers.json +++ b/schrack/cion-registers.json @@ -107,7 +107,7 @@ "type": "uint16", "registerType": "holdingRegister", "readSchedule": "update", - "description": "Mode3-State A, B, C, D, U", + "description": "Status bits", "defaultValue": 85, "access": "R" }, @@ -118,7 +118,7 @@ "type": "uint16", "registerType": "holdingRegister", "readSchedule": "update", - "description": "Status bits", + "description": "CP Status bits", "defaultValue": 0, "access": "R" }, diff --git a/schrack/integrationpluginschrack.cpp b/schrack/integrationpluginschrack.cpp index 7d574a5..bdc7867 100644 --- a/schrack/integrationpluginschrack.cpp +++ b/schrack/integrationpluginschrack.cpp @@ -98,7 +98,7 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) // Note: This register really only tells us if we can control anything... i.e. if the wallbox is unlocked via RFID connect(cionConnection, &CionModbusRtuConnection::chargingEnabledChanged, thing, [=](quint16 charging){ - qCDebug(dcSchrack()) << "Charging enabled changed:" << charging; + qCInfo(dcSchrack()) << "Charge control enabled changed:" << charging; }); // We can write chargingCurrentSetpoint to the preferred charging we want, and the wallbox will take it, @@ -106,16 +106,16 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) // We'll use that for setting our state, just monitoring this one on the logs // Setting this to 0 will pause charging, anything else will control the charging (and return the actual value in currentChargingCurrentE3) connect(cionConnection, &CionModbusRtuConnection::chargingCurrentSetpointChanged, thing, [=](quint16 chargingCurrentSetpoint){ - qCDebug(dcSchrack()) << "Charging current setpoint changed:" << chargingCurrentSetpoint; + qCInfo(dcSchrack()) << "Charging current setpoint changed:" << chargingCurrentSetpoint; }); connect(cionConnection, &CionModbusRtuConnection::cpSignalStateChanged, thing, [=](quint16 cpSignalState){ - qCDebug(dcSchrack()) << "CP Signal state changed:" << (char)cpSignalState; + qCInfo(dcSchrack()) << "CP Signal state changed:" << (char)cpSignalState; thing->setStateValue(cionPluggedInStateTypeId, cpSignalState >= 66); }); connect(cionConnection, &CionModbusRtuConnection::currentChargingCurrentE3Changed, thing, [=](quint16 currentChargingCurrentE3){ - qCDebug(dcSchrack()) << "Current charging current E3 current changed:" << currentChargingCurrentE3; + qCInfo(dcSchrack()) << "Current charging current E3 current changed:" << currentChargingCurrentE3; if (cionConnection->chargingCurrentSetpoint() > 0) { thing->setStateValue(cionMaxChargingCurrentStateTypeId, currentChargingCurrentE3); } @@ -124,19 +124,21 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) // The maxChargingCurrentE3 takes into account the DIP switches and connected cable, so this is effectively // our maximum. However, it will go to 0 when unplugged, which is odd, so we'll ignore 0 values. connect(cionConnection, &CionModbusRtuConnection::maxChargingCurrentE3Changed, thing, [=](quint16 maxChargingCurrentE3){ - qCDebug(dcSchrack()) << "Maximum charging current E3 current changed:" << maxChargingCurrentE3; + qCInfo(dcSchrack()) << "Maximum charging current E3 current changed:" << maxChargingCurrentE3; if (maxChargingCurrentE3 != 0) { thing->setStateMaxValue(cionMaxChargingCurrentStateTypeId, maxChargingCurrentE3); } }); - connect(cionConnection, &CionModbusRtuConnection::statusBitsChanged, thing, [=](quint16 /*statusBits*/){ + connect(cionConnection, &CionModbusRtuConnection::statusBitsChanged, thing, [=](quint16 statusBits){ thing->setStateValue(cionConnectedStateTypeId, true); -// qCDebug(dcSchrack()) << "Status bits changed:" << statusBits; + StatusBits status = static_cast(statusBits); + // TODO: Verify if the statusBit for PluggedIn is reliable and if so, use that instead of the plugged in time for the plugged in state. + qCInfo(dcSchrack()) << "Status bits changed:" << status; }); connect(cionConnection, &CionModbusRtuConnection::minChargingCurrentChanged, thing, [=](quint16 minChargingCurrent){ - qCDebug(dcSchrack()) << "Minimum charging current changed:" << minChargingCurrent; + qCInfo(dcSchrack()) << "Minimum charging current changed:" << minChargingCurrent; if (minChargingCurrent > 32) { // Apparently this register occationally holds random values... As a quick'n dirty workaround we'll ignore everything > 32 qCWarning(dcSchrack()) << "Detected a bogus min charging current register value (reg. 507) of" << minChargingCurrent << ". Ignoring it..."; diff --git a/schrack/integrationpluginschrack.h b/schrack/integrationpluginschrack.h index 0a5ba02..0ec6053 100644 --- a/schrack/integrationpluginschrack.h +++ b/schrack/integrationpluginschrack.h @@ -50,6 +50,22 @@ class IntegrationPluginSchrack : public IntegrationPlugin Q_INTERFACES(IntegrationPlugin) public: + enum StatusBit { + StatusBitPluggedIn = 0x0001, + StatusBitChargeContactor1Active = 0x0002, + StatusBitChargeContactor2Active = 0x0004, + StatusBitVentilationRequired = 0x0008, + StatusBitPlugLockController = 0x0010, + StatusBitPlugLockReturn = 0x0020, + StatusBitCollectiveDisorder = 0x0040, + StatusBitDisorderFiLs = 0x0080, + StatusBitCableDisorder = 0x0100, + StatusBitCableRejected = 0x0200, + StatusBitContactorError = 0x0400 + }; + Q_ENUM(StatusBit); + Q_DECLARE_FLAGS(StatusBits, StatusBit) + explicit IntegrationPluginSchrack(); void init() override; void discoverThings(ThingDiscoveryInfo *info) override; From 0670b34a5ea1dfe6356fbc68ebc9549b649886e8 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 3 Aug 2022 13:26:27 +0200 Subject: [PATCH 3/3] Set Register 100 to 1 for charging This is only needed when there's no RFID reader connected --- schrack/integrationpluginschrack.cpp | 34 ++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/schrack/integrationpluginschrack.cpp b/schrack/integrationpluginschrack.cpp index bdc7867..e85eeed 100644 --- a/schrack/integrationpluginschrack.cpp +++ b/schrack/integrationpluginschrack.cpp @@ -98,7 +98,7 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) // Note: This register really only tells us if we can control anything... i.e. if the wallbox is unlocked via RFID connect(cionConnection, &CionModbusRtuConnection::chargingEnabledChanged, thing, [=](quint16 charging){ - qCInfo(dcSchrack()) << "Charge control enabled changed:" << charging; + qCDebug(dcSchrack()) << "Charge control enabled changed:" << charging; }); // We can write chargingCurrentSetpoint to the preferred charging we want, and the wallbox will take it, @@ -106,16 +106,16 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) // We'll use that for setting our state, just monitoring this one on the logs // Setting this to 0 will pause charging, anything else will control the charging (and return the actual value in currentChargingCurrentE3) connect(cionConnection, &CionModbusRtuConnection::chargingCurrentSetpointChanged, thing, [=](quint16 chargingCurrentSetpoint){ - qCInfo(dcSchrack()) << "Charging current setpoint changed:" << chargingCurrentSetpoint; + qCDebug(dcSchrack()) << "Charging current setpoint changed:" << chargingCurrentSetpoint; }); connect(cionConnection, &CionModbusRtuConnection::cpSignalStateChanged, thing, [=](quint16 cpSignalState){ - qCInfo(dcSchrack()) << "CP Signal state changed:" << (char)cpSignalState; + qCDebug(dcSchrack()) << "CP Signal state changed:" << (char)cpSignalState; thing->setStateValue(cionPluggedInStateTypeId, cpSignalState >= 66); }); connect(cionConnection, &CionModbusRtuConnection::currentChargingCurrentE3Changed, thing, [=](quint16 currentChargingCurrentE3){ - qCInfo(dcSchrack()) << "Current charging current E3 current changed:" << currentChargingCurrentE3; + qCDebug(dcSchrack()) << "Current charging current E3 current changed:" << currentChargingCurrentE3; if (cionConnection->chargingCurrentSetpoint() > 0) { thing->setStateValue(cionMaxChargingCurrentStateTypeId, currentChargingCurrentE3); } @@ -124,7 +124,7 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) // The maxChargingCurrentE3 takes into account the DIP switches and connected cable, so this is effectively // our maximum. However, it will go to 0 when unplugged, which is odd, so we'll ignore 0 values. connect(cionConnection, &CionModbusRtuConnection::maxChargingCurrentE3Changed, thing, [=](quint16 maxChargingCurrentE3){ - qCInfo(dcSchrack()) << "Maximum charging current E3 current changed:" << maxChargingCurrentE3; + qCDebug(dcSchrack()) << "Maximum charging current E3 current changed:" << maxChargingCurrentE3; if (maxChargingCurrentE3 != 0) { thing->setStateMaxValue(cionMaxChargingCurrentStateTypeId, maxChargingCurrentE3); } @@ -134,11 +134,11 @@ void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info) thing->setStateValue(cionConnectedStateTypeId, true); StatusBits status = static_cast(statusBits); // TODO: Verify if the statusBit for PluggedIn is reliable and if so, use that instead of the plugged in time for the plugged in state. - qCInfo(dcSchrack()) << "Status bits changed:" << status; + qCDebug(dcSchrack()) << "Status bits changed:" << status; }); connect(cionConnection, &CionModbusRtuConnection::minChargingCurrentChanged, thing, [=](quint16 minChargingCurrent){ - qCInfo(dcSchrack()) << "Minimum charging current changed:" << minChargingCurrent; + qCDebug(dcSchrack()) << "Minimum charging current changed:" << minChargingCurrent; if (minChargingCurrent > 32) { // Apparently this register occationally holds random values... As a quick'n dirty workaround we'll ignore everything > 32 qCWarning(dcSchrack()) << "Detected a bogus min charging current register value (reg. 507) of" << minChargingCurrent << ". Ignoring it..."; @@ -237,11 +237,27 @@ void IntegrationPluginSchrack::executeAction(ThingActionInfo *info) if (info->action().actionTypeId() == cionPowerActionTypeId) { qCDebug(dcSchrack()) << "Setting charging enabled:" << (info->action().paramValue(cionPowerActionPowerParamTypeId).toBool() ? 1 : 0); int maxSetPoint = info->thing()->stateValue(cionMaxChargingCurrentStateTypeId).toUInt(); - // If user enables it, we'll write the maxChargingPower value + + // Note: If the wallbox has an RFID reader connected, writing register 100 (chargingEnabled) won't work as the RFID + // reader takes control over it. However, if there's no RFID reader connected, we'll have to set it ourselves. + // So summarizing: + // * In setups with RFID reader, we can only control this with register 101 (maxChargingCurrent) by setting it to 0 + // to stop charging, or something >= 6 to allow charging. + // * In setups without RFID reader, we set 100 to true/false. Note that DIP switches 1 & 2 need to be OFF for register + // 100 to be writable. + if (info->action().paramValue(cionPowerActionPowerParamTypeId).toBool()) { + // In case there's no RFID reader + cionConnection->setChargingEnabled(1); + + // And restore the charging current in case setting the above fails ModbusRtuReply *reply = cionConnection->setChargingCurrentSetpoint(maxSetPoint); waitForActionFinish(info, reply, cionPowerStateTypeId, true); - } else { // we'll write 0 to the max charging power + } else { + // In case there's no RFID reader + cionConnection->setChargingEnabled(0); + + // And set the maxChargingCurrent to 0 in case the above fails ModbusRtuReply *reply = cionConnection->setChargingCurrentSetpoint(0); waitForActionFinish(info, reply, cionPowerStateTypeId, false); }