Merge PR #678: Shelly: Reconfigure CoAP on gen 1 shellies if they don't send any data

master
jenkins 2023-05-16 12:59:03 +02:00
commit 83492ae78d
2 changed files with 72 additions and 3 deletions

View File

@ -912,13 +912,16 @@ void IntegrationPluginShelly::onMulticastMessageReceived(const QHostAddress &sou
return;
}
qCDebug(dcShelly) << "CoIoT multicast message for" << thing->name() << ":" << qUtf8Printable(jsonDoc.toJson());
QVariantMap map = jsonDoc.toVariant().toMap();
thing->setStateValue("connected", true);
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
child->setStateValue("connected", true);
}
// Remember when we recieved the last update
thing->setProperty("lastCoIoTMessage", QDateTime::currentDateTime());
qCDebug(dcShelly) << "CoIoT multicast message for" << thing->name() << ":" << qUtf8Printable(jsonDoc.toJson());
QVariantMap map = jsonDoc.toVariant().toMap();
// Some states are calculated from multiple values in the list and we'll need to keep them temporarily
int red = 0, green = 0, blue = 0, white = 0;
@ -1294,9 +1297,10 @@ void IntegrationPluginShelly::updateStatus()
void IntegrationPluginShelly::fetchStatusGen1(Thing *thing)
{
QHostAddress address = getIP(thing);
QUrl url;
url.setScheme("http");
url.setHost(getIP(thing).toString());
url.setHost(address.toString());
url.setPath("/status");
url.setUserName(thing->paramValue(usernameParamTypeMap.value(thing->thingClassId())).toString());
url.setPassword(thing->paramValue(passwordParamTypeMap.value(thing->thingClassId())).toString());
@ -1340,6 +1344,53 @@ void IntegrationPluginShelly::fetchStatusGen1(Thing *thing)
thing->setStateValue("currentVersion", updateMap.value("old_version").toString());
thing->setStateValue("availableVersion", updateMap.value("new_version").toString());
thing->setStateValue("updateStatus", updateStatusMap.value(updateMap.value("status").toString()));
// Sometimes, some shellies just stop to send CoIoT messages until they are rebooted...
// If communication to the shelly per se works fine, but we didn't receive anything in more than a minute,
// let's reconfigure coap and reboot the shelly
if (thing->property("lastCoIoTMessage").toDateTime().addSecs(10 * 60) < QDateTime::currentDateTime()) {
qCInfo(dcShelly()) << "Shelly" << thing->name() << "didn't send us a CoIoT message in a minute. Reconfiguring CoIoT and rebooting it.";
QUrlQuery query;
QHostAddress address = getIP(thing);
query.addQueryItem("coiot_enable", "true");
if (thing->paramValue("coapMode").toString() == "unicast") {
QHostAddress ourAddress;
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
if (address.isInSubnet(addressEntry.ip(), addressEntry.prefixLength())) {
ourAddress = addressEntry.ip();
break;
}
}
}
if (!ourAddress.isNull()) {
query.addQueryItem("coiot_peer", ourAddress.toString() + ":5683");
} else {
qCWarning(dcShelly) << "Unable to determine a matching interface for CoIoT unicast. Falling back to multicast.";
query.addQueryItem("coiot_peer", "mcast");
}
} else {
query.addQueryItem("coiot_peer", "mcast");
}
QNetworkRequest setCoIoTRequest = createHttpRequest(thing, "/settings", query);
QNetworkReply *reply = hardwareManager()->networkManager()->get(setCoIoTRequest);
connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, thing, [this, thing, reply](){
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcShelly()) << "Failed to reconfigure coap on shelly" << thing->name();
}
QNetworkRequest rebootRequest = createHttpRequest(thing, "/reboot");
QNetworkReply *reply = hardwareManager()->networkManager()->get(rebootRequest);
connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, thing, [reply](){
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcShelly()) << "Failed to send reboot request to shelly.";
}
});
});
}
});
}
@ -2059,6 +2110,21 @@ void IntegrationPluginShelly::handleInputEvent(Thing *thing, const QString &butt
}
}
QNetworkRequest IntegrationPluginShelly::createHttpRequest(Thing *thing, const QString &path, const QUrlQuery &urlQuery)
{
QUrl url;
url.setScheme("http");
url.setHost(getIP(thing).toString());
url.setPort(80);
url.setPath(path);
if (!thing->paramValue("username").toString().isEmpty()) {
url.setUserName(thing->paramValue("username").toString());
url.setPassword(thing->paramValue("password").toString());
}
url.setQuery(urlQuery);
return QNetworkRequest(url);
}
QVariantMap IntegrationPluginShelly::createRpcRequest(const QString &method)
{
QVariantMap map;

View File

@ -37,6 +37,8 @@
#include <coap/coap.h>
#include <QHostAddress>
#include <QNetworkRequest>
#include <QUrlQuery>
class ZeroConfServiceBrowser;
class PluginTimer;
@ -79,6 +81,7 @@ private:
void handleInputEvent(Thing *thing, const QString &buttonName, const QString &inputEventString, int inputEventCount);
QNetworkRequest createHttpRequest(Thing *thing, const QString &path, const QUrlQuery &urlQuery = QUrlQuery());
QVariantMap createRpcRequest(const QString &method);
private: