PCE: Assume current power for firmware version 0.19

This commit is contained in:
Simon Stürz 2026-02-04 16:23:21 +01:00
parent 431dc43776
commit 02149aeb2d
6 changed files with 138 additions and 125 deletions

View File

@ -3,7 +3,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH * Copyright (C) 2024 - 2026, chargebyte austria GmbH
* *
* This file is part of nymea-plugins-modbus. * This file is part of nymea-plugins-modbus.
* *
@ -26,13 +26,10 @@
#include "pcelectricdiscovery.h" #include "pcelectricdiscovery.h"
#include "plugininfo.h" #include "plugininfo.h"
#include <hardwaremanager.h>
#include <hardware/electricity.h> #include <hardware/electricity.h>
#include <hardwaremanager.h>
IntegrationPluginPcElectric::IntegrationPluginPcElectric() IntegrationPluginPcElectric::IntegrationPluginPcElectric() {}
{
}
void IntegrationPluginPcElectric::init() void IntegrationPluginPcElectric::init()
{ {
@ -51,8 +48,9 @@ void IntegrationPluginPcElectric::discoverThings(ThingDiscoveryInfo *info)
PcElectricDiscovery *discovery = new PcElectricDiscovery(hardwareManager()->networkDeviceDiscovery(), 502, 1, info); PcElectricDiscovery *discovery = new PcElectricDiscovery(hardwareManager()->networkDeviceDiscovery(), 502, 1, info);
connect(discovery, &PcElectricDiscovery::discoveryFinished, info, [=]() { connect(discovery, &PcElectricDiscovery::discoveryFinished, info, [=]() {
foreach (const PcElectricDiscovery::Result &result, discovery->results()) { foreach (const PcElectricDiscovery::Result &result, discovery->results()) {
ThingDescriptor descriptor(ev11ThingClassId,
ThingDescriptor descriptor(ev11ThingClassId, "PCE EV11.3 (" + result.serialNumber + ")", "Version: " + result.firmwareRevision + " - " + result.networkDeviceInfo.address().toString()); "PCE EV11.3 (" + result.serialNumber + ")",
"Version: " + result.firmwareRevision + " - " + result.networkDeviceInfo.address().toString());
qCDebug(dcPcElectric()) << "Discovered:" << descriptor.title() << descriptor.description(); qCDebug(dcPcElectric()) << "Discovered:" << descriptor.title() << descriptor.description();
// Check if we already have set up this device // Check if we already have set up this device
@ -149,7 +147,6 @@ void IntegrationPluginPcElectric::postSetupThing(Thing *thing)
m_refreshTimer->start(); m_refreshTimer->start();
} }
PceWallbox::ChargingCurrentState chargingCurrentState; PceWallbox::ChargingCurrentState chargingCurrentState;
chargingCurrentState.power = thing->stateValue(ev11PowerStateTypeId).toBool(); chargingCurrentState.power = thing->stateValue(ev11PowerStateTypeId).toBool();
chargingCurrentState.maxChargingCurrent = thing->stateValue(ev11MaxChargingCurrentStateTypeId).toDouble(); chargingCurrentState.maxChargingCurrent = thing->stateValue(ev11MaxChargingCurrentStateTypeId).toDouble();
@ -197,7 +194,6 @@ void IntegrationPluginPcElectric::executeAction(ThingActionInfo *info)
} }
if (info->action().actionTypeId() == ev11PowerActionTypeId) { if (info->action().actionTypeId() == ev11PowerActionTypeId) {
bool power = info->action().paramValue(ev11PowerActionPowerParamTypeId).toBool(); bool power = info->action().paramValue(ev11PowerActionPowerParamTypeId).toBool();
qCDebug(dcPcElectric()) << "Set charging enabled to" << power; qCDebug(dcPcElectric()) << "Set charging enabled to" << power;
@ -222,7 +218,6 @@ void IntegrationPluginPcElectric::executeAction(ThingActionInfo *info)
return; return;
} else if (info->action().actionTypeId() == ev11MaxChargingCurrentActionTypeId) { } else if (info->action().actionTypeId() == ev11MaxChargingCurrentActionTypeId) {
double desiredChargingCurrent = info->action().paramValue(ev11MaxChargingCurrentActionMaxChargingCurrentParamTypeId).toDouble(); double desiredChargingCurrent = info->action().paramValue(ev11MaxChargingCurrentActionMaxChargingCurrentParamTypeId).toDouble();
qCDebug(dcPcElectric()) << "Set max charging current to" << desiredChargingCurrent << "A"; qCDebug(dcPcElectric()) << "Set max charging current to" << desiredChargingCurrent << "A";
@ -247,7 +242,6 @@ void IntegrationPluginPcElectric::executeAction(ThingActionInfo *info)
return; return;
} else if (info->action().actionTypeId() == ev11DesiredPhaseCountActionTypeId) { } else if (info->action().actionTypeId() == ev11DesiredPhaseCountActionTypeId) {
uint desiredPhaseCount = info->action().paramValue(ev11DesiredPhaseCountActionDesiredPhaseCountParamTypeId).toUInt(); uint desiredPhaseCount = info->action().paramValue(ev11DesiredPhaseCountActionDesiredPhaseCountParamTypeId).toUInt();
qCDebug(dcPcElectric()) << "Set desried phase count to" << desiredPhaseCount; qCDebug(dcPcElectric()) << "Set desried phase count to" << desiredPhaseCount;
@ -332,8 +326,7 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info)
} }
thing->setStateMaxValue(ev11MaxChargingCurrentStateTypeId, connection->maxChargingCurrentDip() / 1000); thing->setStateMaxValue(ev11MaxChargingCurrentStateTypeId, connection->maxChargingCurrentDip() / 1000);
thing->setStateValue(ev11PluggedInStateTypeId, connection->chargingState() >= PceWallbox::ChargingStateB1 && thing->setStateValue(ev11PluggedInStateTypeId, connection->chargingState() >= PceWallbox::ChargingStateB1 && connection->chargingState() < PceWallbox::ChargingStateError);
connection->chargingState() < PceWallbox::ChargingStateError);
thing->setStateValue(ev11ChargingStateTypeId, connection->chargingState() == PceWallbox::ChargingStateC2); thing->setStateValue(ev11ChargingStateTypeId, connection->chargingState() == PceWallbox::ChargingStateC2);
if (connection->chargingRelayState() != EV11ModbusTcpConnection::ChargingRelayStateNoCharging) { if (connection->chargingRelayState() != EV11ModbusTcpConnection::ChargingRelayStateNoCharging) {
@ -405,7 +398,6 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info)
} }
if (m_initialUpdate.value(thing)) { if (m_initialUpdate.value(thing)) {
m_initialUpdate[thing] = false; m_initialUpdate[thing] = false;
qCDebug(dcPcElectric()) << "Update initial charger states from charging current register..."; qCDebug(dcPcElectric()) << "Update initial charger states from charging current register...";
@ -440,7 +432,6 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info)
} }
thing->setStateValue(ev11DigitalInputModeStateTypeId, connection->digitalInputMode()); thing->setStateValue(ev11DigitalInputModeStateTypeId, connection->digitalInputMode());
if (connection->firmwareRevision() >= "0022") { if (connection->firmwareRevision() >= "0022") {
thing->setSettingValue(ev11SettingsPhaseAutoSwitchPauseParamTypeId, connection->phaseAutoSwitchPause()); thing->setSettingValue(ev11SettingsPhaseAutoSwitchPauseParamTypeId, connection->phaseAutoSwitchPause());
thing->setStateValue(ev11SettingsPhaseAutoSwitchMinChargingTimeParamTypeId, connection->phaseAutoSwitchMinChargingTime()); thing->setStateValue(ev11SettingsPhaseAutoSwitchMinChargingTimeParamTypeId, connection->phaseAutoSwitchMinChargingTime());
@ -451,12 +442,23 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info)
if (connection->firmwareRevision() >= "0022") { if (connection->firmwareRevision() >= "0022") {
thing->setStateValue(ev11CurrentPowerStateTypeId, connection->currentPower()); thing->setStateValue(ev11CurrentPowerStateTypeId, connection->currentPower());
thing->setStateValue(ev11DigitalInputFlagStateTypeId, QString("0b%1").arg(connection->digitalInputFlag(), 16, 2, QLatin1Char('0'))); thing->setStateValue(ev11DigitalInputFlagStateTypeId, QString("0b%1").arg(connection->digitalInputFlag(), 16, 2, QLatin1Char('0')));
} } else {
// In firmware 0019 there is no current power register, depending on the CP state we can assume the car is consuming the amount
// we adjusted, if the car is full, the CP state will change back to B2
if (connection->chargingState() == PceWallbox::ChargingStateC2 && connection->currentPower() == 0) {
// We are currently chargin, but the wallbox reports 0 W (which is expected), let's calculate the theoretical power...
double assumedCurrentPower = thing->stateValue(ev11PhaseCountStateTypeId).toInt() * 230 * thing->stateValue(ev11MaxChargingCurrentStateTypeId).toDouble();
qCDebug(dcPcElectric()) << "Assuming current power" << assumedCurrentPower << "W (" << thing->stateValue(ev11PhaseCountStateTypeId).toInt() << "phases * 230 V *"
<< thing->stateValue(ev11MaxChargingCurrentStateTypeId).toDouble() << "A )";
thing->setStateValue(ev11CurrentPowerStateTypeId, assumedCurrentPower);
} else {
thing->setStateValue(ev11CurrentPowerStateTypeId, 0);
}
}
}); });
connect(thing, &Thing::settingChanged, connection, [thing, connection](const ParamTypeId &paramTypeId, const QVariant &value) { connect(thing, &Thing::settingChanged, connection, [thing, connection](const ParamTypeId &paramTypeId, const QVariant &value) {
if (paramTypeId == ev11SettingsLedBrightnessParamTypeId) { if (paramTypeId == ev11SettingsLedBrightnessParamTypeId) {
quint16 percentage = value.toUInt(); quint16 percentage = value.toUInt();
@ -547,4 +549,3 @@ void IntegrationPluginPcElectric::setupConnection(ThingSetupInfo *info)
if (monitor->reachable()) if (monitor->reachable())
connection->connectDevice(); connection->connectDevice();
} }

View File

@ -3,7 +3,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH * Copyright (C) 2024 - 2026, chargebyte austria GmbH
* *
* This file is part of nymea-plugins-modbus. * This file is part of nymea-plugins-modbus.
* *
@ -25,15 +25,15 @@
#ifndef INTEGRATIONPLUGINPCELECTRIC_H #ifndef INTEGRATIONPLUGINPCELECTRIC_H
#define INTEGRATIONPLUGINPCELECTRIC_H #define INTEGRATIONPLUGINPCELECTRIC_H
#include <QObject>
#include <QDebug> #include <QDebug>
#include <QObject>
#include <integrations/integrationplugin.h> #include <integrations/integrationplugin.h>
#include <network/networkdevicediscovery.h> #include <network/networkdevicediscovery.h>
#include <plugintimer.h> #include <plugintimer.h>
#include "pcewallbox.h"
#include "extern-plugininfo.h" #include "extern-plugininfo.h"
#include "pcewallbox.h"
class IntegrationPluginPcElectric : public IntegrationPlugin class IntegrationPluginPcElectric : public IntegrationPlugin
{ {
@ -67,9 +67,6 @@ private:
QHash<Thing *, PceWallbox::ChargingCurrentState> m_chargingCurrentStateBuffer; QHash<Thing *, PceWallbox::ChargingCurrentState> m_chargingCurrentStateBuffer;
void setupConnection(ThingSetupInfo *info); void setupConnection(ThingSetupInfo *info);
}; };
#endif // INTEGRATIONPLUGINPCELECTRIC_H #endif // INTEGRATIONPLUGINPCELECTRIC_H

View File

@ -26,20 +26,17 @@
#include "extern-plugininfo.h" #include "extern-plugininfo.h"
PcElectricDiscovery::PcElectricDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port, quint16 modbusAddress, QObject *parent) PcElectricDiscovery::PcElectricDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port, quint16 modbusAddress, QObject *parent)
: QObject{parent}, : QObject{parent}
m_networkDeviceDiscovery{networkDeviceDiscovery}, , m_networkDeviceDiscovery{networkDeviceDiscovery}
m_port{port}, , m_port{port}
m_modbusAddress{modbusAddress} , m_modbusAddress{modbusAddress}
{ {}
}
QList<PcElectricDiscovery::Result> PcElectricDiscovery::results() const QList<PcElectricDiscovery::Result> PcElectricDiscovery::results() const
{ {
return m_results; return m_results;
} }
void PcElectricDiscovery::startDiscovery() void PcElectricDiscovery::startDiscovery()
{ {
qCInfo(dcPcElectric()) << "Discovery: Start searching for PCE wallboxes in the network..."; qCInfo(dcPcElectric()) << "Discovery: Start searching for PCE wallboxes in the network...";
@ -49,7 +46,6 @@ void PcElectricDiscovery::startDiscovery()
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &PcElectricDiscovery::checkNetworkDevice); connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &PcElectricDiscovery::checkNetworkDevice);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater); connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=]() { connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=]() {
m_networkDeviceInfos = discoveryReply->networkDeviceInfos(); m_networkDeviceInfos = discoveryReply->networkDeviceInfos();
// Finish with some delay so the last added network device information objects still can be checked. // Finish with some delay so the last added network device information objects still can be checked.
@ -75,7 +71,8 @@ void PcElectricDiscovery::checkNetworkDevice(const QHostAddress &address)
// Modbus TCP connected...ok, let's try to initialize it! // Modbus TCP connected...ok, let's try to initialize it!
connect(connection, &EV11ModbusTcpConnection::initializationFinished, this, [=](bool success) { connect(connection, &EV11ModbusTcpConnection::initializationFinished, this, [=](bool success) {
if (!success) { if (!success) {
qCDebug(dcPcElectric()) << "Discovery: Initialization failed on" << address.toString() << "Continue...";; qCDebug(dcPcElectric()) << "Discovery: Initialization failed on" << address.toString() << "Continue...";
;
cleanupConnection(connection); cleanupConnection(connection);
return; return;
} }
@ -93,7 +90,6 @@ void PcElectricDiscovery::checkNetworkDevice(const QHostAddress &address)
// According to PCE the HW revision must be 0 // According to PCE the HW revision must be 0
if (!registerMacAddress.isNull() && connection->hardwareRevision() == 0) { if (!registerMacAddress.isNull() && connection->hardwareRevision() == 0) {
// Parse the serial number // Parse the serial number
QByteArray serialRawData; QByteArray serialRawData;
QDataStream stream(&serialRawData, QIODevice::ReadWrite); QDataStream stream(&serialRawData, QIODevice::ReadWrite);
@ -118,7 +114,8 @@ void PcElectricDiscovery::checkNetworkDevice(const QHostAddress &address)
// Initializing... // Initializing...
if (!connection->initialize()) { if (!connection->initialize()) {
qCDebug(dcPcElectric()) << "Discovery: Unable to initialize connection on" << address.toString() << "Continue...";; qCDebug(dcPcElectric()) << "Discovery: Unable to initialize connection on" << address.toString() << "Continue...";
;
cleanupConnection(connection); cleanupConnection(connection);
} }
}); });
@ -126,14 +123,16 @@ void PcElectricDiscovery::checkNetworkDevice(const QHostAddress &address)
// If we get any error...skip this host... // If we get any error...skip this host...
connect(connection->modbusTcpMaster(), &ModbusTcpMaster::connectionErrorOccurred, this, [=](QModbusDevice::Error error) { connect(connection->modbusTcpMaster(), &ModbusTcpMaster::connectionErrorOccurred, this, [=](QModbusDevice::Error error) {
if (error != QModbusDevice::NoError) { if (error != QModbusDevice::NoError) {
qCDebug(dcPcElectric()) << "Discovery: Connection error on" << address.toString() << "Continue...";; qCDebug(dcPcElectric()) << "Discovery: Connection error on" << address.toString() << "Continue...";
;
cleanupConnection(connection); cleanupConnection(connection);
} }
}); });
// If check reachability failed...skip this host... // If check reachability failed...skip this host...
connect(connection, &EV11ModbusTcpConnection::checkReachabilityFailed, this, [=]() { connect(connection, &EV11ModbusTcpConnection::checkReachabilityFailed, this, [=]() {
qCDebug(dcPcElectric()) << "Discovery: Check reachability failed on" << address.toString() << "Continue...";; qCDebug(dcPcElectric()) << "Discovery: Check reachability failed on" << address.toString() << "Continue...";
;
cleanupConnection(connection); cleanupConnection(connection);
}); });
@ -158,15 +157,21 @@ void PcElectricDiscovery::finishDiscovery()
Result result = m_potentialResults.at(i); Result result = m_potentialResults.at(i);
if (networkDeviceInfo.macAddressInfos().hasMacAddress(result.registerMacAddress)) { if (networkDeviceInfo.macAddressInfos().hasMacAddress(result.registerMacAddress)) {
qCInfo(dcPcElectric()) << "Discovery: --> Found EV11.3" qCInfo(dcPcElectric())
<< "Serial number:" << result.serialNumber << "Discovery: --> Found EV11.3"
<< "Firmware revision:" << result.firmwareRevision << "Serial number:"
<< result.serialNumber
<< "Firmware revision:"
<< result.firmwareRevision
<< result.networkDeviceInfo; << result.networkDeviceInfo;
m_results.append(result); m_results.append(result);
} else { } else {
qCWarning(dcPcElectric()) << "Discovery: --> Found potential EV11.3, but not adding to the results due to imcomplete MAC address check:" qCWarning(dcPcElectric())
<< "Serial number:" << result.serialNumber << "Discovery: --> Found potential EV11.3, but not adding to the results due to imcomplete MAC address check:"
<< "Firmware revision:" << result.firmwareRevision << "Serial number:"
<< result.serialNumber
<< "Firmware revision:"
<< result.firmwareRevision
<< result.networkDeviceInfo; << result.networkDeviceInfo;
} }
} }
@ -178,7 +183,10 @@ void PcElectricDiscovery::finishDiscovery()
foreach (EV11ModbusTcpConnection *connection, m_connections) foreach (EV11ModbusTcpConnection *connection, m_connections)
cleanupConnection(connection); cleanupConnection(connection);
qCInfo(dcPcElectric()) << "Discovery: Finished the discovery process. Found" << m_results.length() qCInfo(dcPcElectric())
<< "PCE wallboxes in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz"); << "Discovery: Finished the discovery process. Found"
<< m_results.length()
<< "PCE wallboxes in"
<< QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
emit discoveryFinished(); emit discoveryFinished();
} }

