improved async action handling

This commit is contained in:
Boernsman 2020-02-18 18:56:18 +05:00 committed by bernhard.trinnes
parent 4b0b83d941
commit 1cbbeb2045
5 changed files with 200 additions and 92 deletions

View File

@ -214,42 +214,43 @@ void DevicePluginKeba::onReportTwoReceived(const KeContact::ReportTwo &reportTwo
return; return;
device->setStateValue(wallboxPowerStateTypeId, reportTwo.enableUser); device->setStateValue(wallboxPowerStateTypeId, reportTwo.enableUser);
device->setStateValue(wallboxMaxChargingCurrentPercentStateTypeId, reportTwo.MaxCurrentPercentage);
switch (reportTwo.state) { switch (reportTwo.state) {
case KeContact::State::Starting: case KeContact::StateStarting:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Starting")); device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Starting"));
break; break;
case KeContact::State::NotReady: case KeContact::StateNotReady:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Not ready for charging")); device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Not ready for charging"));
break; break;
case KeContact::State::Ready: case KeContact::StateReady:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Ready for charging")); device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Ready for charging"));
break; break;
case KeContact::State::Charging: case KeContact::StateCharging:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Charging")); device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Charging"));
break; break;
case KeContact::State::Error: case KeContact::StateError:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Erro")); device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Erro"));
break; break;
case KeContact::State::AuthorizationRejected: case KeContact::StateAuthorizationRejected:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Authorization rejected")); device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Authorization rejected"));
break; break;
} }
switch (reportTwo.plugState) { switch (reportTwo.plugState) {
case KeContact::PlugState::Unplugged: case KeContact::PlugStateUnplugged:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Unplugged")); device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Unplugged"));
break; break;
case KeContact::PlugState::PluggedOnChargingStation: case KeContact::PlugStatePluggedOnChargingStation:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in charging station")); device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in charging station"));
break; break;
case KeContact::PlugState::PluggedOnChargingStationAndPluggedOnEV: case KeContact::PlugStatePluggedOnChargingStationAndPluggedOnEV:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV")); device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV"));
break; break;
case KeContact::PlugState::PluggedOnChargingStationAndPlugLocked: case KeContact::PlugStatePluggedOnChargingStationAndPlugLocked:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in and locked")); device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in and locked"));
break; break;
case KeContact::PlugState::PluggedOnChargingStationAndPlugLockedAndPluggedOnEV: case KeContact::PlugStatePluggedOnChargingStationAndPlugLockedAndPluggedOnEV:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV and locked")); device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV and locked"));
break; break;
} }
@ -273,17 +274,74 @@ void DevicePluginKeba::onReportThreeReceived(const KeContact::ReportThree &repor
device->setStateValue(wallboxTotalEnergyConsumedStateTypeId, reportThree.EnergyTotal); device->setStateValue(wallboxTotalEnergyConsumedStateTypeId, reportThree.EnergyTotal);
} }
void DevicePluginKeba::onBroadcastReceived(KeContact::BroadcastType type, const QVariant &content)
{
KeContact *keba = static_cast<KeContact *>(sender());
Device *device = myDevices().findById(m_kebaDevices.key(keba));
if (!device)
return;
switch (type) {
case KeContact::BroadcastTypePlug:
switch (KeContact::PlugState(content.toInt())) {
case KeContact::PlugStateUnplugged:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Unplugged"));
break;
case KeContact::PlugStatePluggedOnChargingStation:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in charging station"));
break;
case KeContact::PlugStatePluggedOnChargingStationAndPluggedOnEV:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV"));
break;
case KeContact::PlugStatePluggedOnChargingStationAndPlugLocked:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in and locked"));
break;
case KeContact::PlugStatePluggedOnChargingStationAndPlugLockedAndPluggedOnEV:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV and locked"));
break;
}
break;
case KeContact::BroadcastTypeInput:
break;
case KeContact::BroadcastTypeEPres:
device->setStateValue(wallboxEPStateTypeId, content.toInt());
break;
case KeContact::BroadcastTypeState:
switch (KeContact::State(content.toInt())) {
case KeContact::StateStarting:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Starting"));
break;
case KeContact::StateNotReady:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Not ready for charging"));
break;
case KeContact::StateReady:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Ready for charging"));
break;
case KeContact::StateCharging:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Charging"));
break;
case KeContact::StateError:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Erro"));
break;
case KeContact::StateAuthorizationRejected:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Authorization rejected"));
break;
}
break;
case KeContact::BroadcastTypeMaxCurr:
device->setStateValue(wallboxMaxChargingCurrentStateTypeId, content.toInt());
break;
case KeContact::BroadcastTypeEnableSys:
break;
}
}
void DevicePluginKeba::executeAction(DeviceActionInfo *info) void DevicePluginKeba::executeAction(DeviceActionInfo *info)
{ {
Device *device = info->device(); Device *device = info->device();
Action action = info->action(); Action action = info->action();
qCDebug(dcKebaKeContact()) << "Execute action" << device->name() << action.actionTypeId().toString();
if (device->deviceClassId() == wallboxDeviceClassId) { if (device->deviceClassId() == wallboxDeviceClassId) {
// Print information that we are executing now the update action
qCDebug(dcKebaKeContact()) << "Execute update action" << action.id();
KeContact *keba = m_kebaDevices.value(device->id()); KeContact *keba = m_kebaDevices.value(device->id());
if (!keba) { if (!keba) {
qCWarning(dcKebaKeContact()) << "Device not properly initialized, Keba object missing"; qCWarning(dcKebaKeContact()) << "Device not properly initialized, Keba object missing";
@ -291,8 +349,8 @@ void DevicePluginKeba::executeAction(DeviceActionInfo *info)
} }
if(action.actionTypeId() == wallboxMaxChargingCurrentActionTypeId){ if(action.actionTypeId() == wallboxMaxChargingCurrentActionTypeId){
int ampere = action.param(wallboxMaxChargingCurrentActionMaxChargingCurrentParamTypeId).value().toInt()*1000; int milliAmpere = action.param(wallboxMaxChargingCurrentActionMaxChargingCurrentParamTypeId).value().toInt();
QUuid requestId = keba->setMaxAmpere(ampere); QUuid requestId = keba->setMaxAmpere(milliAmpere);
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &DeviceActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);}); connect(info, &DeviceActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);});

View File

@ -75,6 +75,7 @@ private slots:
void onReportOneReceived(const KeContact::ReportOne &reportOne); void onReportOneReceived(const KeContact::ReportOne &reportOne);
void onReportTwoReceived(const KeContact::ReportTwo &reportTwo); void onReportTwoReceived(const KeContact::ReportTwo &reportTwo);
void onReportThreeReceived(const KeContact::ReportThree &reportThree); void onReportThreeReceived(const KeContact::ReportThree &reportThree);
void onBroadcastReceived(KeContact::BroadcastType type, const QVariant &content);
}; };
#endif // INTEGRATIONPLUGINKEBA_H #endif // INTEGRATIONPLUGINKEBA_H

