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;
device->setStateValue(wallboxPowerStateTypeId, reportTwo.enableUser);
device->setStateValue(wallboxMaxChargingCurrentPercentStateTypeId, reportTwo.MaxCurrentPercentage);
switch (reportTwo.state) {
case KeContact::State::Starting:
case KeContact::StateStarting:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Starting"));
break;
case KeContact::State::NotReady:
case KeContact::StateNotReady:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Not ready for charging"));
break;
case KeContact::State::Ready:
case KeContact::StateReady:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Ready for charging"));
break;
case KeContact::State::Charging:
case KeContact::StateCharging:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Charging"));
break;
case KeContact::State::Error:
case KeContact::StateError:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Erro"));
break;
case KeContact::State::AuthorizationRejected:
case KeContact::StateAuthorizationRejected:
device->setStateValue(wallboxActivityStateTypeId, QT_TR_NOOP("Authorization rejected"));
break;
}
switch (reportTwo.plugState) {
case KeContact::PlugState::Unplugged:
case KeContact::PlugStateUnplugged:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Unplugged"));
break;
case KeContact::PlugState::PluggedOnChargingStation:
case KeContact::PlugStatePluggedOnChargingStation:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in charging station"));
break;
case KeContact::PlugState::PluggedOnChargingStationAndPluggedOnEV:
case KeContact::PlugStatePluggedOnChargingStationAndPluggedOnEV:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV"));
break;
case KeContact::PlugState::PluggedOnChargingStationAndPlugLocked:
case KeContact::PlugStatePluggedOnChargingStationAndPlugLocked:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in and locked"));
break;
case KeContact::PlugState::PluggedOnChargingStationAndPlugLockedAndPluggedOnEV:
case KeContact::PlugStatePluggedOnChargingStationAndPlugLockedAndPluggedOnEV:
device->setStateValue(wallboxPlugStateStateTypeId, QT_TR_NOOP("Plugged in on EV and locked"));
break;
}
@ -273,17 +274,74 @@ void DevicePluginKeba::onReportThreeReceived(const KeContact::ReportThree &repor
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)
{
Device *device = info->device();
Action action = info->action();
qCDebug(dcKebaKeContact()) << "Execute action" << device->name() << action.actionTypeId().toString();
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());
if (!keba) {
qCWarning(dcKebaKeContact()) << "Device not properly initialized, Keba object missing";
@ -291,8 +349,8 @@ void DevicePluginKeba::executeAction(DeviceActionInfo *info)
}
if(action.actionTypeId() == wallboxMaxChargingCurrentActionTypeId){
int ampere = action.param(wallboxMaxChargingCurrentActionMaxChargingCurrentParamTypeId).value().toInt()*1000;
QUuid requestId = keba->setMaxAmpere(ampere);
int milliAmpere = action.param(wallboxMaxChargingCurrentActionMaxChargingCurrentParamTypeId).value().toInt();
QUuid requestId = keba->setMaxAmpere(milliAmpere);
m_asyncActions.insert(requestId, info);
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 onReportTwoReceived(const KeContact::ReportTwo &reportTwo);
void onReportThreeReceived(const KeContact::ReportThree &reportThree);
void onBroadcastReceived(KeContact::BroadcastType type, const QVariant &content);
};
#endif // INTEGRATIONPLUGINKEBA_H

View File

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

View File

@ -45,6 +45,7 @@ KeContact::KeContact(QHostAddress address, QObject *parent) :
emit connectionChanged(false);
//Try to send the next command
handleNextCommandInQueue();
m_deviceBlocked = false;
});
}
@ -88,13 +89,14 @@ void KeContact::sendCommand(const QByteArray &command)
emit connectionChanged(false);
return;
}
if(!m_commandList.isEmpty()) {
if(m_deviceBlocked) {
//add command to queue
m_commandList.append(command);
} else {
//send command
m_udpSocket->writeDatagram(command, m_address, 7090);
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();
if (!m_commandList.isEmpty()) {
QByteArray command = m_commandList.first();
QByteArray command = m_commandList.takeFirst();
m_udpSocket->writeDatagram(command, m_address, 7090);
m_requestTimeoutTimer->start(5000);
} else {
@ -244,24 +246,40 @@ void KeContact::readPendingDatagrams()
qCDebug(dcKebaKeContact()) << "Data received" << datagram;
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
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();
handleNextCommandInQueue();
if(datagram.left(8).contains("Firmware")){
qCDebug(dcKebaKeContact()) << "Firmware information reveiced";
QByteArrayList firmware = datagram.split(':');
if (firmware.length() >= 2) {
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
QJsonParseError error;
@ -272,7 +290,7 @@ void KeContact::readPendingDatagrams()
QVariantMap data = jsonDoc.toVariant().toMap();
if(data.contains("ID")){
if(data.contains("ID")) {
if (data.value("ID").toString() == "1") {
ReportOne reportOne;
@ -322,6 +340,26 @@ void KeContact::readPendingDatagrams()
reportThree.SerialNumber = data.value("Serial").toString();
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();
enum State {
Starting = 0,
NotReady,
Ready,
Charging,
Error,
AuthorizationRejected
StateStarting = 0,
StateNotReady,
StateReady,
StateCharging,
StateError,
StateAuthorizationRejected
};
enum PlugState {
Unplugged = 0,
PluggedOnChargingStation = 1,
PluggedOnChargingStationAndPlugLocked = 3,
PluggedOnChargingStationAndPluggedOnEV = 5,
PluggedOnChargingStationAndPlugLockedAndPluggedOnEV = 7
PlugStateUnplugged = 0,
PlugStatePluggedOnChargingStation = 1,
PlugStatePluggedOnChargingStationAndPlugLocked = 3,
PlugStatePluggedOnChargingStationAndPluggedOnEV = 5,
PlugStatePluggedOnChargingStationAndPlugLockedAndPluggedOnEV = 7
};
enum BroadcastType {
BroadcastTypeState = 0,
BroadcastTypePlug,
BroadcastTypeInput,
BroadcastTypeEnableSys,
BroadcastTypeMaxCurr,
BroadcastTypeEPres
};
struct ReportOne {
@ -139,6 +148,7 @@ signals:
void reportOneReceived(const ReportOne &reportOne);
void reportTwoReceived(const ReportTwo &reportTwo);
void reportThreeReceived(const ReportThree &reportThree);
void broadcastReceived(BroadcastType type, const QVariant &content);
private slots:
void readPendingDatagrams();