PCE: update settings handling, update method and connection behavior
This commit is contained in:
parent
816c132c46
commit
323019fc05
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -61,6 +61,7 @@ private:
|
||||
PluginTimer *m_refreshTimer = nullptr;
|
||||
QHash<Thing *, PceWallbox *> m_connections;
|
||||
QHash<Thing *, NetworkDeviceMonitor *> m_monitors;
|
||||
QHash<Thing *, bool> m_initialUpdate;
|
||||
|
||||
void setupConnection(ThingSetupInfo *info);
|
||||
|
||||
|
||||
@ -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": [
|
||||
|
||||
@ -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<quint16> 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<quint16> 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<quint16> 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<quint16> 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()
|
||||
|
||||
@ -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<QueuedModbusReply *> m_queue;
|
||||
bool m_aboutToDelete = false;
|
||||
|
||||
void sendNextRequest();
|
||||
void enqueueRequest(QueuedModbusReply *reply, bool prepend = false);
|
||||
|
||||
void cleanupQueue();
|
||||
|
||||
Reference in New Issue
Block a user