View File

@ -39,7 +39,8 @@
"displayName": "Connected", "displayName": "Connected",
"displayNameEvent": "Connection changed", "displayNameEvent": "Connection changed",
"type": "bool", "type": "bool",
"defaultValue": false "defaultValue": false,
"cached": false
}, },
{ {
"id": "83ed0774-2a91-434d-b03c-d920d02f2981", "id": "83ed0774-2a91-434d-b03c-d920d02f2981",

View File

@ -45,6 +45,7 @@ KeContact::KeContact(QHostAddress address, QObject *parent) :
emit connectionChanged(false); emit connectionChanged(false);
//Try to send the next command //Try to send the next command
handleNextCommandInQueue(); handleNextCommandInQueue();
m_deviceBlocked = false;
}); });
} }
@ -88,13 +89,14 @@ void KeContact::sendCommand(const QByteArray &command)
emit connectionChanged(false); emit connectionChanged(false);
return; return;
} }
if(!m_commandList.isEmpty()) { if(m_deviceBlocked) {
//add command to queue //add command to queue
m_commandList.append(command); m_commandList.append(command);
} else { } else {
//send command //send command
m_udpSocket->writeDatagram(command, m_address, 7090); m_udpSocket->writeDatagram(command, m_address, 7090);
m_requestTimeoutTimer->start(5000); m_requestTimeoutTimer->start(5000);
m_deviceBlocked = true;
} }
} }
@ -107,7 +109,7 @@ void KeContact::handleNextCommandInQueue()
} }
qCDebug(dcKebaKeContact()) << "Handle Command Queue- Pending commands" << m_commandList.length() << "Pending requestIds" << m_pendingRequests.length(); qCDebug(dcKebaKeContact()) << "Handle Command Queue- Pending commands" << m_commandList.length() << "Pending requestIds" << m_pendingRequests.length();
if (!m_commandList.isEmpty()) { if (!m_commandList.isEmpty()) {
QByteArray command = m_commandList.first(); QByteArray command = m_commandList.takeFirst();
m_udpSocket->writeDatagram(command, m_address, 7090); m_udpSocket->writeDatagram(command, m_address, 7090);
m_requestTimeoutTimer->start(5000); m_requestTimeoutTimer->start(5000);
} else { } else {
@ -244,24 +246,40 @@ void KeContact::readPendingDatagrams()
qCDebug(dcKebaKeContact()) << "Data received" << datagram; qCDebug(dcKebaKeContact()) << "Data received" << datagram;
if(datagram.contains("TCH-OK")){ if(datagram.contains("TCH-OK")){
if (datagram.contains("done")) {
emit commandExecuted(m_pendingRequests.takeFirst(), true);
} else {
emit commandExecuted(m_pendingRequests.takeFirst(), false);
}
}
//Command response has been received, now send the next command //Command response has been received, now send the next command
m_deviceBlocked = false;
m_requestTimeoutTimer->stop();
handleNextCommandInQueue();
if (!m_pendingRequests.isEmpty()) {
QUuid requestId = m_pendingRequests.takeFirst();
if (datagram.contains("done")) {
emit commandExecuted(requestId, true);
} else {
emit commandExecuted(requestId, false);
}
} else {
//Probably the response has taken too long and the requestId has been already removed
}
} else if(datagram.left(8).contains("Firmware")){
//Command response has been received, now send the next command
m_deviceBlocked = false;
m_requestTimeoutTimer->stop(); m_requestTimeoutTimer->stop();
handleNextCommandInQueue(); handleNextCommandInQueue();
if(datagram.left(8).contains("Firmware")){
qCDebug(dcKebaKeContact()) << "Firmware information reveiced"; qCDebug(dcKebaKeContact()) << "Firmware information reveiced";
QByteArrayList firmware = datagram.split(':'); QByteArrayList firmware = datagram.split(':');
if (firmware.length() >= 2) { if (firmware.length() >= 2) {
emit deviceInformationReceived(firmware[1]); emit deviceInformationReceived(firmware[1]);
} }
} } else {
//Command response has been received, now send the next command
m_deviceBlocked = false;
m_requestTimeoutTimer->stop();
handleNextCommandInQueue();
// Convert the rawdata to a json document // Convert the rawdata to a json document
QJsonParseError error; QJsonParseError error;
@ -272,7 +290,7 @@ void KeContact::readPendingDatagrams()
QVariantMap data = jsonDoc.toVariant().toMap(); QVariantMap data = jsonDoc.toVariant().toMap();
if(data.contains("ID")){ if(data.contains("ID")) {
if (data.value("ID").toString() == "1") { if (data.value("ID").toString() == "1") {
ReportOne reportOne; ReportOne reportOne;
@ -322,6 +340,26 @@ void KeContact::readPendingDatagrams()
reportThree.SerialNumber = data.value("Serial").toString(); reportThree.SerialNumber = data.value("Serial").toString();
emit reportThreeReceived(reportThree); emit reportThreeReceived(reportThree);
} }
} else {
if (data.contains("State")) {
emit broadcastReceived(BroadcastType::BroadcastTypeState, data.value("State"));
}
if (data.contains("Plug")) {
emit broadcastReceived(BroadcastType::BroadcastTypePlug, data.value("Plug"));
}
if (data.contains("Input")) {
emit broadcastReceived(BroadcastType::BroadcastTypeInput, data.value("Input"));
}
if (data.contains("Enable sys")) {
emit broadcastReceived(BroadcastType::BroadcastTypeEnableSys, data.value("Enable sys"));
}
if (data.contains("Max curr")) {
emit broadcastReceived(BroadcastType::BroadcastTypeMaxCurr, data.value("Max curr"));
}
if (data.contains("E pres")) {
emit broadcastReceived(BroadcastType::BroadcastTypeEPres, data.value("E pres"));
}
}
} }
} }
} }