View File

@ -37,7 +37,8 @@ class PcElectricDiscovery : public QObject
public: public:
explicit PcElectricDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port, quint16 modbusAddress, QObject *parent = nullptr); explicit PcElectricDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port, quint16 modbusAddress, QObject *parent = nullptr);
typedef struct Result { typedef struct Result
{
QString serialNumber; QString serialNumber;
QString firmwareRevision; QString firmwareRevision;
QHostAddress address; QHostAddress address;

View File

@ -82,7 +82,6 @@ bool PceWallbox::update()
QueuedModbusReply *reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, readBlockStatusDataUnit(), this); QueuedModbusReply *reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, readBlockStatusDataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -100,7 +99,6 @@ bool PceWallbox::update()
enqueueRequest(reply); enqueueRequest(reply);
// charging current register. Contains // charging current register. Contains
// - power state // - power state
// - chargingcurrent (if power is true) // - chargingcurrent (if power is true)
@ -117,7 +115,6 @@ bool PceWallbox::update()
reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, chargingCurrentDataUnit(), this); reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, chargingCurrentDataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -149,7 +146,6 @@ bool PceWallbox::update()
reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, digitalInputModeDataUnit(), this); reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, digitalInputModeDataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -168,7 +164,6 @@ bool PceWallbox::update()
enqueueRequest(reply); enqueueRequest(reply);
} }
// Led brightness // Led brightness
bool ledBrightnessAlreadyQueued = false; bool ledBrightnessAlreadyQueued = false;
foreach (QueuedModbusReply *r, m_readQueue) { foreach (QueuedModbusReply *r, m_readQueue) {
@ -182,7 +177,6 @@ bool PceWallbox::update()
reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, ledBrightnessDataUnit(), this); reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, ledBrightnessDataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -204,11 +198,9 @@ bool PceWallbox::update()
enqueueRequest(reply); enqueueRequest(reply);
} }
if (firmwareRevision() < "0022") if (firmwareRevision() < "0022")
return true; return true;
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// Registers since 0022 (V 0.22) // Registers since 0022 (V 0.22)
@ -225,7 +217,6 @@ bool PceWallbox::update()
reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, readBlockUpdate2DataUnit(), this); reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, readBlockUpdate2DataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -245,7 +236,6 @@ bool PceWallbox::update()
enqueueRequest(reply); enqueueRequest(reply);
} }
bool phaseAutoSwitchPauseQueued = false; bool phaseAutoSwitchPauseQueued = false;
foreach (QueuedModbusReply *r, m_readQueue) { foreach (QueuedModbusReply *r, m_readQueue) {
if (r->dataUnit().startAddress() == phaseAutoSwitchPauseDataUnit().startAddress()) { if (r->dataUnit().startAddress() == phaseAutoSwitchPauseDataUnit().startAddress()) {
@ -258,7 +248,6 @@ bool PceWallbox::update()
reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, phaseAutoSwitchPauseDataUnit(), this); reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, phaseAutoSwitchPauseDataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -290,7 +279,6 @@ bool PceWallbox::update()
reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, phaseAutoSwitchMinChargingTimeDataUnit(), this); reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, phaseAutoSwitchMinChargingTimeDataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -322,7 +310,6 @@ bool PceWallbox::update()
reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, forceChargingResumeDataUnit(), this); reply = new QueuedModbusReply(QueuedModbusReply::RequestTypeRead, forceChargingResumeDataUnit(), this);
connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater); connect(reply, &QueuedModbusReply::finished, reply, &QueuedModbusReply::deleteLater);
connect(reply, &QueuedModbusReply::finished, this, [this, reply]() { connect(reply, &QueuedModbusReply::finished, this, [this, reply]() {
if (m_currentReply == reply) if (m_currentReply == reply)
m_currentReply = nullptr; m_currentReply = nullptr;
@ -506,7 +493,6 @@ PceWallbox::ChargingCurrentState PceWallbox::deriveStatesFromRegister(quint16 re
// Only set max charging current if power, otherwise we use default 6A // Only set max charging current if power, otherwise we use default 6A
if (chargingCurrentState.power) { if (chargingCurrentState.power) {
bool threePhaseCharging = (registerValue & (1 << 15)); bool threePhaseCharging = (registerValue & (1 << 15));
chargingCurrentState.desiredPhaseCount = (threePhaseCharging ? 3 : 1); chargingCurrentState.desiredPhaseCount = (threePhaseCharging ? 3 : 1);
@ -516,7 +502,6 @@ PceWallbox::ChargingCurrentState PceWallbox::deriveStatesFromRegister(quint16 re
return chargingCurrentState; return chargingCurrentState;
} }
void PceWallbox::sendHeartbeat() void PceWallbox::sendHeartbeat()
{ {
if (m_aboutToDelete) if (m_aboutToDelete)
@ -573,26 +558,41 @@ void PceWallbox::sendNextRequest()
switch (m_currentReply->requestType()) { switch (m_currentReply->requestType()) {
case QueuedModbusReply::RequestTypeRead: case QueuedModbusReply::RequestTypeRead:
qCDebug(dcPcElectric()) << "--> Reading" << ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType()) qCDebug(dcPcElectric())
<< "register:" << m_currentReply->dataUnit().startAddress() << "--> Reading"
<< "length" << m_currentReply->dataUnit().valueCount(); << ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType())
<< "register:"
<< m_currentReply->dataUnit().startAddress()
<< "length"
<< m_currentReply->dataUnit().valueCount();
m_currentReply->setReply(m_modbusTcpMaster->sendReadRequest(m_currentReply->dataUnit(), m_slaveId)); m_currentReply->setReply(m_modbusTcpMaster->sendReadRequest(m_currentReply->dataUnit(), m_slaveId));
break; break;
case QueuedModbusReply::RequestTypeWrite: case QueuedModbusReply::RequestTypeWrite:
qCDebug(dcPcElectric()) << "--> Writing" << ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType()) qCDebug(dcPcElectric())
<< "register:" << m_currentReply->dataUnit().startAddress() << "--> Writing"
<< "length:" << m_currentReply->dataUnit().valueCount() << ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType())
<< "values:" << m_currentReply->dataUnit().values(); << "register:"
<< m_currentReply->dataUnit().startAddress()
<< "length:"
<< m_currentReply->dataUnit().valueCount()
<< "values:"
<< m_currentReply->dataUnit().values();
m_currentReply->setReply(m_modbusTcpMaster->sendWriteRequest(m_currentReply->dataUnit(), m_slaveId)); m_currentReply->setReply(m_modbusTcpMaster->sendWriteRequest(m_currentReply->dataUnit(), m_slaveId));
break; break;
} }
if (!m_currentReply->reply()) { if (!m_currentReply->reply()) {
qCWarning(dcPcElectric()) << "Error occurred while sending" << m_currentReply->requestType() qCWarning(dcPcElectric())
<< "Error occurred while sending"
<< m_currentReply->requestType()
<< ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType()) << ModbusDataUtils::registerTypeToString(m_currentReply->dataUnit().registerType())
<< "register:" << m_currentReply->dataUnit().startAddress() << "register:"
<< "length:" << m_currentReply->dataUnit().valueCount() << m_currentReply->dataUnit().startAddress()
<< "to" << m_modbusTcpMaster->hostAddress().toString() << m_modbusTcpMaster->errorString(); << "length:"
<< m_currentReply->dataUnit().valueCount()
<< "to"
<< m_modbusTcpMaster->hostAddress().toString()
<< m_modbusTcpMaster->errorString();
m_currentReply->deleteLater(); m_currentReply->deleteLater();
m_currentReply = nullptr; m_currentReply = nullptr;
QTimer::singleShot(0, this, &PceWallbox::sendNextRequest); QTimer::singleShot(0, this, &PceWallbox::sendNextRequest);
@ -634,6 +634,13 @@ void PceWallbox::cleanupQueues()
QDebug operator<<(QDebug debug, const PceWallbox::ChargingCurrentState &chargingCurrentState) QDebug operator<<(QDebug debug, const PceWallbox::ChargingCurrentState &chargingCurrentState)
{ {
QDebugStateSaver saver(debug); QDebugStateSaver saver(debug);
debug.nospace() << "ChargingCurrentState(" << chargingCurrentState.power << ", " << chargingCurrentState.maxChargingCurrent << " [A], " << chargingCurrentState.desiredPhaseCount << ')'; debug.nospace()
<< "ChargingCurrentState("
<< chargingCurrentState.power
<< ", "
<< chargingCurrentState.maxChargingCurrent
<< " [A], "
<< chargingCurrentState.desiredPhaseCount
<< ')';
return debug; return debug;
} }

View File

@ -25,10 +25,10 @@
#ifndef PCEWALLBOX_H #ifndef PCEWALLBOX_H
#define PCEWALLBOX_H #define PCEWALLBOX_H
#include <QTimer>
#include <QQueue>
#include <QDebug> #include <QDebug>
#include <QObject> #include <QObject>
#include <QQueue>
#include <QTimer>
#include <queuedmodbusreply.h> #include <queuedmodbusreply.h>
@ -38,7 +38,8 @@ class PceWallbox : public EV11ModbusTcpConnection
{ {
Q_OBJECT Q_OBJECT
public: public:
typedef struct ChargingCurrentState { typedef struct ChargingCurrentState
{
bool power = false; bool power = false;
double maxChargingCurrent = 6; double maxChargingCurrent = 6;
uint desiredPhaseCount = 3; uint desiredPhaseCount = 3;
@ -57,7 +58,6 @@ public:
QueuedModbusReply *setDigitalInputModeAsync(DigitalInputMode digitalInputMode); QueuedModbusReply *setDigitalInputModeAsync(DigitalInputMode digitalInputMode);
// Note: the modbus implementation of the wallbox gets stuck if a Modbus request has been sent // 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 // 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 // fixes the broken communication afterwards. This method waits for the current request before closing the
@ -87,5 +87,4 @@ private:
QDebug operator<<(QDebug debug, const PceWallbox::ChargingCurrentState &chargingCurrentState); QDebug operator<<(QDebug debug, const PceWallbox::ChargingCurrentState &chargingCurrentState);
#endif // PCEWALLBOX_H #endif // PCEWALLBOX_H