Merge PR #530: go-eCharger: Handle reconfigure for MQTT and queue HTTP requests

This commit is contained in:
Jenkins nymea 2022-03-27 19:50:05 +02:00
commit c8cee228f4
3 changed files with 31 additions and 18 deletions

View File

@ -2,8 +2,9 @@
nymea plugin for go-eCharger smart wallbox for electic vehicles. nymea plugin for go-eCharger smart wallbox for electic vehicles.
Once you connect to the go-eCharger, nymea will configure the wallbox to use MQTT and send information to nymea. If you are using the original go-e App or other client services to communicate with the wallbox, disable MQTT during the setup in order to make sure all services are able to communicate with the wallbox. There is no support for multiple MQTT clients on go-e devices, thus nymea defaults to HTTP to prevent constant reconfiguration trough the clients.
Please make sure no other service is using the custom MQTT server in the local network, otherwise they will exclude each other, depending who comes first.
The preferred way of communicating would be MQTT, default is HTTP.
## Supported Things ## Supported Things

View File

@ -105,9 +105,6 @@ void IntegrationPluginGoECharger::setupThing(ThingSetupInfo *info)
{ {
Thing *thing = info->thing(); Thing *thing = info->thing();
if (thing->thingClassId() == goeHomeThingClassId) { if (thing->thingClassId() == goeHomeThingClassId) {
// TODO: handle reconfigure
QNetworkReply *reply = hardwareManager()->networkManager()->get(buildStatusRequest(thing)); QNetworkReply *reply = hardwareManager()->networkManager()->get(buildStatusRequest(thing));
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, info, [=](){ connect(reply, &QNetworkReply::finished, info, [=](){
@ -129,6 +126,13 @@ void IntegrationPluginGoECharger::setupThing(ThingSetupInfo *info)
qCDebug(dcGoECharger()) << "Received" << qUtf8Printable(jsonDoc.toJson()); qCDebug(dcGoECharger()) << "Received" << qUtf8Printable(jsonDoc.toJson());
QVariantMap statusMap = jsonDoc.toVariant().toMap(); QVariantMap statusMap = jsonDoc.toVariant().toMap();
if (thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool()) { if (thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool()) {
// Handle reconfigure
if (m_channels.contains(thing)) {
hardwareManager()->mqttProvider()->releaseChannel(m_channels.take(thing));
// Continue with normal setup
}
// Verify mqtt client and set it up // Verify mqtt client and set it up
qCDebug(dcGoECharger()) << "Setup using MQTT connection for" << thing; qCDebug(dcGoECharger()) << "Setup using MQTT connection for" << thing;
QHostAddress address = QHostAddress(thing->paramValue(goeHomeThingIpAddressParamTypeId).toString()); QHostAddress address = QHostAddress(thing->paramValue(goeHomeThingIpAddressParamTypeId).toString());
@ -151,13 +155,11 @@ void IntegrationPluginGoECharger::postSetupThing(Thing *thing)
{ {
if (thing->thingClassId() == goeHomeThingClassId) { if (thing->thingClassId() == goeHomeThingClassId) {
// Set up refresh timer if needed and if we are not using mqtt // Set up refresh timer if needed and if we are not using mqtt
if (!thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool()) { if (!thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool() && !m_refreshTimer) {
if (!m_refreshTimer) { qCDebug(dcGoECharger()) << "Enabling HTTP refresh timer...";
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(4); m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(4);
connect(m_refreshTimer, &PluginTimer::timeout, this, &IntegrationPluginGoECharger::refreshHttp); connect(m_refreshTimer, &PluginTimer::timeout, this, &IntegrationPluginGoECharger::refreshHttp);
m_refreshTimer->start(); m_refreshTimer->start();
qCDebug(dcGoECharger()) << "Enable HTTP refresh timer...";
}
} }
} }
} }
@ -169,6 +171,11 @@ void IntegrationPluginGoECharger::thingRemoved(Thing *thing)
hardwareManager()->mqttProvider()->releaseChannel(m_channels.take(thing)); hardwareManager()->mqttProvider()->releaseChannel(m_channels.take(thing));
} }
// Cleanup possible pending replies
if (m_pendingReplies.contains(thing) && m_pendingReplies.value(thing)) {
m_pendingReplies.take(thing)->abort();
}
// Clean up refresh timer if set up // Clean up refresh timer if set up
if (m_refreshTimer && myThings().isEmpty()) { if (m_refreshTimer && myThings().isEmpty()) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer); hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
@ -210,36 +217,30 @@ void IntegrationPluginGoECharger::executeAction(ThingActionInfo *info)
qCDebug(dcGoECharger()) << "Setting max charging current to" << maxChargingCurrent << "A"; qCDebug(dcGoECharger()) << "Setting max charging current to" << maxChargingCurrent << "A";
// FIXME: check if we can use amx since it is better for pv charging, not all version seen implement amx // FIXME: check if we can use amx since it is better for pv charging, not all version seen implement amx
// Maybe check if the user sets it or a automatism // Maybe check if the user sets it or a automatism
// Set the allow value
QString configuration = QString("amp=%1").arg(maxChargingCurrent); QString configuration = QString("amp=%1").arg(maxChargingCurrent);
sendActionRequest(thing, info, configuration); sendActionRequest(thing, info, configuration);
return; return;
} else if (action.actionTypeId() == goeHomeAbsoluteMaxAmpereActionTypeId) { } else if (action.actionTypeId() == goeHomeAbsoluteMaxAmpereActionTypeId) {
uint maxAmpere = action.paramValue(goeHomeAbsoluteMaxAmpereActionAbsoluteMaxAmpereParamTypeId).toUInt(); uint maxAmpere = action.paramValue(goeHomeAbsoluteMaxAmpereActionAbsoluteMaxAmpereParamTypeId).toUInt();
qCDebug(dcGoECharger()) << "Setting absolute maximal charging amperes to" << maxAmpere << "A"; qCDebug(dcGoECharger()) << "Setting absolute maximal charging amperes to" << maxAmpere << "A";
// TODO: use amx if available
// Set the allow value
QString configuration = QString("ama=%1").arg(maxAmpere); QString configuration = QString("ama=%1").arg(maxAmpere);
sendActionRequest(thing, info, configuration); sendActionRequest(thing, info, configuration);
return; return;
} else if (action.actionTypeId() == goeHomeCloudActionTypeId) { } else if (action.actionTypeId() == goeHomeCloudActionTypeId) {
bool enabled = action.paramValue(goeHomeCloudActionCloudParamTypeId).toBool(); bool enabled = action.paramValue(goeHomeCloudActionCloudParamTypeId).toBool();
qCDebug(dcGoECharger()) << "Set cloud" << (enabled ? "enabled" : "disabled"); qCDebug(dcGoECharger()) << "Set cloud" << (enabled ? "enabled" : "disabled");
// Set the allow value
QString configuration = QString("cdi=%1").arg(enabled ? 1: 0); QString configuration = QString("cdi=%1").arg(enabled ? 1: 0);
sendActionRequest(thing, info, configuration); sendActionRequest(thing, info, configuration);
return; return;
} else if (action.actionTypeId() == goeHomeLedBrightnessActionTypeId) { } else if (action.actionTypeId() == goeHomeLedBrightnessActionTypeId) {
quint8 brightness = action.paramValue(goeHomeLedBrightnessActionLedBrightnessParamTypeId).toUInt(); quint8 brightness = action.paramValue(goeHomeLedBrightnessActionLedBrightnessParamTypeId).toUInt();
qCDebug(dcGoECharger()) << "Set led brightnss to" << brightness << "/" << 255; qCDebug(dcGoECharger()) << "Set led brightnss to" << brightness << "/" << 255;
// Set the allow value
QString configuration = QString("lbr=%1").arg(brightness); QString configuration = QString("lbr=%1").arg(brightness);
sendActionRequest(thing, info, configuration); sendActionRequest(thing, info, configuration);
return; return;
} else if (action.actionTypeId() == goeHomeLedEnergySaveActionTypeId) { } else if (action.actionTypeId() == goeHomeLedEnergySaveActionTypeId) {
bool enabled = action.paramValue(goeHomeLedEnergySaveActionLedEnergySaveParamTypeId).toBool(); bool enabled = action.paramValue(goeHomeLedEnergySaveActionLedEnergySaveParamTypeId).toBool();
qCDebug(dcGoECharger()) << "Set led energy saving" << (enabled ? "enabled" : "disabled"); qCDebug(dcGoECharger()) << "Set led energy saving" << (enabled ? "enabled" : "disabled");
// Set the allow value
QString configuration = QString("lse=%1").arg(enabled ? 1: 0); QString configuration = QString("lse=%1").arg(enabled ? 1: 0);
sendActionRequest(thing, info, configuration); sendActionRequest(thing, info, configuration);
return; return;
@ -682,10 +683,20 @@ void IntegrationPluginGoECharger::refreshHttp()
// Poll thing which if not using mqtt // Poll thing which if not using mqtt
if (!thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool()) { if (!thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool()) {
// Make sure there is not a request pending for this thing, otherwise wait for the next refresh
if (m_pendingReplies.contains(thing) && m_pendingReplies.value(thing))
continue;
qCDebug(dcGoECharger()) << "Refresh HTTP status from" << thing; qCDebug(dcGoECharger()) << "Refresh HTTP status from" << thing;
QNetworkReply *reply = hardwareManager()->networkManager()->get(buildStatusRequest(thing)); QNetworkReply *reply = hardwareManager()->networkManager()->get(buildStatusRequest(thing));
m_pendingReplies.insert(thing, reply);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, thing, [=](){ connect(reply, &QNetworkReply::finished, thing, [=](){
// We are done with this thing reply
m_pendingReplies.remove(thing);
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcGoECharger()) << "HTTP status reply returned error:" << reply->errorString(); qCWarning(dcGoECharger()) << "HTTP status reply returned error:" << reply->errorString();
thing->setStateValue(goeHomeConnectedStateTypeId, false); thing->setStateValue(goeHomeConnectedStateTypeId, false);

View File

@ -88,6 +88,7 @@ public:
private: private:
PluginTimer *m_refreshTimer = nullptr; PluginTimer *m_refreshTimer = nullptr;
QHash<Thing *, MqttChannel *> m_channels; QHash<Thing *, MqttChannel *> m_channels;
QHash<Thing *, QNetworkReply *> m_pendingReplies;
void update(Thing *thing, const QVariantMap &statusMap); void update(Thing *thing, const QVariantMap &statusMap);
QNetworkRequest buildStatusRequest(Thing *thing); QNetworkRequest buildStatusRequest(Thing *thing);