New plugin: Shelly
This commit is contained in:
parent
97f507033e
commit
0d4d6cd4f6
@ -36,7 +36,7 @@ Device::DeviceSetupStatus DevicePluginMqttClient::setupDevice(Device *device)
|
||||
{
|
||||
MqttClient *client = nullptr;
|
||||
if (device->deviceClassId() == internalMqttClientDeviceClassId) {
|
||||
client = hardwareManager()->mqttProvider()->createInternalClient(device->id());
|
||||
client = hardwareManager()->mqttProvider()->createInternalClient(device->id().toString());
|
||||
} else if (device->deviceClassId() == mqttClientDeviceClassId){
|
||||
client = new MqttClient("nymea-" + device->id().toString().remove(QRegExp("[{}]")).left(8), this);
|
||||
client->setUsername(device->paramValue(mqttClientDeviceUsernameParamTypeId).toString());
|
||||
|
||||
@ -34,6 +34,7 @@ PLUGIN_DIRS = \
|
||||
osdomotics \
|
||||
philipshue \
|
||||
pushbullet \
|
||||
shelly \
|
||||
systemmonitor \
|
||||
remotessh \
|
||||
senic \
|
||||
|
||||
20
shelly/README.md
Normal file
20
shelly/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Tasmota
|
||||
|
||||
This plugin allows to make use of Sonoff-Tasmota devices via the nymea internal MQTT broker. There is no external MQTT broker needed.
|
||||
|
||||
Note that Sonoff devices must be flashed with the Tasmota sofware and connected to the WiFi network in order to work with this plugin.
|
||||
|
||||
See the [Sonoff-Tasmota wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for a list of all supported devices and instructions on how to
|
||||
install Tasmota on those.
|
||||
|
||||
After flashing Tasmota to a Sonoff device and connecting it to WiFi, it can be added to nymea. The only required
|
||||
thing is the IP address to the device. This plugin will create a new isoloated MQTT channel on the nymea internal
|
||||
MQTT broker and provision login details to the Tasmota device via HTTP. Once that is successful, the Tasmota device
|
||||
will connect to the MQTT broker and appear as connected in nymea.
|
||||
|
||||
## Plugin properties
|
||||
When adding a Tasmota device it will add a new Gateway type device representing the Tasmota device itself. In addition
|
||||
to that a power switch device will appear which can be used to control the switches in the Tasmota device. Upon
|
||||
device setup, the user can optionally select the type of the connected hardware, (e.g. a light) which causes this
|
||||
plugin to create a light device in the system which also controls the switches inside the Tasmota device and nicely
|
||||
integrates with the nymea:ux for the given device type.
|
||||
231
shelly/devicepluginshelly.cpp
Normal file
231
shelly/devicepluginshelly.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "devicepluginshelly.h"
|
||||
#include "plugininfo.h"
|
||||
|
||||
#include <QUrlQuery>
|
||||
#include <QNetworkReply>
|
||||
#include <QHostAddress>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "hardwaremanager.h"
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include "network/mqtt/mqttprovider.h"
|
||||
#include "network/mqtt/mqttchannel.h"
|
||||
|
||||
#include "network/zeroconf/zeroconfservicebrowser.h"
|
||||
#include "platform/platformzeroconfcontroller.h"
|
||||
|
||||
DevicePluginShelly::DevicePluginShelly()
|
||||
{
|
||||
}
|
||||
|
||||
DevicePluginShelly::~DevicePluginShelly()
|
||||
{
|
||||
}
|
||||
|
||||
void DevicePluginShelly::init()
|
||||
{
|
||||
m_zeroconfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_http._tcp");
|
||||
}
|
||||
|
||||
void DevicePluginShelly::discoverDevices(DeviceDiscoveryInfo *info)
|
||||
{
|
||||
foreach (const ZeroConfServiceEntry &entry, m_zeroconfBrowser->serviceEntries()) {
|
||||
// qCDebug(dcShelly()) << "Have entry" << entry;
|
||||
QRegExp namePattern("^shelly[1-2]-[0-9A-Z]+$");
|
||||
if (!entry.name().contains(namePattern)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DeviceDescriptor descriptor(shellyOneDeviceClassId, entry.name(), entry.hostAddress().toString());
|
||||
ParamList params;
|
||||
params << Param(shellyOneDeviceIdParamTypeId, entry.name());
|
||||
descriptor.setParams(params);
|
||||
|
||||
Device *existingDevice = myDevices().findByParams(params);
|
||||
if (existingDevice) {
|
||||
descriptor.setDeviceId(existingDevice->id());
|
||||
}
|
||||
|
||||
info->addDeviceDescriptor(descriptor);
|
||||
qCDebug(dcShelly()) << "Found shelly device!" << entry;
|
||||
|
||||
}
|
||||
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
}
|
||||
|
||||
void DevicePluginShelly::setupDevice(DeviceSetupInfo *info)
|
||||
{
|
||||
Device *device = info->device();
|
||||
|
||||
if (device->deviceClassId() == shellyOneDeviceClassId) {
|
||||
QString shellyId = device->paramValue(shellyOneDeviceIdParamTypeId).toString();
|
||||
ZeroConfServiceEntry zeroConfEntry;
|
||||
foreach (const ZeroConfServiceEntry &entry, m_zeroconfBrowser->serviceEntries()) {
|
||||
if (entry.name() == shellyId) {
|
||||
zeroConfEntry = entry;
|
||||
}
|
||||
}
|
||||
QHostAddress address;
|
||||
pluginStorage()->beginGroup(device->id().toString());
|
||||
if (zeroConfEntry.isValid()) {
|
||||
address = zeroConfEntry.hostAddress().toString();
|
||||
pluginStorage()->setValue("cachedAddress", address.toString());
|
||||
} else {
|
||||
qCWarning(dcShelly()) << "Could not find Shelly device on zeroconf. Trying cached address.";
|
||||
address = pluginStorage()->value("cachedAddress").toString();
|
||||
}
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
if (address.isNull()) {
|
||||
qCWarning(dcShelly()) << "Unable to determine Shelly's network address. Failed to set up device.";
|
||||
info->finish(Device::DeviceErrorHardwareNotAvailable, QT_TR_NOOP("Unable to find the device in the network."));
|
||||
return;
|
||||
}
|
||||
|
||||
MqttChannel *channel = hardwareManager()->mqttProvider()->createChannel(shellyId, QHostAddress(address), {"shellies"});
|
||||
if (!channel) {
|
||||
qCWarning(dcShelly()) << "Failed to create MQTT channel.";
|
||||
return info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error creating MQTT channel. Please check MQTT server settings."));
|
||||
}
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(address.toString());
|
||||
url.setPort(80);
|
||||
url.setPath("/settings");
|
||||
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("mqtt_server", channel->serverAddress().toString() + ":" + QString::number(channel->serverPort()));
|
||||
query.addQueryItem("mqtt_user", channel->username());
|
||||
query.addQueryItem("mqtt_pass", channel->password());
|
||||
query.addQueryItem("mqtt_enable", "true");
|
||||
|
||||
url.setQuery(query);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
qCDebug(dcShelly()) << "Connecting to" << url.toString();
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(info, &DeviceSetupInfo::aborted, channel, [this, channel](){
|
||||
hardwareManager()->mqttProvider()->releaseChannel(channel);
|
||||
});
|
||||
connect(reply, &QNetworkReply::finished, info, [this, info, reply, channel](){
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qCWarning(dcShelly()) << "Error fetching device settings" << reply->error() << reply->errorString();
|
||||
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Error connecting to Shelly device."));
|
||||
hardwareManager()->mqttProvider()->releaseChannel(channel);
|
||||
return;
|
||||
}
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcShelly()) << "Error parsing settings reply" << error.errorString() << "\n" << data;
|
||||
info->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("Unexpected data received from Shelly device."));
|
||||
hardwareManager()->mqttProvider()->releaseChannel(channel);
|
||||
return;
|
||||
}
|
||||
qCDebug(dcShelly()) << "Settings data" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
|
||||
|
||||
m_mqttChannels.insert(info->device(), channel);
|
||||
connect(channel, &MqttChannel::clientConnected, this, &DevicePluginShelly::onClientConnected);
|
||||
connect(channel, &MqttChannel::clientDisconnected, this, &DevicePluginShelly::onClientDisconnected);
|
||||
connect(channel, &MqttChannel::publishReceived, this, &DevicePluginShelly::onPublishReceived);
|
||||
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
qCWarning(dcShelly) << "Unhandled DeviceClass in setupDevice" << device->deviceClassId();
|
||||
}
|
||||
|
||||
void DevicePluginShelly::deviceRemoved(Device *device)
|
||||
{
|
||||
if (m_mqttChannels.contains(device)) {
|
||||
hardwareManager()->mqttProvider()->releaseChannel(m_mqttChannels.take(device));
|
||||
}
|
||||
qCDebug(dcShelly()) << "Device removed" << device->name();
|
||||
}
|
||||
|
||||
void DevicePluginShelly::executeAction(DeviceActionInfo *info)
|
||||
{
|
||||
Device *device = info->device();
|
||||
Action action = info->action();
|
||||
|
||||
if (action.actionTypeId() == shellyOnePowerActionTypeId) {
|
||||
MqttChannel *channel = m_mqttChannels.value(device);
|
||||
QString shellyId = device->paramValue(shellyOneDeviceIdParamTypeId).toString();
|
||||
bool on = action.param(shellyOnePowerActionPowerParamTypeId).value().toBool();
|
||||
channel->publish("shellies/" + shellyId + "/relay/0/command", on ? "on" : "off");
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
qCWarning(dcShelly()) << "Unhandled execute action call for device" << device;
|
||||
}
|
||||
|
||||
void DevicePluginShelly::onClientConnected(MqttChannel *channel)
|
||||
{
|
||||
Device *device = m_mqttChannels.key(channel);
|
||||
if (!device) {
|
||||
qCWarning(dcShelly()) << "Received a client connect for a device we don't know!";
|
||||
return;
|
||||
}
|
||||
device->setStateValue(shellyOneConnectedStateTypeId, true);
|
||||
}
|
||||
|
||||
void DevicePluginShelly::onClientDisconnected(MqttChannel *channel)
|
||||
{
|
||||
Device *device = m_mqttChannels.key(channel);
|
||||
if (!device) {
|
||||
qCWarning(dcShelly()) << "Received a client disconnect for a device we don't know!";
|
||||
return;
|
||||
}
|
||||
device->setStateValue(shellyOneConnectedStateTypeId, false);
|
||||
}
|
||||
|
||||
void DevicePluginShelly::onPublishReceived(MqttChannel *channel, const QString &topic, const QByteArray &payload)
|
||||
{
|
||||
Device *device = m_mqttChannels.key(channel);
|
||||
if (!device) {
|
||||
qCWarning(dcShelly()) << "Received a publish message for a device we don't know!";
|
||||
return;
|
||||
}
|
||||
|
||||
QString shellyId = device->paramValue(shellyOneDeviceIdParamTypeId).toString();
|
||||
if (topic == "shellies/" + shellyId + "/input/0") {
|
||||
// "1" or "0"
|
||||
// Emit event button pressed
|
||||
}
|
||||
|
||||
if (topic == "shellies/" + shellyId + "/relay/0") {
|
||||
bool on = payload == "on";
|
||||
device->setStateValue(shellyOnePowerStateTypeId, on);
|
||||
}
|
||||
qCDebug(dcShelly()) << "Publish received from" << device->name() << topic << payload;
|
||||
|
||||
}
|
||||
59
shelly/devicepluginshelly.h
Normal file
59
shelly/devicepluginshelly.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* nymea is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* nymea is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with nymea. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef DEVICEPLUGINSHELLY_H
|
||||
#define DEVICEPLUGINSHELLY_H
|
||||
|
||||
#include "devices/deviceplugin.h"
|
||||
|
||||
class ZeroConfServiceBrowser;
|
||||
|
||||
class MqttChannel;
|
||||
|
||||
class DevicePluginShelly: public DevicePlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginshelly.json")
|
||||
Q_INTERFACES(DevicePlugin)
|
||||
|
||||
|
||||
public:
|
||||
explicit DevicePluginShelly();
|
||||
~DevicePluginShelly() override;
|
||||
|
||||
void init() override;
|
||||
void discoverDevices(DeviceDiscoveryInfo *info) override;
|
||||
void setupDevice(DeviceSetupInfo *info) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
void executeAction(DeviceActionInfo *info) override;
|
||||
|
||||
private slots:
|
||||
void onClientConnected(MqttChannel* channel);
|
||||
void onClientDisconnected(MqttChannel* channel);
|
||||
void onPublishReceived(MqttChannel* channel, const QString &topic, const QByteArray &payload);
|
||||
|
||||
private:
|
||||
ZeroConfServiceBrowser *m_zeroconfBrowser = nullptr;
|
||||
|
||||
QHash<Device*, MqttChannel*> m_mqttChannels;
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINSHELLY_H
|
||||
57
shelly/devicepluginshelly.json
Normal file
57
shelly/devicepluginshelly.json
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "shelly",
|
||||
"displayName": "Shelly",
|
||||
"id": "6162773b-0435-408c-a4f8-7860d38031a9",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "shelly",
|
||||
"displayName": "Shelly",
|
||||
"id": "d8e45fc2-90af-492e-8305-50baa1ec4c18",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"id": "f810b66a-7177-4397-9771-4229abaabbb6",
|
||||
"name": "shellyOne",
|
||||
"displayName": "Shelly One",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": [ "powerswitch", "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "1d301dc0-5e48-473f-a611-8e407289e545",
|
||||
"name":"id",
|
||||
"displayName": "ID",
|
||||
"type": "QString"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "e5d41e05-2296-457e-97d8-98a5ac0de615",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "0f6df838-7fc4-4fc0-9247-b9b8fa4ec924",
|
||||
"name": "power",
|
||||
"displayName": "Power",
|
||||
"displayNameEvent": "Power changed",
|
||||
"displayNameAction": "Set power",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true
|
||||
}
|
||||
],
|
||||
"eventTypes": [
|
||||
{
|
||||
"id": "172e6aa3-13d3-4c71-8a4d-112605460863",
|
||||
"name": "pressed",
|
||||
"displayName": "Pressed"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
9
shelly/shelly.pro
Normal file
9
shelly/shelly.pro
Normal file
@ -0,0 +1,9 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT += network
|
||||
|
||||
SOURCES += \
|
||||
devicepluginshelly.cpp \
|
||||
|
||||
HEADERS += \
|
||||
devicepluginshelly.h \
|
||||
@ -84,7 +84,7 @@ Device::DeviceSetupStatus DevicePluginTasmota::setupDevice(Device *device)
|
||||
qCWarning(dcTasmota) << "Not a valid IP address given for IP address parameter";
|
||||
return Device::DeviceSetupStatusFailure;
|
||||
}
|
||||
MqttChannel *channel = hardwareManager()->mqttProvider()->createChannel(device->id(), deviceAddress);
|
||||
MqttChannel *channel = hardwareManager()->mqttProvider()->createChannel(device->id().toString().remove(QRegExp("[{}-]")), deviceAddress);
|
||||
if (!channel) {
|
||||
qCWarning(dcTasmota) << "Failed to create MQTT channel.";
|
||||
return Device::DeviceSetupStatusFailure;
|
||||
@ -99,7 +99,7 @@ Device::DeviceSetupStatus DevicePluginTasmota::setupDevice(Device *device)
|
||||
configItems.insert("MqttUser", channel->username());
|
||||
configItems.insert("MqttPassword", channel->password());
|
||||
configItems.insert("Topic", "sonoff");
|
||||
configItems.insert("FullTopic", channel->topicPrefix() + "/%topic%/");
|
||||
configItems.insert("FullTopic", channel->topicPrefixList().first() + "/%topic%/");
|
||||
|
||||
QStringList configList;
|
||||
foreach (const QString &key, configItems.keys()) {
|
||||
@ -222,8 +222,8 @@ Device::DeviceError DevicePluginTasmota::executeAction(Device *device, const Act
|
||||
}
|
||||
ParamTypeId channelParamTypeId = m_channelParamTypeMap.value(device->deviceClassId());
|
||||
ParamTypeId powerActionParamTypeId = ParamTypeId(m_powerStateTypeMap.value(device->deviceClassId()).toString());
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(channelParamTypeId).toString() << (action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(channelParamTypeId).toString().toLower(), action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(channelParamTypeId).toString() << (action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(channelParamTypeId).toString().toLower(), action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
device->setStateValue(m_powerStateTypeMap.value(device->deviceClassId()), action.param(powerActionParamTypeId).value().toBool());
|
||||
return Device::DeviceErrorNoError;
|
||||
}
|
||||
@ -237,20 +237,20 @@ Device::DeviceError DevicePluginTasmota::executeAction(Device *device, const Act
|
||||
ParamTypeId openingChannelParamTypeId = m_openingChannelParamTypeMap.value(device->deviceClassId());
|
||||
ParamTypeId closingChannelParamTypeId = m_closingChannelParamTypeMap.value(device->deviceClassId());
|
||||
if (action.actionTypeId() == tasmotaShutterOpenActionTypeId) {
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "ON";
|
||||
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "ON");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "ON";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "ON");
|
||||
} else if (action.actionTypeId() == tasmotaShutterCloseActionTypeId) {
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "ON";
|
||||
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "ON");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "ON";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "ON");
|
||||
} else { // Stop
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
}
|
||||
return Device::DeviceErrorNoError;
|
||||
}
|
||||
@ -289,7 +289,7 @@ void DevicePluginTasmota::onPublishReceived(MqttChannel *channel, const QString
|
||||
qCDebug(dcTasmota) << "Publish received from Sonoff device:" << topic << payload;
|
||||
Device *dev = m_mqttChannels.key(channel);
|
||||
if (m_ipAddressParamTypeMap.contains(dev->deviceClassId())) {
|
||||
if (topic.startsWith(channel->topicPrefix() + "/sonoff/POWER")) {
|
||||
if (topic.startsWith(channel->topicPrefixList().first() + "/sonoff/POWER")) {
|
||||
QString channelName = topic.split("/").last();
|
||||
|
||||
foreach (Device *child, myDevices()) {
|
||||
@ -308,7 +308,7 @@ void DevicePluginTasmota::onPublishReceived(MqttChannel *channel, const QString
|
||||
}
|
||||
}
|
||||
}
|
||||
if (topic.startsWith(channel->topicPrefix() + "/sonoff/STATE")) {
|
||||
if (topic.startsWith(channel->topicPrefixList().first() + "/sonoff/STATE")) {
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user