View File

@ -47,20 +47,29 @@ public:
bool init(); bool init();
enum State { enum State {
Starting = 0, StateStarting = 0,
NotReady, StateNotReady,
Ready, StateReady,
Charging, StateCharging,
Error, StateError,
AuthorizationRejected StateAuthorizationRejected
}; };
enum PlugState { enum PlugState {
Unplugged = 0, PlugStateUnplugged = 0,
PluggedOnChargingStation = 1, PlugStatePluggedOnChargingStation = 1,
PluggedOnChargingStationAndPlugLocked = 3, PlugStatePluggedOnChargingStationAndPlugLocked = 3,
PluggedOnChargingStationAndPluggedOnEV = 5, PlugStatePluggedOnChargingStationAndPluggedOnEV = 5,
PluggedOnChargingStationAndPlugLockedAndPluggedOnEV = 7 PlugStatePluggedOnChargingStationAndPlugLockedAndPluggedOnEV = 7
};
enum BroadcastType {
BroadcastTypeState = 0,
BroadcastTypePlug,
BroadcastTypeInput,
BroadcastTypeEnableSys,
BroadcastTypeMaxCurr,
BroadcastTypeEPres
}; };
struct ReportOne { struct ReportOne {
@ -139,6 +148,7 @@ signals:
void reportOneReceived(const ReportOne &reportOne); void reportOneReceived(const ReportOne &reportOne);
void reportTwoReceived(const ReportTwo &reportTwo); void reportTwoReceived(const ReportTwo &reportTwo);
void reportThreeReceived(const ReportThree &reportThree); void reportThreeReceived(const ReportThree &reportThree);
void broadcastReceived(BroadcastType type, const QVariant &content);
private slots: private slots:
void readPendingDatagrams(); void readPendingDatagrams();