mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-17 00:36:35 +02:00
initial setup configuration - not receiving published data
This commit is contained in:
parent
04c8796055
commit
ff03f6d28b
1
Garadget
1
Garadget
@ -1 +0,0 @@
|
||||
Subproject commit 9de1de8da96224f315f858178506dbc09ef1602b
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.14.1, 2021-09-22T16:29:05. -->
|
||||
<!-- Written by QtCreator 4.14.1, 2021-10-18T09:17:58. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
@ -250,7 +250,7 @@
|
||||
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">0</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
|
||||
@ -48,6 +48,41 @@ static QHash<ThingClassId, QHash<QString, StateTypeId>> stateMaps = {
|
||||
{sonoff_basicThingClassId, sonoff_basicPowerStateTypeIds},
|
||||
};
|
||||
|
||||
// bee add static id
|
||||
|
||||
static QHash<QString, StateTypeId> sonoff_basicstateStateTypeIds = {
|
||||
{"closed", sonoff_basicStateStateTypeId},
|
||||
};
|
||||
|
||||
static QHash<ThingClassId,QHash<QString, StateTypeId>> stateStateMAPS = {
|
||||
{sonoff_basicThingClassId, sonoff_basicstateStateTypeIds},
|
||||
};
|
||||
|
||||
static QHash<QString, StateTypeId> sonoff_basicClosingOutputStateTypeIds = {
|
||||
{"CLOSE1", sonoff_basicClosingOutputStateTypeId},
|
||||
};
|
||||
|
||||
static QHash<ThingClassId, QHash<QString, StateTypeId>> stateClosingOutputMaps = {
|
||||
{sonoff_basicThingClassId, sonoff_basicClosingOutputStateTypeIds},
|
||||
};
|
||||
|
||||
static QHash<QString, StateTypeId> sonoff_basicOpeningOutputStateTypeIds = {
|
||||
{"OPEN1", sonoff_basicOpeningOutputStateTypeId},
|
||||
};
|
||||
|
||||
static QHash<ThingClassId, QHash<QString, StateTypeId>> stateOpeningMaps = {
|
||||
{sonoff_basicThingClassId, sonoff_basicOpeningOutputStateTypeIds},
|
||||
};
|
||||
|
||||
static QHash<QString, StateTypeId> sonoff_basicMovingStateTypeIds = {
|
||||
{"STOP1", sonoff_basicMovingStateTypeId},
|
||||
};
|
||||
|
||||
static QHash<ThingClassId, QHash<QString, StateTypeId>> stateMovingMaps = {
|
||||
{sonoff_basicThingClassId, sonoff_basicMovingStateTypeIds},
|
||||
};
|
||||
|
||||
|
||||
IntegrationPluginGaradget::IntegrationPluginGaradget()
|
||||
{
|
||||
// Helper maps for parent devices (aka sonoff_*)
|
||||
@ -58,6 +93,19 @@ IntegrationPluginGaradget::IntegrationPluginGaradget()
|
||||
m_connectedStateTypeMap[sonoff_basicThingClassId] = sonoff_basicConnectedStateTypeId;
|
||||
|
||||
m_signalStrengthStateTypeMap[sonoff_basicThingClassId] = sonoff_basicSignalStrengthStateTypeId;
|
||||
|
||||
// bee adders for extendedgaragestate
|
||||
|
||||
m_stateStateTypeMap[sonoff_basicThingClassId] = sonoff_basicStateStateTypeId;
|
||||
|
||||
m_movingStateTypeMap[sonoff_basicThingClassId] = sonoff_basicMovingStateTypeId;
|
||||
|
||||
m_percentageStateTypeMap[sonoff_basicThingClassId] = sonoff_basicPercentageStateTypeId;
|
||||
|
||||
m_closingOutputStateTypeMap[sonoff_basicThingClassId] = sonoff_basicClosingOutputStateTypeId;
|
||||
|
||||
m_openingOutputStateTypeMap[sonoff_basicThingClassId] = sonoff_basicOpeningOutputStateTypeId;
|
||||
|
||||
}
|
||||
|
||||
IntegrationPluginGaradget::~IntegrationPluginGaradget()
|
||||
@ -73,29 +121,64 @@ void IntegrationPluginGaradget::setupThing(ThingSetupInfo *info)
|
||||
Thing *thing = info->thing();
|
||||
|
||||
if (m_ipAddressParamTypeMap.contains(thing->thingClassId())) {
|
||||
ParamTypeId ipAddressParamTypeId = m_ipAddressParamTypeMap.value(thing->thingClassId());
|
||||
// ParamTypeId ipAddressParamTypeId = m_ipAddressParamTypeMap.value(thing->thingClassId());
|
||||
|
||||
QHostAddress deviceAddress = QHostAddress(thing->paramValue(ipAddressParamTypeId).toString());
|
||||
// QHostAddress deviceAddress = QHostAddress(thing->paramValue(ipAddressParamTypeId).toString());
|
||||
// ipaddress is defined here but not sure how to get rid of and still have the mqtt channel. Garadget only works with the broker.
|
||||
QHostAddress deviceAddress = QHostAddress("192.168.1.174");
|
||||
if (deviceAddress.isNull()) {
|
||||
qCWarning(dcGaradget) << "Not a valid IP address given for IP address parameter";
|
||||
//: Error setting up thing
|
||||
return info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The given IP address is not valid."));
|
||||
}
|
||||
MqttChannel *channel = hardwareManager()->mqttProvider()->createChannel(thing->id().toString().remove(QRegExp("[{}-]")), deviceAddress );
|
||||
// MqttChannel *channel = hardwareManager()->mqttProvider()->createChannel(thing->id().toString().remove(QRegExp("[{}-]")), deviceAddress );
|
||||
MqttChannel *channel = hardwareManager()->mqttProvider()->createChannel("garage", deviceAddress );
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget) << "Failed to create MQTT channel.";
|
||||
//: Error setting up thing
|
||||
return info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error creating MQTT channel. Please check MQTT server settings."));
|
||||
}
|
||||
// ipaddress is defined here but not sure how to get rid of and still have the mqtt channel. Garadget only works with the broker.
|
||||
|
||||
qCDebug(dcGaradget) << "BEE initial setup instructions:" << deviceAddress.toString() << channel;
|
||||
qCDebug(dcGaradget) << "initial setup instructions:" << deviceAddress.toString() << channel;
|
||||
/*
|
||||
QUrl url(QString("http://%1/cm").arg(deviceAddress.toString()));
|
||||
QUrlQuery query;
|
||||
QMap<QString, QString> configItems;
|
||||
configItems.insert("MqttHost", channel->serverAddress().toString());
|
||||
configItems.insert("MqttPort", QString::number(channel->serverPort()));
|
||||
configItems.insert("MqttClient", channel->clientId());
|
||||
configItems.insert("MqttUser", channel->username());
|
||||
configItems.insert("MqttPassword", channel->password());
|
||||
configItems.insert("Topic", "sonoff");
|
||||
configItems.insert("FullTopic", channel->topicPrefixList().first() + "/%topic%/");
|
||||
|
||||
QStringList configList;
|
||||
foreach (const QString &key, configItems.keys()) {
|
||||
configList << key + ' ' + configItems.value(key);
|
||||
}
|
||||
QString fullCommand = "Backlog " + configList.join(';');
|
||||
query.addQueryItem("cmnd", fullCommand.toUtf8().toPercentEncoding());
|
||||
|
||||
url.setQuery(query);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [this, info, channel, reply](){
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qCDebug(dcTasmota) << "Sonoff thing setup call failed:" << reply->error() << reply->errorString() << reply->readAll();
|
||||
hardwareManager()->mqttProvider()->releaseChannel(channel);
|
||||
//: Error setting up thing
|
||||
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("Could not connect to Tasmota device."));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
//BEE mod
|
||||
|
||||
m_mqttChannels.insert(info->thing(), channel);
|
||||
connect(channel, &MqttChannel::clientConnected, this, &IntegrationPluginGaradget::onClientConnected);
|
||||
connect(channel, &MqttChannel::clientDisconnected, this, &IntegrationPluginGaradget::onClientDisconnected);
|
||||
connect(channel, &MqttChannel::publishReceived, this, &IntegrationPluginGaradget::onPublishReceived);
|
||||
|
||||
qCDebug(dcGaradget) << "Garadget setup complete";
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
foreach (Thing *child, myThings()) {
|
||||
@ -104,22 +187,21 @@ void IntegrationPluginGaradget::setupThing(ThingSetupInfo *info)
|
||||
return;
|
||||
}
|
||||
}
|
||||
// });
|
||||
|
||||
// insert to reprogram client Garadget to new device/topic name
|
||||
QJsonObject beeobj;
|
||||
beeobj.insert("nme", QString(channel->topicPrefixList().first()));
|
||||
QJsonDocument beedoc(beeobj);
|
||||
QByteArray beedata = beedoc.toJson(QJsonDocument::Compact);
|
||||
QString jsonString(beedata);
|
||||
qCDebug(dcGaradget) << "Publishing:" << "garadget/garage/set-conf " << beedata;
|
||||
// next line will not publish to the correct device as topic is 32 characters long and garadget only allows 30 characters.
|
||||
channel->publish("garadget/garaged/set-config", beedata);
|
||||
channel->publish("garadget/garage/command", "get-config");
|
||||
// need to develop test for correct modification of nme
|
||||
QJsonObject garadgetobj;
|
||||
garadgetobj.insert("nme", QString(channel->topicPrefixList().first()));
|
||||
QJsonDocument garadgetdoc(garadgetobj);
|
||||
QByteArray garadgetdata = garadgetdoc.toJson(QJsonDocument::Compact);
|
||||
QString jsonString(garadgetdata);
|
||||
qCDebug(dcGaradget) << "Publishing:" << "garadget/" + channel->topicPrefixList().first() << garadgetdata;
|
||||
channel->publish("garadget/" + channel->topicPrefixList().first() + "/set-config", garadgetdata);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_connectedStateTypeMap.contains(thing->thingClassId())) {
|
||||
qCDebug(dcGaradget) << "entered connectedStateTypeMap function";
|
||||
Thing* parentDevice = myThings().findById(thing->parentId());
|
||||
StateTypeId connectedStateTypeId = m_connectedStateTypeMap.value(thing->thingClassId());
|
||||
thing->setStateValue(m_connectedStateTypeMap.value(thing->thingClassId()), parentDevice->stateValue(connectedStateTypeId));
|
||||
@ -135,6 +217,16 @@ void IntegrationPluginGaradget::thingRemoved(Thing *thing)
|
||||
if (m_mqttChannels.contains(thing)) {
|
||||
qCDebug(dcGaradget) << "Releasing MQTT channel";
|
||||
MqttChannel* channel = m_mqttChannels.take(thing);
|
||||
|
||||
// insert to reprogram client Garadget to new device/topic name
|
||||
QJsonObject garadgetobj;
|
||||
garadgetobj.insert("nme","garage" );
|
||||
QJsonDocument garadgetdoc(garadgetobj);
|
||||
QByteArray garadgetdata = garadgetdoc.toJson(QJsonDocument::Compact);
|
||||
QString jsonString(garadgetdata);
|
||||
qCDebug(dcGaradget) << "garadget/" + QString(channel->topicPrefixList().first()) + "/set-config" << " topic = " << garadgetdata;
|
||||
channel->publish("garadget/" + QString(channel->topicPrefixList().first()) + "/set-config", garadgetdata);
|
||||
|
||||
hardwareManager()->mqttProvider()->releaseChannel(channel);
|
||||
}
|
||||
}
|
||||
@ -144,38 +236,10 @@ void IntegrationPluginGaradget::executeAction(ThingActionInfo *info)
|
||||
Thing *thing = info->thing();
|
||||
Action action = info->action();
|
||||
|
||||
if (thing->thingClassId() == sonoff_basicThingClassId) {
|
||||
MqttChannel *channel = m_mqttChannels.value(thing);
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget()) << "No MQTT channel for this thing.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
QString channelName = stateMaps.value(thing->thingClassId()).key(action.actionTypeId());
|
||||
QByteArray payload = action.paramValue(action.actionTypeId()).toBool() ? "ON" : "OFF";
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + channelName << payload;
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + channelName, payload);
|
||||
thing->setStateValue(action.actionTypeId(), action.paramValue(action.actionTypeId()));
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
qCDebug(dcGaradget) << "executeAction function" << (thing->thingClassId());
|
||||
|
||||
// Legacy (deprecated) connected devices
|
||||
if (m_powerStateTypeMap.contains(thing->thingClassId())) {
|
||||
Thing *parentDev = myThings().findById(thing->parentId());
|
||||
MqttChannel *channel = m_mqttChannels.value(parentDev);
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget()) << "No mqtt channel for this thing.";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
ParamTypeId channelParamTypeId = m_channelParamTypeMap.value(thing->thingClassId());
|
||||
ParamTypeId powerActionParamTypeId = ParamTypeId(m_powerStateTypeMap.value(thing->thingClassId()).toString());
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(channelParamTypeId).toString() << (action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(channelParamTypeId).toString().toLower(), action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
thing->setStateValue(m_powerStateTypeMap.value(thing->thingClassId()), action.param(powerActionParamTypeId).value().toBool());
|
||||
return info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
if (m_closableStopActionTypeMap.contains(thing->thingClassId())) {
|
||||
qCDebug(dcGaradget) << "Publishing: m_closableStopActionTypeMap" << "how did I get here?";
|
||||
Thing *parentDev = myThings().findById(thing->parentId());
|
||||
MqttChannel *channel = m_mqttChannels.value(parentDev);
|
||||
if (!channel) {
|
||||
@ -202,7 +266,57 @@ void IntegrationPluginGaradget::executeAction(ThingActionInfo *info)
|
||||
}
|
||||
return info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
qCWarning(dcGaradget) << "Unhandled execute action call for devie" << thing;
|
||||
|
||||
if (thing->thingClassId() == sonoff_basicThingClassId) {
|
||||
MqttChannel *channel = m_mqttChannels.value(thing);
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget()) << "No MQTT channel for this thing.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
qCDebug(dcGaradget) << "entered sonoff_basicThingClassId function" << (thing->thingClassId());
|
||||
// QString channelName = stateMaps.value(thing->thingClassId()).key(action.actionTypeId());
|
||||
// QByteArray payload = action.paramValue(action.actionTypeId()).toBool() ? "ON" : "OFF";
|
||||
// qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + channelName << payload;
|
||||
// channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + channelName, payload);
|
||||
// qCDebug(dcGaradget) << "Publishing:" << "garadget/" + channel->topicPrefixList().first() + "/command" << payload;
|
||||
// channel->publish("garadget/" + channel->topicPrefixList().first() + "/command", payload);
|
||||
// thing->setStateValue(action.actionTypeId(), action.paramValue(action.actionTypeId()));
|
||||
// info->finish(Thing::ThingErrorNoError);
|
||||
// return;
|
||||
|
||||
if (action.actionTypeId() == sonoff_basicOpenActionTypeId) {
|
||||
qCDebug(dcGaradget) << "Publishing:" << "garadget/" + channel->topicPrefixList().first() + "/command" << "open";
|
||||
channel->publish("garadget/" + channel->topicPrefixList().first() + "/command", "open");
|
||||
// qCDebug(dcGaradget) << "OpenAction stuff:" << action.actionTypeId() << action.paramValue(action.actionTypeId());
|
||||
// qCDebug(dcGaradget) << "OpenMapAction stuff:" << action.paramValue(action.actionTypeId()) << stateOpeningMaps.value(thing->thingClassId()).key(action.actionTypeId());
|
||||
// thing->setStateValue(action.actionTypeId(), action.paramValue(action.actionTypeId()));
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
if (action.actionTypeId() == sonoff_basicCloseActionTypeId) {
|
||||
qCDebug(dcGaradget) << "Publishing:" << "garadget/" + channel->topicPrefixList().first() + "/command" << "close";
|
||||
channel->publish("garadget/" + channel->topicPrefixList().first() + "/command", "close");
|
||||
// qCDebug(dcGaradget) << "CloseAction stuff:" << thing << thing->thingClassId() << thing->thingClassId();
|
||||
// qCDebug(dcGaradget) << "CloseAction newparameter" << thing->paramValue(stateStateMAPS) ;
|
||||
// thing->setStateValue(stateStateMAPS.value(thing->thingClassId()).key(action.actionTypeId()),"closed");
|
||||
// qCDebug(dcGaradget) << "CloseMapAction stuff:" << stateStateMAPS.value(thing->thingClassId()).key(action.actionTypeId());
|
||||
// thing->setStateValue(action.actionTypeId(), action.paramValue(action.actionTypeId()));
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
if (action.actionTypeId() == sonoff_basicStopActionTypeId) {
|
||||
qCDebug(dcGaradget) << "Publishing:" << "garadget/" + channel->topicPrefixList().first() + "/command" << "stop";
|
||||
channel->publish("garadget/" + channel->topicPrefixList().first() + "/command", "stop");
|
||||
// qCDebug(dcGaradget) << "StopAction stuff:" << action.actionTypeId() << action.paramValue(action.actionTypeId());
|
||||
// qCDebug(dcGaradget) << "StopMapAction stuff:" << action.paramValue(action.actionTypeId()) << stateMovingMaps.value(thing->thingClassId()).key(action.actionTypeId());
|
||||
// thing->setStateValue(action.actionTypeId(), action.paramValue(action.actionTypeId()));
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
qCWarning(dcGaradget) << "Unhandled execute action call for device" << thing;
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::onClientConnected(MqttChannel *channel)
|
||||
@ -274,5 +388,19 @@ void IntegrationPluginGaradget::onPublishReceived(MqttChannel *channel, const QS
|
||||
child->setStateValue(m_signalStrengthStateTypeMap.value(child->thingClassId()), dataMap.value("Wifi").toMap().value("RSSI").toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (topic.startsWith("garadget/" + channel->topicPrefixList().first() + "/status")) {
|
||||
qCDebug(dcGaradget) << "Garadget status received " << payload;
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcGaradget) << "Cannot parse JSON from Garadget device" << error.errorString();
|
||||
return;
|
||||
}
|
||||
QVariantMap dataMap = jsonDoc.toVariant().toMap();
|
||||
// thing->setStateValue(m_signalStrengthStateTypeMap.value(thing->thingClassId()), dataMap.value("Gstatus").toMap().value("status"));
|
||||
thing->setStateValue(m_stateStateTypeMap.value(thing->thingClassId()), dataMap.value("status").toMap().value("state"));
|
||||
|
||||
qCDebug(dcGaradget) << "Datamap " << m_signalStrengthStateTypeMap.value(thing->thingClassId());
|
||||
qCDebug(dcGaradget) << "Garadget status decode " << jsonDoc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,301 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project 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 project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "integrationpluginGaradget.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"
|
||||
|
||||
static QHash<QString, StateTypeId> sonoff_basicPowerStateTypeIds = {
|
||||
{"POWER1", sonoff_basicPowerStateTypeId},
|
||||
};
|
||||
static QHash<ThingClassId, QHash<QString, StateTypeId>> stateMaps = {
|
||||
{sonoff_basicThingClassId, sonoff_basicPowerStateTypeIds},
|
||||
};
|
||||
|
||||
IntegrationPluginGaradget::IntegrationPluginGaradget()
|
||||
{
|
||||
// Helper maps for parent devices (aka sonoff_*)
|
||||
m_ipAddressParamTypeMap[sonoff_basicThingClassId] = sonoff_basicThingIpAddressParamTypeId;
|
||||
|
||||
|
||||
// Helper maps for all devices
|
||||
m_connectedStateTypeMap[sonoff_basicThingClassId] = sonoff_basicConnectedStateTypeId;
|
||||
|
||||
m_signalStrengthStateTypeMap[sonoff_basicThingClassId] = sonoff_basicSignalStrengthStateTypeId;
|
||||
}
|
||||
|
||||
IntegrationPluginGaradget::~IntegrationPluginGaradget()
|
||||
{
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::init()
|
||||
{
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
|
||||
if (m_ipAddressParamTypeMap.contains(thing->thingClassId())) {
|
||||
ParamTypeId ipAddressParamTypeId = m_ipAddressParamTypeMap.value(thing->thingClassId());
|
||||
|
||||
QHostAddress deviceAddress = QHostAddress(thing->paramValue(ipAddressParamTypeId).toString());
|
||||
if (deviceAddress.isNull()) {
|
||||
qCWarning(dcGaradget) << "Not a valid IP address given for IP address parameter";
|
||||
//: Error setting up thing
|
||||
return info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The given IP address is not valid."));
|
||||
}
|
||||
|
||||
MqttChannel *channel = hardwareManager()->mqttProvider()->createChannel(thing->id().toString().remove(QRegExp("[{}-]")), deviceAddress );
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget) << "Failed to create MQTT channel.";
|
||||
//: Error setting up thing
|
||||
return info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error creating MQTT channel. Please check MQTT server settings."));
|
||||
}
|
||||
// ipaddress is defined here but not sure how to get rid of and still have the mqtt channel. Garadget only works with the broker.
|
||||
|
||||
qCDebug(dcGaradget) << "BEE initial setup instructions:" << deviceAddress.toString() << channel;
|
||||
|
||||
m_mqttChannels.insert(info->thing(), channel);
|
||||
connect(channel, &MqttChannel::clientConnected, this, &IntegrationPluginGaradget::onClientConnected);
|
||||
connect(channel, &MqttChannel::clientDisconnected, this, &IntegrationPluginGaradget::onClientDisconnected);
|
||||
connect(channel, &MqttChannel::publishReceived, this, &IntegrationPluginGaradget::onPublishReceived);
|
||||
|
||||
qCDebug(dcGaradget) << "Garadget setup complete";
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
foreach (Thing *child, myThings()) {
|
||||
if (child->parentId() == info->thing()->id()) {
|
||||
// Already have child devices... We're done here
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// insert to reprogram client Garadget to new device/topic name
|
||||
QJsonObject beeobj;
|
||||
beeobj.insert("nme", QString(channel->topicPrefixList().first()));
|
||||
QJsonDocument beedoc(beeobj);
|
||||
QByteArray beedata = beedoc.toJson(QJsonDocument::Compact);
|
||||
QString jsonString(beedata);
|
||||
qCDebug(dcGaradget) << "Publishing:" << "garadget/garage/set-conf " << beedata;
|
||||
// next line will not publish to the correct device as topic is 32 characters long and garadget only allows 30 characters.
|
||||
channel->publish("garadget/garaged/set-config", beedata);
|
||||
channel->publish("garadget/garage/command", "get-config");
|
||||
// need to develop test for correct modification of nme
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_connectedStateTypeMap.contains(thing->thingClassId())) {
|
||||
Thing* parentDevice = myThings().findById(thing->parentId());
|
||||
StateTypeId connectedStateTypeId = m_connectedStateTypeMap.value(thing->thingClassId());
|
||||
thing->setStateValue(m_connectedStateTypeMap.value(thing->thingClassId()), parentDevice->stateValue(connectedStateTypeId));
|
||||
return info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
|
||||
qCWarning(dcGaradget) << "Unhandled ThingClass in setupDevice" << thing->thingClassId();
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::onPublishReceivedSetup(MqttChannel *channel, const QString &topic, const QByteArray &payload)
|
||||
{
|
||||
qCDebug(dcGaradget) << "Publish received from garadget/garage thing:" << topic << qUtf8Printable(payload);
|
||||
Thing *thing = m_mqttChannels.key(channel);
|
||||
if (topic.startsWith( "garadget/garage/config")) {
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||
qCWarning(dcGaradget) << "BEE on receive QJsonDocument: " << jsonDoc;
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcGaradget) << "Cannot parse JSON from Garadget device" << error.errorString();
|
||||
return;
|
||||
}
|
||||
QVariantMap dataMap = jsonDoc.toVariant().toMap();
|
||||
thing->setStateValue(m_signalStrengthStateTypeMap.value(thing->thingClassId()), dataMap.value("Wifi").toMap().value("RSSI").toInt());
|
||||
|
||||
}
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||
qCWarning(dcGaradget) << "BEE on receive ending QJsonDocument: " << jsonDoc;
|
||||
}
|
||||
|
||||
|
||||
void IntegrationPluginGaradget::thingRemoved(Thing *thing)
|
||||
{
|
||||
qCDebug(dcGaradget) << "Device removed" << thing->name();
|
||||
if (m_mqttChannels.contains(thing)) {
|
||||
qCDebug(dcGaradget) << "Releasing MQTT channel";
|
||||
MqttChannel* channel = m_mqttChannels.take(thing);
|
||||
hardwareManager()->mqttProvider()->releaseChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::executeAction(ThingActionInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
Action action = info->action();
|
||||
|
||||
if (thing->thingClassId() == sonoff_basicThingClassId) {
|
||||
MqttChannel *channel = m_mqttChannels.value(thing);
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget()) << "No MQTT channel for this thing.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
QString channelName = stateMaps.value(thing->thingClassId()).key(action.actionTypeId());
|
||||
QByteArray payload = action.paramValue(action.actionTypeId()).toBool() ? "ON" : "OFF";
|
||||
qCDebug(dcGaradget) << "Publishing:" << "garadget/" + channel->topicPrefixList().first() + "/command " + channelName << payload;
|
||||
channel->publish("garadget/" + channel->topicPrefixList().first() + "/command " + channelName, payload);
|
||||
thing->setStateValue(action.actionTypeId(), action.paramValue(action.actionTypeId()));
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
// Legacy (deprecated) connected devices
|
||||
if (m_powerStateTypeMap.contains(thing->thingClassId())) {
|
||||
Thing *parentDev = myThings().findById(thing->parentId());
|
||||
MqttChannel *channel = m_mqttChannels.value(parentDev);
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget()) << "No mqtt channel for this thing.";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
ParamTypeId channelParamTypeId = m_channelParamTypeMap.value(thing->thingClassId());
|
||||
ParamTypeId powerActionParamTypeId = ParamTypeId(m_powerStateTypeMap.value(thing->thingClassId()).toString());
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(channelParamTypeId).toString() << (action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(channelParamTypeId).toString().toLower(), action.param(powerActionParamTypeId).value().toBool() ? "ON" : "OFF");
|
||||
thing->setStateValue(m_powerStateTypeMap.value(thing->thingClassId()), action.param(powerActionParamTypeId).value().toBool());
|
||||
return info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
if (m_closableStopActionTypeMap.contains(thing->thingClassId())) {
|
||||
Thing *parentDev = myThings().findById(thing->parentId());
|
||||
MqttChannel *channel = m_mqttChannels.value(parentDev);
|
||||
if (!channel) {
|
||||
qCWarning(dcGaradget()) << "No mqtt channel for this thing.";
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
ParamTypeId openingChannelParamTypeId = m_openingChannelParamTypeMap.value(thing->thingClassId());
|
||||
ParamTypeId closingChannelParamTypeId = m_closingChannelParamTypeMap.value(thing->thingClassId());
|
||||
if (action.actionTypeId() == m_closableOpenActionTypeMap.value(thing->thingClassId())) {
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(openingChannelParamTypeId).toString() << "ON";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(openingChannelParamTypeId).toString().toLower(), "ON");
|
||||
} else if (action.actionTypeId() == m_closableCloseActionTypeMap.value(thing->thingClassId())) {
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(closingChannelParamTypeId).toString() << "ON";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(closingChannelParamTypeId).toString().toLower(), "ON");
|
||||
} else { // Stop
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
qCDebug(dcGaradget) << "Publishing:" << channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||
channel->publish(channel->topicPrefixList().first() + "/sonoff/cmnd/" + thing->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||
}
|
||||
return info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
qCWarning(dcGaradget) << "Unhandled execute action call for devie" << thing;
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::onClientConnected(MqttChannel *channel)
|
||||
{
|
||||
qCDebug(dcGaradget) << "Sonoff thing connected!";
|
||||
Thing *dev = m_mqttChannels.key(channel);
|
||||
dev->setStateValue(m_connectedStateTypeMap.value(dev->thingClassId()), true);
|
||||
|
||||
foreach (Thing *child, myThings()) {
|
||||
if (child->parentId() == dev->id()) {
|
||||
child->setStateValue(m_connectedStateTypeMap.value(child->thingClassId()), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::onClientDisconnected(MqttChannel *channel)
|
||||
{
|
||||
qCDebug(dcGaradget) << "Sonoff thing disconnected!";
|
||||
Thing *dev = m_mqttChannels.key(channel);
|
||||
dev->setStateValue(m_connectedStateTypeMap.value(dev->thingClassId()), false);
|
||||
|
||||
foreach (Thing *child, myThings()) {
|
||||
if (child->parentId() == dev->id()) {
|
||||
child->setStateValue(m_connectedStateTypeMap.value(child->thingClassId()), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginGaradget::onPublishReceived(MqttChannel *channel, const QString &topic, const QByteArray &payload)
|
||||
{
|
||||
qCDebug(dcGaradget) << "Publish received from Sonoff thing:" << topic << qUtf8Printable(payload);
|
||||
Thing *thing = m_mqttChannels.key(channel);
|
||||
if (topic.startsWith(channel->topicPrefixList().first() + "/sonoff/POWER")) {
|
||||
QString channelName = topic.split("/").last();
|
||||
|
||||
thing->setStateValue(stateMaps.value(thing->thingClassId()).value(channelName), payload == "ON");
|
||||
|
||||
// Legacy (deprecated) connected things via params
|
||||
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
if (child->paramValue(m_channelParamTypeMap.value(child->thingClassId())).toString() != channelName) {
|
||||
continue;
|
||||
}
|
||||
if (m_powerStateTypeMap.contains(child->thingClassId())) {
|
||||
child->setStateValue(m_powerStateTypeMap.value(child->thingClassId()), payload == "ON");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (topic.startsWith(channel->topicPrefixList().first() + "/sonoff/STATE")) {
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcGaradget) << "Cannot parse JSON from Garadget device" << error.errorString();
|
||||
return;
|
||||
}
|
||||
QVariantMap dataMap = jsonDoc.toVariant().toMap();
|
||||
thing->setStateValue(m_signalStrengthStateTypeMap.value(thing->thingClassId()), dataMap.value("Wifi").toMap().value("RSSI").toInt());
|
||||
|
||||
if (m_brightnessStateTypeMap.contains(thing->thingClassId())) {
|
||||
thing->setStateValue(m_brightnessStateTypeMap.value(thing->thingClassId()), dataMap.value("Dimmer").toInt());
|
||||
}
|
||||
|
||||
// Legacy (deprecated) connected things by params
|
||||
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
if (m_powerStateTypeMap.contains(child->thingClassId())) {
|
||||
QString childChannel = child->paramValue(m_channelParamTypeMap.value(child->thingClassId())).toString();
|
||||
QString valueString = jsonDoc.toVariant().toMap().value(childChannel).toString();
|
||||
child->setStateValue(m_powerStateTypeMap.value(child->thingClassId()), valueString == "ON");
|
||||
}
|
||||
child->setStateValue(m_signalStrengthStateTypeMap.value(child->thingClassId()), dataMap.value("Wifi").toMap().value("RSSI").toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +63,19 @@ private:
|
||||
// Helpers for parent devices (the ones starting with sonoff)
|
||||
QHash<ThingClassId, ParamTypeId> m_ipAddressParamTypeMap;
|
||||
QHash<ThingClassId, QList<ParamTypeId> > m_attachedDeviceParamTypeIdMap;
|
||||
|
||||
// helpers from bee
|
||||
QHash<ThingClassId, ParamTypeId> m_stateParamTypeMap;
|
||||
QHash<ThingClassId, ParamTypeId> m_movingParamTypeMap;
|
||||
QHash<ThingClassId, ParamTypeId> m_percentageParamTypeMap;
|
||||
QHash<ThingClassId, ParamTypeId> m_closingOutputParamTypeMap;
|
||||
QHash<ThingClassId, ParamTypeId> m_openingOutputParamTypeMap;
|
||||
|
||||
QHash<ThingClassId, StateTypeId> m_stateStateTypeMap;
|
||||
QHash<ThingClassId, StateTypeId> m_movingStateTypeMap;
|
||||
QHash<ThingClassId, StateTypeId> m_percentageStateTypeMap;
|
||||
QHash<ThingClassId, StateTypeId> m_closingOutputStateTypeMap;
|
||||
QHash<ThingClassId, StateTypeId> m_openingOutputStateTypeMap;
|
||||
|
||||
// Helpers for child devices (virtual ones, starting with Garadget)
|
||||
QHash<ThingClassId, ParamTypeId> m_channelParamTypeMap;
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"id": "e808b8ae-7608-41ce-8444-892f0648a4d3",
|
||||
"setupMethod": "JustAdd",
|
||||
"createMethods": ["User"],
|
||||
"interfaces": [ ],
|
||||
"interfaces": ["extendedstatefulgaragedoor"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "54a11a17-fc37-4316-891f-001c55e38220",
|
||||
@ -24,6 +24,16 @@
|
||||
}
|
||||
|
||||
],
|
||||
"settingsTypes": [
|
||||
{
|
||||
"id": "cc818e83-40d4-4dc3-850e-acb25477aeae",
|
||||
"name": "openingDuration",
|
||||
"displayName": "Opening duration [ms]",
|
||||
"type": "uint",
|
||||
"minValue": 1000,
|
||||
"defaultValue": 5000
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "a3d7e6eb-82d0-47ee-b95f-4dde931eb7e2",
|
||||
@ -45,6 +55,65 @@
|
||||
"maxValue": 100,
|
||||
"defaultValue": -1
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"id": "174509b5-fc3e-4f03-8c93-8e044f0a2ce0" ,
|
||||
"name": "state",
|
||||
"displayName": "State",
|
||||
"displayNameEvent": "State changed",
|
||||
"displayNameAction": "Set state",
|
||||
"type": "QString",
|
||||
"possibleValues": ["open", "closed", "opening", "closing", "intermediate"],
|
||||
"defaultValue": "closed",
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "d3f711a1-9c79-459d-b697-d427280d9be8" ,
|
||||
"name": "moving",
|
||||
"displayName": "Moving",
|
||||
"displayNameEvent": "Moving changed",
|
||||
"displayNameAction": "Set moving",
|
||||
"type": "bool",
|
||||
"writable": true,
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "b2bdaa74-a6e1-4208-9094-a38bae3f3672" ,
|
||||
"name": "percentage",
|
||||
"displayName": "Open position",
|
||||
"displayNameEvent": "Openposition changed",
|
||||
"displayNameAction": "Set percentage",
|
||||
"type": "int",
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"defaultValue": 100,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "1aadbcf4-314b-409b-9223-55d433433edf" ,
|
||||
"name": "openingOutput",
|
||||
"displayName": "Openingoutput",
|
||||
"displayNameEvent": "Openingoutput changed",
|
||||
"displayNameAction": "Set openingOutput",
|
||||
"type": "bool",
|
||||
"writable": true,
|
||||
"defaultValue": false,
|
||||
"ioType": "digitalInput"
|
||||
},
|
||||
{
|
||||
"id": "e6b564ff-094d-45ba-a4db-f64a8bedf258" ,
|
||||
"name": "closingOutput",
|
||||
"displayName": "Closingoutput",
|
||||
"displayNameEvent": "Closingoutput changed",
|
||||
"displayNameAction": "Set closingOutput",
|
||||
"type": "bool",
|
||||
"writable": true,
|
||||
"defaultValue": false,
|
||||
"ioType": "digitalInput"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"id": "481a7cf8-418b-4774-8fd4-32693ab52299",
|
||||
"name": "power",
|
||||
@ -62,6 +131,22 @@
|
||||
],
|
||||
"actionTypes": [
|
||||
|
||||
{
|
||||
"id": "ae3b1c67-7219-4768-a1c7-55c3b9a610cb" ,
|
||||
"name": "open",
|
||||
"displayName": "Open"
|
||||
},
|
||||
{
|
||||
"id": "56a9e131-b65e-4622-9a9b-f5b42d0021ef" ,
|
||||
"name": "close",
|
||||
"displayName": "Close"
|
||||
},
|
||||
{
|
||||
"id": "12ea84c1-0650-4ac1-a02c-de95965def92" ,
|
||||
"name": "stop",
|
||||
"displayName": "Stop"
|
||||
}
|
||||
|
||||
],
|
||||
"eventTypes": [
|
||||
|
||||
|
||||
@ -31,6 +31,33 @@
|
||||
<extracomment>The name of the EventType ({481a7cf8-418b-4774-8fd4-32693ab52299}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>State changed</source>
|
||||
<extracomment>The name of the EventType ({174509b5-fc3e-4f03-8c93-8e044f0a2ce0}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Moving changed</source>
|
||||
<extracomment>The name of the EventType ({d3f711a1-9c79-459d-b697-d427280d9be8}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Openposition changed</source>
|
||||
<extracomment>The name of the EventType ({b2bdaa74-a6e1-4208-9094-a38bae3f3672}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Openingoutput changed</source>
|
||||
<extracomment>The name of the EventType ({1aadbcf4-314b-409b-9223-55d433433edf}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Closingoutput changed</source>
|
||||
<extracomment>The name of the EventType ({e6b564ff-094d-45ba-a4db-f64a8bedf258}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Power</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, ActionType: power, ID: {481a7cf8-418b-4774-8fd4-32693ab52299})
|
||||
@ -42,16 +69,141 @@ The name of the StateType ({481a7cf8-418b-4774-8fd4-32693ab52299}) of ThingClass
|
||||
The name of the ActionType ({481a7cf8-418b-4774-8fd4-32693ab52299}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
|
||||
|
||||
<message>
|
||||
<source>State</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, ActionType: state, ID: {174509b5-fc3e-4f03-8c93-8e044f0a2ce0})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: sonoff_basic, EventType: state, ID: {174509b5-fc3e-4f03-8c93-8e044f0a2ce0})
|
||||
----------
|
||||
The name of the StateType ({174509b5-fc3e-4f03-8c93-8e044f0a2ce0}) of ThingClass sonoff_basic
|
||||
----------
|
||||
The name of the ActionType ({174509b5-fc3e-4f03-8c93-8e044f0a2ce0}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Moving</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, ActionType: moving, ID: {d3f711a1-9c79-459d-b697-d427280d9be8})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: sonoff_basic, EventType: moving, ID: {d3f711a1-9c79-459d-b697-d427280d9be8})
|
||||
----------
|
||||
The name of the StateType ({d3f711a1-9c79-459d-b697-d427280d9be8}) of ThingClass sonoff_basic
|
||||
----------
|
||||
The name of the ActionType ({d3f711a1-9c79-459d-b697-d427280d9be8}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>"Open Position"</source></source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, ActionType: percentage, ID: {b2bdaa74-a6e1-4208-9094-a38bae3f3672})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: sonoff_basic, EventType: percentage, ID: {b2bdaa74-a6e1-4208-9094-a38bae3f3672})
|
||||
----------
|
||||
The name of the StateType ({b2bdaa74-a6e1-4208-9094-a38bae3f3672}) of ThingClass sonoff_basic
|
||||
----------
|
||||
The name of the ActionType ({b2bdaa74-a6e1-4208-9094-a38bae3f3672}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>"Openingoutput"</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, ActionType: openingOutput, ID: {1aadbcf4-314b-409b-9223-55d433433edf})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: sonoff_basic, EventType: openingOutput, ID: {1aadbcf4-314b-409b-9223-55d433433edf})
|
||||
----------
|
||||
The name of the StateType ({1aadbcf4-314b-409b-9223-55d433433edf}) of ThingClass sonoff_basic
|
||||
----------
|
||||
The name of the ActionType ({1aadbcf4-314b-409b-9223-55d433433edf}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>"Closingoutput"</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, ActionType: closingOutput, ID: {e6b564ff-094d-45ba-a4db-f64a8bedf258})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: sonoff_basic, EventType: closingOutput, ID: {e6b564ff-094d-45ba-a4db-f64a8bedf258})
|
||||
----------
|
||||
The name of the StateType ({e6b564ff-094d-45ba-a4db-f64a8bedf258}) of ThingClass sonoff_basic
|
||||
----------
|
||||
The name of the ActionType ({e6b564ff-094d-45ba-a4db-f64a8bedf258}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Set power</source>
|
||||
<extracomment>The name of the ActionType ({481a7cf8-418b-4774-8fd4-32693ab52299}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Set state</source>
|
||||
<extracomment>The name of the ActionType ({174509b5-fc3e-4f03-8c93-8e044f0a2ce0}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Set moving</source>
|
||||
<extracomment>The name of the ActionType ({d3f711a1-9c79-459d-b697-d427280d9be8}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Set percentage</source>
|
||||
<extracomment>The name of the ActionType ({b2bdaa74-a6e1-4208-9094-a38bae3f3672}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Set openingOutput</source>
|
||||
<extracomment>The name of the ActionType ({1aadbcf4-314b-409b-9223-55d433433edf}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Set closingOutput</source>
|
||||
<extracomment>The name of the ActionType ({e6b564ff-094d-45ba-a4db-f64a8bedf258}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Garadget</source>
|
||||
<extracomment>The name of the vendor ({22d59bee-79cc-4dea-b742-30ac6bdcf2c9})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
----------
|
||||
|
||||
|
||||
|
||||
The name of the StateType ({e6b564ff-094d-45ba-a4db-f64a8bedf258}) of ThingClass extendedStatefulGaragedoor
|
||||
----------
|
||||
The name of the StateType ({d3f711a1-9c79-459d-b697-d427280d9be8}) of ThingClass extendedStatefulGaragedoor
|
||||
----------
|
||||
The name of the StateType ({1aadbcf4-314b-409b-9223-55d433433edf}) of ThingClass extendedStatefulGaragedoor
|
||||
----------
|
||||
The name of the ParamType (ThingClass: extendedStatefulGaragedoor, EventType: percentage, ID: {b2bdaa74-a6e1-4208-9094-a38bae3f3672})
|
||||
----------
|
||||
The name of the StateType ({b2bdaa74-a6e1-4208-9094-a38bae3f3672}) of ThingClass extendedStatefulGaragedoor</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Openposition changed</source>
|
||||
<extracomment>The name of the EventType ({b2bdaa74-a6e1-4208-9094-a38bae3f3672}) of ThingClass extendedStatefulGaragedoor</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Opening duration [ms]</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: extendedStatefulGaragedoor, Type: settings, ID: {cc818e83-40d4-4dc3-850e-acb25477aeae})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
----------
|
||||
The name of the StateType ({174509b5-fc3e-4f03-8c93-8e044f0a2ce0}) of ThingClass extendedStatefulGaragedoor</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>State changed</source>
|
||||
<extracomment>The name of the EventType ({174509b5-fc3e-4f03-8c93-8e044f0a2ce0}) of ThingClass extendedStatefulGaragedoor</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>IntegrationPluginGaradget</name>
|
||||
<message>
|
||||
<source>The given IP address is not valid.</source>
|
||||
<extracomment>Error setting up thing</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error creating MQTT channel. Please check MQTT server settings.</source>
|
||||
<extracomment>Error setting up thing</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not connect to Garadget device.</source>
|
||||
<extracomment>Error setting up thing</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Garadget</name>
|
||||
<message>
|
||||
<source>Sonoff-Garadget</source>
|
||||
<extracomment>The name of the plugin Garadget ({476781af-ad41-423b-b9bb-f308f2aff339})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Single switch (Sonoff Basic, RF, Touch...)</source>
|
||||
<extracomment>The name of the ThingClass ({e808b8ae-7608-41ce-8444-892f0648a4d3})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>IP address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, Type: thing, ID: {54a11a17-fc37-4316-891f-001c55e38220})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connected device</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, Type: thing, ID: {f2a79266-1b69-4c50-8397-9533dd2f30cb})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connected changed</source>
|
||||
<extracomment>The name of the EventType ({a3d7e6eb-82d0-47ee-b95f-4dde931eb7e2}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, EventType: connected, ID: {a3d7e6eb-82d0-47ee-b95f-4dde931eb7e2})
|
||||
----------
|
||||
The name of the StateType ({a3d7e6eb-82d0-47ee-b95f-4dde931eb7e2}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Power changed</source>
|
||||
<extracomment>The name of the EventType ({481a7cf8-418b-4774-8fd4-32693ab52299}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Power</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, ActionType: power, ID: {481a7cf8-418b-4774-8fd4-32693ab52299})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: sonoff_basic, EventType: power, ID: {481a7cf8-418b-4774-8fd4-32693ab52299})
|
||||
----------
|
||||
The name of the StateType ({481a7cf8-418b-4774-8fd4-32693ab52299}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
<source>Garadget</source>
|
||||
<extracomment>The name of the vendor ({22d59bee-79cc-4dea-b742-30ac6bdcf2c9})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Signal strength</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: sonoff_basic, EventType: signalStrength, ID: {e276e6ca-4cb5-46d2-9a78-31f92d78ac70})
|
||||
----------
|
||||
The name of the StateType ({e276e6ca-4cb5-46d2-9a78-31f92d78ac70}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Signal strength changed</source>
|
||||
<extracomment>The name of the EventType ({e276e6ca-4cb5-46d2-9a78-31f92d78ac70}) of ThingClass sonoff_basic</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
</context>
|
||||
</TS>
|
||||
Loading…
x
Reference in New Issue
Block a user