mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-10-22 14:33:25 +02:00
Some cleanup
This commit is contained in:
parent
ff03f6d28b
commit
9bac686148
@ -1,14 +0,0 @@
|
|||||||
include($$[QT_INSTALL_PREFIX]/include/nymea/plugin.pri)
|
|
||||||
|
|
||||||
QT += network
|
|
||||||
|
|
||||||
PKGCONFIG += nymea-mqtt
|
|
||||||
|
|
||||||
TARGET = $$qtLibraryTarget(nymea_integrationpluginGaradget)
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
integrationpluginGaradget.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
integrationpluginGaradget.h
|
|
||||||
|
|
||||||
12
garadget/garadget.pro
Normal file
12
garadget/garadget.pro
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
include(../plugins.pri)
|
||||||
|
|
||||||
|
QT += network
|
||||||
|
|
||||||
|
PKGCONFIG += nymea-mqtt
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
integrationplugingaradget.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
integrationplugingaradget.h
|
||||||
|
|
||||||
@ -1,406 +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},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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_*)
|
|
||||||
m_ipAddressParamTypeMap[sonoff_basicThingClassId] = sonoff_basicThingIpAddressParamTypeId;
|
|
||||||
|
|
||||||
|
|
||||||
// Helper maps for all devices
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
// 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("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."));
|
|
||||||
}
|
|
||||||
|
|
||||||
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()) {
|
|
||||||
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 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));
|
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
|
||||||
}
|
|
||||||
|
|
||||||
qCWarning(dcGaradget) << "Unhandled ThingClass in setupDevice" << thing->thingClassId();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IntegrationPluginGaradget::executeAction(ThingActionInfo *info)
|
|
||||||
{
|
|
||||||
Thing *thing = info->thing();
|
|
||||||
Action action = info->action();
|
|
||||||
|
|
||||||
qCDebug(dcGaradget) << "executeAction function" << (thing->thingClassId());
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
208
garadget/integrationplugingaradget.cpp
Normal file
208
garadget/integrationplugingaradget.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
void IntegrationPluginGaradget::setupThing(ThingSetupInfo *info)
|
||||||
|
{
|
||||||
|
Thing *thing = info->thing();
|
||||||
|
|
||||||
|
// QHostAddress deviceAddress = QHostAddress(thing->paramValue(garadgetThingIpAddressParamTypeId).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.
|
||||||
|
|
||||||
|
// Note from Michael: So, how does one configure the garadget device to connect to the MQTT broker? Is there a webinterface
|
||||||
|
// where you go with the browser and configure nymea's address there? If so, we could automate that so that the user
|
||||||
|
// doesn't have to do that.
|
||||||
|
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."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note from Michael: Does the clientId really need to be "garage"? Note that client ids must be unique on a single
|
||||||
|
// broker. So setting this to "garage" would prevent multiple garadgets from connecting to the same nymea instance.
|
||||||
|
// Better use something unique like the thingId if the garadget device supports it. Or, maybe, the user could configure
|
||||||
|
// it during setup using a paramType (like the ip address param stuff above).
|
||||||
|
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."));
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcGaradget) << "initial setup instructions:" << deviceAddress.toString() << channel;
|
||||||
|
|
||||||
|
// Note from Michael: With other devices that use MQTT, normally we do a REST call to their webinterface just to configure
|
||||||
|
// nymea's IP on them with this code below. Could that work with the garadget too?
|
||||||
|
/*
|
||||||
|
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(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";
|
||||||
|
|
||||||
|
// insert to reprogram client Garadget to new device/topic name
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginGaradget::thingRemoved(Thing *thing)
|
||||||
|
{
|
||||||
|
qCDebug(dcGaradget) << "Device removed" << thing->name();
|
||||||
|
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();
|
||||||
|
|
||||||
|
qCDebug(dcGaradget) << "executeAction function" << (thing->thingClassId());
|
||||||
|
|
||||||
|
MqttChannel *channel = m_mqttChannels.value(info->thing());
|
||||||
|
if (!channel) {
|
||||||
|
qCWarning(dcGaradget()) << "No mqtt channel for this thing.";
|
||||||
|
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (action.actionTypeId() == garadgetOpenActionTypeId) {
|
||||||
|
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() == garadgetCloseActionTypeId) {
|
||||||
|
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() == garadgetStopActionTypeId) {
|
||||||
|
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 garadget thing" << thing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginGaradget::onClientConnected(MqttChannel *channel)
|
||||||
|
{
|
||||||
|
qCDebug(dcGaradget) << "Garadget thing connected!";
|
||||||
|
Thing *dev = m_mqttChannels.key(channel);
|
||||||
|
dev->setStateValue(garadgetConnectedStateTypeId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginGaradget::onClientDisconnected(MqttChannel *channel)
|
||||||
|
{
|
||||||
|
qCDebug(dcGaradget) << "Garadget thing disconnected!";
|
||||||
|
Thing *dev = m_mqttChannels.key(channel);
|
||||||
|
dev->setStateValue(garadgetConnectedStateTypeId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginGaradget::onPublishReceived(MqttChannel *channel, const QString &topic, const QByteArray &payload)
|
||||||
|
{
|
||||||
|
qCDebug(dcGaradget) << "Publish received from garadget thing:" << topic << qUtf8Printable(payload);
|
||||||
|
Thing *thing = m_mqttChannels.key(channel);
|
||||||
|
|
||||||
|
// TODO: Fill in the "state" state with "open", "closed", "opening", "closing", "intermediate", dending on what we get from the garadget
|
||||||
|
if (topic.startsWith(channel->topicPrefixList().first() + "/sonoff/STATE")) {
|
||||||
|
thing->setStateValue(garadgetStateStateTypeId, "closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,15 +39,14 @@ class IntegrationPluginGaradget: public IntegrationPlugin
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginGaradget.json")
|
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationplugingaradget.json")
|
||||||
Q_INTERFACES(IntegrationPlugin)
|
Q_INTERFACES(IntegrationPlugin)
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit IntegrationPluginGaradget();
|
explicit IntegrationPluginGaradget() = default;
|
||||||
~IntegrationPluginGaradget();
|
~IntegrationPluginGaradget() = default;
|
||||||
|
|
||||||
void init() override;
|
|
||||||
void setupThing(ThingSetupInfo *info) override;
|
void setupThing(ThingSetupInfo *info) override;
|
||||||
void thingRemoved(Thing *thing) override;
|
void thingRemoved(Thing *thing) override;
|
||||||
void executeAction(ThingActionInfo *info) override;
|
void executeAction(ThingActionInfo *info) override;
|
||||||
@ -59,39 +58,6 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<Thing*, MqttChannel*> m_mqttChannels;
|
QHash<Thing*, MqttChannel*> m_mqttChannels;
|
||||||
|
|
||||||
// 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;
|
|
||||||
QHash<ThingClassId, ParamTypeId> m_openingChannelParamTypeMap;
|
|
||||||
QHash<ThingClassId, ParamTypeId> m_closingChannelParamTypeMap;
|
|
||||||
QHash<ThingClassId, StateTypeId> m_powerStateTypeMap;
|
|
||||||
|
|
||||||
QHash<ThingClassId, ActionTypeId> m_closableOpenActionTypeMap;
|
|
||||||
QHash<ThingClassId, ActionTypeId> m_closableCloseActionTypeMap;
|
|
||||||
QHash<ThingClassId, ActionTypeId> m_closableStopActionTypeMap;
|
|
||||||
|
|
||||||
// Helpers for both devices
|
|
||||||
QHash<ThingClassId, StateTypeId> m_connectedStateTypeMap;
|
|
||||||
QHash<ThingClassId, StateTypeId> m_signalStrengthStateTypeMap;
|
|
||||||
|
|
||||||
QHash<ThingClassId, StateTypeId> m_brightnessStateTypeMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTEGRATIONPLUGINGARADGET_H
|
#endif // INTEGRATIONPLUGINGARADGET_H
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Garadget",
|
"name": "Garadget",
|
||||||
"displayName": "Sonoff-Garadget",
|
"displayName": "Garadget",
|
||||||
"id": "476781af-ad41-423b-b9bb-f308f2aff339",
|
"id": "476781af-ad41-423b-b9bb-f308f2aff339",
|
||||||
"vendors": [
|
"vendors": [
|
||||||
{
|
{
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"id": "22d59bee-79cc-4dea-b742-30ac6bdcf2c9",
|
"id": "22d59bee-79cc-4dea-b742-30ac6bdcf2c9",
|
||||||
"thingClasses": [
|
"thingClasses": [
|
||||||
{
|
{
|
||||||
"name": "sonoff_basic",
|
"name": "garadget",
|
||||||
"displayName": "Garadget",
|
"displayName": "Garadget",
|
||||||
"id": "e808b8ae-7608-41ce-8444-892f0648a4d3",
|
"id": "e808b8ae-7608-41ce-8444-892f0648a4d3",
|
||||||
"setupMethod": "JustAdd",
|
"setupMethod": "JustAdd",
|
||||||
@ -22,6 +22,7 @@ PLUGIN_DIRS = \
|
|||||||
fastcom \
|
fastcom \
|
||||||
flowercare \
|
flowercare \
|
||||||
fronius \
|
fronius \
|
||||||
|
garadget \
|
||||||
genericelements \
|
genericelements \
|
||||||
genericthings \
|
genericthings \
|
||||||
goecharger \
|
goecharger \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user