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

master
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.
Once you connect to the go-eCharger, nymea will configure the wallbox to use MQTT and send information to nymea.
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.
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.
The preferred way of communicating would be MQTT, default is HTTP.
## Supported Things

View File

@ -105,9 +105,6 @@ void IntegrationPluginGoECharger::setupThing(ThingSetupInfo *info)
{
Thing *thing = info->thing();
if (thing->thingClassId() == goeHomeThingClassId) {
// TODO: handle reconfigure
QNetworkReply *reply = hardwareManager()->networkManager()->get(buildStatusRequest(thing));
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, info, [=](){
@ -129,6 +126,13 @@ void IntegrationPluginGoECharger::setupThing(ThingSetupInfo *info)
qCDebug(dcGoECharger()) << "Received" << qUtf8Printable(jsonDoc.toJson());
QVariantMap statusMap = jsonDoc.toVariant().toMap();
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
qCDebug(dcGoECharger()) << "Setup using MQTT connection for" << thing;
QHostAddress address = QHostAddress(thing->paramValue(goeHomeThingIpAddressParamTypeId).toString());
@ -151,13 +155,11 @@ void IntegrationPluginGoECharger::postSetupThing(Thing *thing)
{
if (thing->thingClassId() == goeHomeThingClassId) {
// Set up refresh timer if needed and if we are not using mqtt
if (!thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool()) {
if (!m_refreshTimer) {
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(4);
connect(m_refreshTimer, &PluginTimer::timeout, this, &IntegrationPluginGoECharger::refreshHttp);
m_refreshTimer->start();
qCDebug(dcGoECharger()) << "Enable HTTP refresh timer...";
}
if (!thing->paramValue(goeHomeThingUseMqttParamTypeId).toBool() && !m_refreshTimer) {
qCDebug(dcGoECharger()) << "Enabling HTTP refresh timer...";
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(4);
connect(m_refreshTimer, &PluginTimer::timeout, this, &IntegrationPluginGoECharger::refreshHttp);
m_refreshTimer->start();
}
}
}
@ -169,6 +171,11 @@ void IntegrationPluginGoECharger::thingRemoved(Thing *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
if (m_refreshTimer && myThings().isEmpty()) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
@ -210,36 +217,30 @@ void IntegrationPluginGoECharger::executeAction(ThingActionInfo *info)
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
// Maybe check if the user sets it or a automatism
// Set the allow value
QString configuration = QString("amp=%1").arg(maxChargingCurrent);
sendActionRequest(thing, info, configuration);
return;
} else if (action.actionTypeId() == goeHomeAbsoluteMaxAmpereActionTypeId) {
uint maxAmpere = action.paramValue(goeHomeAbsoluteMaxAmpereActionAbsoluteMaxAmpereParamTypeId).toUInt();
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);
sendActionRequest(thing, info, configuration);
return;
} else if (action.actionTypeId() == goeHomeCloudActionTypeId) {
bool enabled = action.paramValue(goeHomeCloudActionCloudParamTypeId).toBool();
qCDebug(dcGoECharger()) << "Set cloud" << (enabled ? "enabled" : "disabled");
// Set the allow value
QString configuration = QString("cdi=%1").arg(enabled ? 1: 0);
sendActionRequest(thing, info, configuration);
return;
} else if (action.actionTypeId() == goeHomeLedBrightnessActionTypeId) {
quint8 brightness = action.paramValue(goeHomeLedBrightnessActionLedBrightnessParamTypeId).toUInt();
qCDebug(dcGoECharger()) << "Set led brightnss to" << brightness << "/" << 255;
// Set the allow value
QString configuration = QString("lbr=%1").arg(brightness);
sendActionRequest(thing, info, configuration);
return;
} else if (action.actionTypeId() == goeHomeLedEnergySaveActionTypeId) {
bool enabled = action.paramValue(goeHomeLedEnergySaveActionLedEnergySaveParamTypeId).toBool();
qCDebug(dcGoECharger()) << "Set led energy saving" << (enabled ? "enabled" : "disabled");
// Set the allow value
QString configuration = QString("lse=%1").arg(enabled ? 1: 0);
sendActionRequest(thing, info, configuration);
return;
@ -682,10 +683,20 @@ void IntegrationPluginGoECharger::refreshHttp()
// Poll thing which if not using mqtt
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;
QNetworkReply *reply = hardwareManager()->networkManager()->get(buildStatusRequest(thing));
m_pendingReplies.insert(thing, reply);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, thing, [=](){
// We are done with this thing reply
m_pendingReplies.remove(thing);
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcGoECharger()) << "HTTP status reply returned error:" << reply->errorString();
thing->setStateValue(goeHomeConnectedStateTypeId, false);

View File

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