Combine both Tap devices into one thing
Combine rotary and switch devices into one nymea thingmaster
parent
ce9998a54d
commit
cefe81f450
|
|
@ -61,24 +61,20 @@ void HueRemote::updateStates(const QVariantMap &statesMap, const QVariantMap &co
|
||||||
|
|
||||||
QString lastUpdate = statesMap.value("lastupdated").toString();
|
QString lastUpdate = statesMap.value("lastupdated").toString();
|
||||||
int buttonCode = statesMap.value("buttonevent").toInt();
|
int buttonCode = statesMap.value("buttonevent").toInt();
|
||||||
int rotationCode = statesMap.value("expectedrotation").toInt();
|
|
||||||
|
|
||||||
// If we never polled, just store lastUpdate/buttonCode/rotationCode and not emit a falsely button pressed event
|
// If we never polled, just store lastUpdate/buttonCode/rotationCode and not emit a falsely button pressed event
|
||||||
if (m_lastUpdate.isEmpty() || m_lastButtonCode == -1) {
|
if (m_lastUpdate.isEmpty() || m_lastButtonCode == -1) {
|
||||||
m_lastUpdate = lastUpdate;
|
m_lastUpdate = lastUpdate;
|
||||||
m_lastButtonCode = buttonCode;
|
m_lastButtonCode = buttonCode;
|
||||||
m_lastRotationCode = rotationCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_lastUpdate != lastUpdate || m_lastButtonCode != buttonCode || m_lastRotationCode != rotationCode) {
|
if (m_lastUpdate != lastUpdate || m_lastButtonCode != buttonCode) {
|
||||||
m_lastUpdate = lastUpdate;
|
m_lastUpdate = lastUpdate;
|
||||||
m_lastButtonCode = buttonCode;
|
m_lastButtonCode = buttonCode;
|
||||||
m_lastRotationCode = rotationCode;
|
|
||||||
|
|
||||||
qCDebug(dcPhilipsHue) << "button pressed" << buttonCode;
|
qCDebug(dcPhilipsHue) << "button pressed" << buttonCode;
|
||||||
|
|
||||||
emit buttonPressed(buttonCode);
|
emit buttonPressed(buttonCode);
|
||||||
emit rotated(rotationCode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,10 @@ private:
|
||||||
int m_battery;
|
int m_battery;
|
||||||
QString m_lastUpdate;
|
QString m_lastUpdate;
|
||||||
int m_lastButtonCode = -1;
|
int m_lastButtonCode = -1;
|
||||||
int m_lastRotationCode = 0;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stateChanged();
|
void stateChanged();
|
||||||
void buttonPressed(int buttonCode);
|
void buttonPressed(int buttonCode);
|
||||||
void rotated(int rotationCode);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 "huetapdial.h"
|
||||||
|
#include "extern-plugininfo.h"
|
||||||
|
|
||||||
|
#include <QtMath>
|
||||||
|
|
||||||
|
HueTapDial::HueTapDial(HueBridge *bridge, QObject *parent) :
|
||||||
|
HueDevice(bridge, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int HueTapDial::rotaryId() const
|
||||||
|
{
|
||||||
|
return m_rotaryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HueTapDial::setRotaryId(int sensorId)
|
||||||
|
{
|
||||||
|
m_rotaryId = sensorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HueTapDial::rotaryUuid() const
|
||||||
|
{
|
||||||
|
return m_rotaryUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HueTapDial::setRotaryUuid(const QString &rotaryUuid)
|
||||||
|
{
|
||||||
|
m_rotaryUuid = rotaryUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HueTapDial::switchId() const
|
||||||
|
{
|
||||||
|
return m_switchId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HueTapDial::setSwitchId(int sensorId)
|
||||||
|
{
|
||||||
|
m_SwitchId = sensorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString HueTapDial::switchUuid() const
|
||||||
|
{
|
||||||
|
return m_switchUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HueTapDial::setSwitchUuid(const QString &switchUuid)
|
||||||
|
{
|
||||||
|
m_switchUuid = switchUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
double HueTapDial::level() const
|
||||||
|
{
|
||||||
|
return m_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HueTapDial::batteryLevel() const
|
||||||
|
{
|
||||||
|
return m_batteryLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HueTapDial::updateStates(const QVariantMap &sensorMap)
|
||||||
|
{
|
||||||
|
qCDebug(dcPhilipsHue()) << "Hue Tap Dial data:" << qUtf8Printable(QJsonDocument::fromVariant(sensorMap).toJson(QJsonDocument::Indented));
|
||||||
|
|
||||||
|
// Config
|
||||||
|
QVariantMap configMap = sensorMap.value("config").toMap();
|
||||||
|
if (configMap.contains("reachable")) {
|
||||||
|
setReachable(configMap.value("reachable", false).toBool());
|
||||||
|
// emit reachableChanged????
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configMap.contains("battery")) {
|
||||||
|
int batteryLevel = configMap.value("battery", 0).toInt();
|
||||||
|
if (m_batteryLevel != batteryLevel) {
|
||||||
|
m_batteryLevel = batteryLevel;
|
||||||
|
emit batteryLevelChanged(m_batteryLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// States
|
||||||
|
QVariantMap stateMap = sensorMap.value("state").toMap();
|
||||||
|
|
||||||
|
// If rotated
|
||||||
|
if (sensorMap.value("uniqueid").toString() == m_rotaryUuid) {
|
||||||
|
QString lastUpdate = stateMap.value("lastupdated").toString();
|
||||||
|
int rotationCode = stateMap.value("expectedrotation").toInt();
|
||||||
|
|
||||||
|
// If we never polled, just store lastUpdate/rotationCode and not emit a false rotated event
|
||||||
|
if (m_lastUpdate.isEmpty() || m_lastRotationCode == 0) {
|
||||||
|
m_lastUpdate = lastUpdate;
|
||||||
|
m_lastRotationCode = rotationCode;
|
||||||
|
}
|
||||||
|
if (m_lastUpdate != lastUpdate || m_lastRotationCode != rotationCode) {
|
||||||
|
m_lastUpdate = lastUpdate;
|
||||||
|
m_lastRotationCode = rotationCode;
|
||||||
|
qCDebug(dcPhilipsHue) << "rotated" << rotationCode;
|
||||||
|
emit rotated(rotationCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If button press
|
||||||
|
if (sensorMap.value("uniqueid").toString() == m_switchUuid) {
|
||||||
|
QString lastUpdate = stateMap.value("lastupdated").toString();
|
||||||
|
int buttonCode = stateMap.value("buttonevent").toInt();
|
||||||
|
|
||||||
|
// If we never polled, just store lastUpdate/buttonCode and not emit a false button pressed event
|
||||||
|
if (m_lastUpdate.isEmpty() || m_lastButtonCode == -1) {
|
||||||
|
m_lastUpdate = lastUpdate;
|
||||||
|
m_lastButtonCode = buttonCode;
|
||||||
|
}
|
||||||
|
if (m_lastUpdate != lastUpdate || m_lastButtonCode != buttonCode) {
|
||||||
|
m_lastUpdate = lastUpdate;
|
||||||
|
m_lastButtonCode = buttonCode;
|
||||||
|
qCDebug(dcPhilipsHue) << "button pressed" << buttonCode;
|
||||||
|
emit buttonPressed(buttonCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HueTapDial::isValid()
|
||||||
|
{
|
||||||
|
return !m_rotaryUuid.isEmpty() && !m_switchUuid.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HueTapDial::hasSensor(int sensorId)
|
||||||
|
{
|
||||||
|
return m_rotaryId == sensorId || m_switchId == sensorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HueTapDial::hasSensor(const QString &sensorUuid)
|
||||||
|
{
|
||||||
|
return m_rotaryUuid == sensorUuid || m_switchUuid == sensorUuid;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef HUETAPDIAL_H
|
||||||
|
#define HUETAPDIAL_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "extern-plugininfo.h"
|
||||||
|
#include "huedevice.h"
|
||||||
|
|
||||||
|
class HueTapDial : public HueDevice
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit HueTapDial(HueBridge *bridge, QObject *parent = nullptr);
|
||||||
|
//virtual ~HueTapDial() = default;
|
||||||
|
|
||||||
|
int rotaryId() const;
|
||||||
|
void setRotaryId(int sensorId);
|
||||||
|
|
||||||
|
QString rotaryUuid() const;
|
||||||
|
void setRotaryUuid(const QString &rotaryUuid);
|
||||||
|
|
||||||
|
int switchId() const;
|
||||||
|
void setSwitchId(int sensorId);
|
||||||
|
|
||||||
|
QString switchUuid() const;
|
||||||
|
void setSwitchUuid(const QString &switchUuid);
|
||||||
|
|
||||||
|
int level() const;
|
||||||
|
int batteryLevel() const;
|
||||||
|
|
||||||
|
void updateStates(const QVariantMap &sensorMap);
|
||||||
|
|
||||||
|
bool isValid();
|
||||||
|
bool hasSensor(int sensorId);
|
||||||
|
bool hasSensor(const QString &sensorUuid);
|
||||||
|
|
||||||
|
// virtual StateTypeId connectedStateTypeId() const = 0;
|
||||||
|
// virtual StateTypeId levelStateTypeId() const = 0;
|
||||||
|
// virtual StateTypeId batteryLevelStateTypeId() const = 0;
|
||||||
|
// virtual StateTypeId batteryCriticalStateTypeId() const = 0;
|
||||||
|
|
||||||
|
// StateTypeId connectedStateTypeId() const override { return tapDialConnectedStateTypeId; }
|
||||||
|
// StateTypeId levelStateTypeId() const override { return tapDialLevelStateTypeId; }
|
||||||
|
// StateTypeId batteryLevelStateTypeId() const override { return tapDialBatteryLevelStateTypeId; }
|
||||||
|
// StateTypeId batteryCriticalStateTypeId() const override { return tapDialBatteryCriticalStateTypeId; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Params
|
||||||
|
int m_rotaryId;
|
||||||
|
QString m_rotaryUuid;
|
||||||
|
|
||||||
|
int m_switchId;
|
||||||
|
QString m_switchUuid;
|
||||||
|
|
||||||
|
// States
|
||||||
|
QString m_lastUpdate;
|
||||||
|
double m_level = 0;
|
||||||
|
int m_batteryLevel = 0;
|
||||||
|
int m_lastButtonCode = -1;
|
||||||
|
int m_lastRotationCode = 0;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void levelChanged(double level);
|
||||||
|
void batteryLevelChanged(int batteryLevel);
|
||||||
|
void buttonPressed(int buttonCode);
|
||||||
|
void rotated(int rotationCode);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HUETAPDIAL_H
|
||||||
|
|
@ -519,18 +519,21 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
|
||||||
if (thing->thingClassId() == tapDialThingClassId) {
|
if (thing->thingClassId() == tapDialThingClassId) {
|
||||||
qCDebug(dcPhilipsHue) << "Setup Hue Tap Dial" << thing->params() << thing->thingClassId();
|
qCDebug(dcPhilipsHue) << "Setup Hue Tap Dial" << thing->params() << thing->thingClassId();
|
||||||
|
|
||||||
HueRemote *hueTapDial = new HueRemote(bridge, this);
|
HueTapDial *hueTapDial = new HueTapDial(bridge, this);
|
||||||
|
|
||||||
hueTapDial->setId(thing->paramValue(tapDialThingSensorIdParamTypeId).toInt());
|
|
||||||
hueTapDial->setModelId(thing->paramValue(tapDialThingModelIdParamTypeId).toString());
|
hueTapDial->setModelId(thing->paramValue(tapDialThingModelIdParamTypeId).toString());
|
||||||
hueTapDial->setType(thing->paramValue(tapDialThingTypeParamTypeId).toString());
|
|
||||||
hueTapDial->setUuid(thing->paramValue(tapDialThingUuidParamTypeId).toString());
|
hueTapDial->setUuid(thing->paramValue(tapDialThingUuidParamTypeId).toString());
|
||||||
|
hueTapDial->setRotaryId(thing->paramValue(tapDialThingIdRotaryParamTypeId).toInt());
|
||||||
|
hueTapDial->setRotaryUuid(thing->paramValue(tapDialThingUuidRotaryParamTypeId).toString());
|
||||||
|
hueTapDial->setSwitchId(thing->paramValue(tapDialThingIdSwitchParamTypeId).toInt());
|
||||||
|
hueTapDial->setSwitchUuid(thing->paramValue(tapDialThingUuidSwitchParamTypeId).toString());
|
||||||
|
|
||||||
connect(hueTapDial, &HueRemote::stateChanged, this, &IntegrationPluginPhilipsHue::remoteStateChanged);
|
connect(hueTapDial, &HueTapDial::reachableChanged, this, &IntegrationPluginPhilipsHue::onTapDialReachableChanged);
|
||||||
connect(hueTapDial, &HueRemote::buttonPressed, this, &IntegrationPluginPhilipsHue::onRemoteButtonEvent);
|
connect(hueTapDial, &HueTapDial::batteryLevelChanged, this, &IntegrationPluginPhilipsHue::onTapDialBatteryLevelChanged);
|
||||||
connect(hueTapDial, &HueRemote::rotated, this, &IntegrationPluginPhilipsHue::onRemoteRotaryEvent);
|
connect(hueTapDial, &HueTapDial::buttonPressed, this, &IntegrationPluginPhilipsHue::onTapDialButtonEvent);
|
||||||
|
connect(hueTapDial, &HueTapDial::rotated, this, &IntegrationPluginPhilipsHue::onTapDialRotaryEvent);
|
||||||
|
|
||||||
m_remotes.insert(hueTapDial, thing);
|
m_tapDials.insert(hueTapDial, thing);
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
return info->finish(Thing::ThingErrorNoError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -707,12 +710,18 @@ void IntegrationPluginPhilipsHue::thingRemoved(Thing *thing)
|
||||||
light->deleteLater();
|
light->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thing->thingClassId() == remoteThingClassId || thing->thingClassId() == dimmerSwitch2ThingClassId || thing->thingClassId() == tapDialThingClassId || thing->thingClassId() == tapThingClassId || thing->thingClassId() == fohThingClassId || thing->thingClassId() == smartButtonThingClassId || thing->thingClassId() == wallSwitchThingClassId) {
|
if (thing->thingClassId() == remoteThingClassId || thing->thingClassId() == dimmerSwitch2ThingClassId || thing->thingClassId() == tapThingClassId || thing->thingClassId() == fohThingClassId || thing->thingClassId() == smartButtonThingClassId || thing->thingClassId() == wallSwitchThingClassId) {
|
||||||
HueRemote *remote = m_remotes.key(thing);
|
HueRemote *remote = m_remotes.key(thing);
|
||||||
m_remotes.remove(remote);
|
m_remotes.remove(remote);
|
||||||
remote->deleteLater();
|
remote->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thing->thingClassId() == tapDialThingClassId) {
|
||||||
|
HueTapDial *tapDial = m_tapDials.key(thing);
|
||||||
|
m_tapDials.remove(tapDial);
|
||||||
|
tapDial->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
if (thing->thingClassId() == outdoorSensorThingClassId || thing->thingClassId() == motionSensorThingClassId) {
|
if (thing->thingClassId() == outdoorSensorThingClassId || thing->thingClassId() == motionSensorThingClassId) {
|
||||||
HueMotionSensor *motionSensor = m_motionSensors.key(thing);
|
HueMotionSensor *motionSensor = m_motionSensors.key(thing);
|
||||||
m_motionSensors.remove(motionSensor);
|
m_motionSensors.remove(motionSensor);
|
||||||
|
|
@ -1340,49 +1349,6 @@ void IntegrationPluginPhilipsHue::onRemoteButtonEvent(int buttonCode)
|
||||||
// * codes ending in 0 (e.g. 1000) indicate start of long press
|
// * codes ending in 0 (e.g. 1000) indicate start of long press
|
||||||
// * codes ending in 3 (e.g. 1003) indicate end of long press
|
// * codes ending in 3 (e.g. 1003) indicate end of long press
|
||||||
// * codes ending in 1 (e.g. 1001) are sent during the long press
|
// * codes ending in 1 (e.g. 1001) are sent during the long press
|
||||||
} else if (thing->thingClassId() == tapDialThingClassId) {
|
|
||||||
switch (buttonCode) {
|
|
||||||
case 1002:
|
|
||||||
param = Param(tapDialPressedEventButtonNameParamTypeId, "•");
|
|
||||||
id = tapDialPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
case 1001:
|
|
||||||
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "•");
|
|
||||||
id = tapDialLongPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
case 2002:
|
|
||||||
param = Param(tapDialPressedEventButtonNameParamTypeId, "••");
|
|
||||||
id = tapDialPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
case 2001:
|
|
||||||
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "••");
|
|
||||||
id = tapDialLongPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
case 3002:
|
|
||||||
param = Param(tapDialPressedEventButtonNameParamTypeId, "•••");
|
|
||||||
id = tapDialPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
case 3001:
|
|
||||||
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "•••");
|
|
||||||
id = tapDialLongPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
case 4002:
|
|
||||||
param = Param(tapDialPressedEventButtonNameParamTypeId, "••••");
|
|
||||||
id = tapDialPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
case 4001:
|
|
||||||
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "••••");
|
|
||||||
id = tapDialLongPressedEventTypeId;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
qCDebug(dcPhilipsHue()) << "Unhandled button code received from Hue Tap Dial:" << buttonCode << "Thing name:" << thing->name();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// codes ending in 2 (e.g. 1002) are short presses;
|
|
||||||
// for long presses the Dimmer Switch V2 sends 3 codes:
|
|
||||||
// * codes ending in 0 (e.g. 1000) indicate start of long press
|
|
||||||
// * codes ending in 3 (e.g. 1003) indicate end of long press --> not yet supported by this plugin, but e.g. LongPressEnded action could be added
|
|
||||||
// * codes ending in 1 (e.g. 1001) are sent during the long press --> probably for backwards compatibility with earlier version, and therefore not added to this plugin
|
|
||||||
} else if (thing->thingClassId() == tapThingClassId) {
|
} else if (thing->thingClassId() == tapThingClassId) {
|
||||||
switch (buttonCode) {
|
switch (buttonCode) {
|
||||||
case 34:
|
case 34:
|
||||||
|
|
@ -1457,15 +1423,75 @@ void IntegrationPluginPhilipsHue::onRemoteButtonEvent(int buttonCode)
|
||||||
emitEvent(Event(id, m_remotes.value(remote)->id(), ParamList() << param));
|
emitEvent(Event(id, m_remotes.value(remote)->id(), ParamList() << param));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginPhilipsHue::onRemoteRotaryEvent(int rotationCode)
|
void IntegrationPluginPhilipsHue::onTapDialButtonEvent(int buttonCode)
|
||||||
{
|
{
|
||||||
HueRemote *remote = static_cast<HueRemote *>(sender());
|
HueTapDial *tapDial = static_cast<HueTapDial *>(sender());
|
||||||
Thing *thing = m_remotes.value(remote);
|
Thing *thing = m_tapDials.value(tapDial);
|
||||||
if (!thing) {
|
if (!thing) {
|
||||||
qCWarning(dcPhilipsHue()) << "Received a button press event for a thing we don't know!";
|
qCWarning(dcPhilipsHue()) << "Received a button press event for a thing we don't know!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EventTypeId id;
|
||||||
|
Param param;
|
||||||
|
|
||||||
|
if (thing->thingClassId() == tapDialThingClassId) {
|
||||||
|
switch (buttonCode) {
|
||||||
|
case 1002:
|
||||||
|
param = Param(tapDialPressedEventButtonNameParamTypeId, "•");
|
||||||
|
id = tapDialPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
case 1001:
|
||||||
|
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "•");
|
||||||
|
id = tapDialLongPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
case 2002:
|
||||||
|
param = Param(tapDialPressedEventButtonNameParamTypeId, "••");
|
||||||
|
id = tapDialPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
case 2001:
|
||||||
|
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "••");
|
||||||
|
id = tapDialLongPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
case 3002:
|
||||||
|
param = Param(tapDialPressedEventButtonNameParamTypeId, "•••");
|
||||||
|
id = tapDialPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
case 3001:
|
||||||
|
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "•••");
|
||||||
|
id = tapDialLongPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
case 4002:
|
||||||
|
param = Param(tapDialPressedEventButtonNameParamTypeId, "••••");
|
||||||
|
id = tapDialPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
case 4001:
|
||||||
|
param = Param(tapDialLongPressedEventButtonNameParamTypeId, "••••");
|
||||||
|
id = tapDialLongPressedEventTypeId;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCDebug(dcPhilipsHue()) << "Unhandled button code received from Hue Tap Dial:" << buttonCode << "Thing name:" << thing->name();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// codes ending in 2 (e.g. 1002) are short presses;
|
||||||
|
// for long presses the Dimmer Switch V2 sends 3 codes:
|
||||||
|
// * codes ending in 0 (e.g. 1000) indicate start of long press
|
||||||
|
// * codes ending in 3 (e.g. 1003) indicate end of long press --> not yet supported by this plugin, but e.g. LongPressEnded action could be added
|
||||||
|
// * codes ending in 1 (e.g. 1001) are sent during the long press --> probably for backwards compatibility with earlier version, and therefore not added to this plugin
|
||||||
|
}
|
||||||
|
emitEvent(Event(id, m_tapDials.value(tapDial)->id(), ParamList() << param));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IntegrationPluginPhilipsHue::onTapDialRotaryEvent(int rotationCode)
|
||||||
|
{
|
||||||
|
HueTapDial *tapDial = static_cast<HueTapDial *>(sender());
|
||||||
|
Thing *thing = m_tapDials.value(tapDial);
|
||||||
|
if (!thing) {
|
||||||
|
qCWarning(dcPhilipsHue()) << "Received a rotary event for a thing we don't know!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EventTypeId id;
|
EventTypeId id;
|
||||||
Param param;
|
Param param;
|
||||||
int currentLevel = thing->stateValue(tapDialLevelStateTypeId).toUInt();
|
int currentLevel = thing->stateValue(tapDialLevelStateTypeId).toUInt();
|
||||||
|
|
@ -1491,7 +1517,22 @@ void IntegrationPluginPhilipsHue::onRemoteRotaryEvent(int rotationCode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emitEvent(Event(id, m_remotes.value(remote)->id()));
|
emitEvent(Event(id, m_tapDials.value(tapDial)->id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginPhilipsHue::onTapDialReachableChanged(bool reachable)
|
||||||
|
{
|
||||||
|
HueTapDial *tapDial = static_cast<HueTapDial *>(sender());
|
||||||
|
Thing *tapDialDevice = m_tapDials.value(tapDial);
|
||||||
|
tapDialDevice->setStateValue(tapDialConnectedStateTypeId, reachable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginPhilipsHue::onTapDialBatteryLevelChanged(int batteryLevel)
|
||||||
|
{
|
||||||
|
HueTapDial *tapDial = static_cast<HueTapDial *>(sender());
|
||||||
|
Thing *tapDialDevice = m_tapDials.value(tapDial);
|
||||||
|
tapDialDevice->setStateValue(tapDialBatteryLevelStateTypeId, batteryLevel);
|
||||||
|
tapDialDevice->setStateValue(tapDialBatteryCriticalStateTypeId, (batteryLevel < 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginPhilipsHue::onMotionSensorReachableChanged(bool reachable)
|
void IntegrationPluginPhilipsHue::onMotionSensorReachableChanged(bool reachable)
|
||||||
|
|
@ -1784,8 +1825,10 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
|
||||||
// Create sensors if not already added
|
// Create sensors if not already added
|
||||||
QVariantMap sensorsMap = jsonDoc.toVariant().toMap();
|
QVariantMap sensorsMap = jsonDoc.toVariant().toMap();
|
||||||
QHash<QString, HueMotionSensor *> motionSensors;
|
QHash<QString, HueMotionSensor *> motionSensors;
|
||||||
|
QHash<QString, HueTapDial *> tapDials;
|
||||||
QList<HueRemote*> remotesToRemove = m_remotes.keys();
|
QList<HueRemote*> remotesToRemove = m_remotes.keys();
|
||||||
QList<HueMotionSensor*> sensorsToRemove = m_motionSensors.keys();
|
QList<HueMotionSensor*> sensorsToRemove = m_motionSensors.keys();
|
||||||
|
QList<HueTapDial*> tapDialsToRemove = m_tapDials.keys();
|
||||||
foreach (const QString &sensorId, sensorsMap.keys()) {
|
foreach (const QString &sensorId, sensorsMap.keys()) {
|
||||||
|
|
||||||
QVariantMap sensorMap = sensorsMap.value(sensorId).toMap();
|
QVariantMap sensorMap = sensorsMap.value(sensorId).toMap();
|
||||||
|
|
@ -1800,6 +1843,12 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
foreach (HueTapDial* tapDial, tapDialsToRemove) {
|
||||||
|
if (tapDial->uuid() == uuid.split("-").first()) {
|
||||||
|
tapDialsToRemove.removeAll(tapDial);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
foreach (HueMotionSensor* sensor, sensorsToRemove) {
|
foreach (HueMotionSensor* sensor, sensorsToRemove) {
|
||||||
if (sensor->uuid() == uuid.split("-").first()) {
|
if (sensor->uuid() == uuid.split("-").first()) {
|
||||||
sensorsToRemove.removeAll(sensor);
|
sensorsToRemove.removeAll(sensor);
|
||||||
|
|
@ -1836,26 +1885,49 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
|
||||||
|
|
||||||
// Tap Dial
|
// Tap Dial
|
||||||
} else if (model == "RDM002") {
|
} else if (model == "RDM002") {
|
||||||
|
// Get the base uuid from this sensor
|
||||||
|
QString baseUuid = HueDevice::getBaseUuid(uuid);
|
||||||
|
qCDebug(dcPhilipsHue) << "Base uuid:" << baseUuid;
|
||||||
|
|
||||||
|
// Rotary dial
|
||||||
if (sensorMap.value("type").toString() == "ZLLRelativeRotary") {
|
if (sensorMap.value("type").toString() == "ZLLRelativeRotary") {
|
||||||
ThingDescriptor descriptor(tapDialThingClassId, sensorMap.value("name").toString(), "Philips Hue Tap Dial", thing->id());
|
qCDebug(dcPhilipsHue()) << "Found rotary dial from tap dial:" << baseUuid << sensorMap;
|
||||||
ParamList params;
|
// Check if we have tap dial for this rotary dial
|
||||||
params.append(Param(tapDialThingModelIdParamTypeId, model));
|
if (tapDials.contains(baseUuid)) {
|
||||||
params.append(Param(tapDialThingTypeParamTypeId, sensorMap.value("type").toString()));
|
HueTapDial *tapDial = tapDials.value(baseUuid);
|
||||||
params.append(Param(tapDialThingUuidParamTypeId, uuid));
|
tapDial->setRotaryUuid(uuid);
|
||||||
params.append(Param(tapDialThingSensorIdParamTypeId, sensorId));
|
tapDial->setRotaryId(sensorId.toInt());
|
||||||
descriptor.setParams(params);
|
} else {
|
||||||
emit autoThingsAppeared({descriptor});
|
// Create a tap dial
|
||||||
qCDebug(dcPhilipsHue) << "Found new tap dial" << sensorMap.value("name").toString() << model;
|
HueTapDial *tapDial = nullptr;
|
||||||
} else if (sensorMap.value("type").toString() == "ZLLSwitch") {
|
tapDial = new HueTapDial(bridge, this);
|
||||||
ThingDescriptor descriptor(tapDialThingClassId, sensorMap.value("name").toString(), "Philips Hue Tap Dial", thing->id());
|
|
||||||
ParamList params;
|
tapDial->setModelId(model);
|
||||||
params.append(Param(tapDialThingModelIdParamTypeId, model));
|
tapDial->setUuid(baseUuid);
|
||||||
params.append(Param(tapDialThingTypeParamTypeId, sensorMap.value("type").toString()));
|
tapDial->setRotaryUuid(uuid);
|
||||||
params.append(Param(tapDialThingUuidParamTypeId, uuid));
|
tapDial->setRotaryId(sensorId.toInt());
|
||||||
params.append(Param(tapDialThingSensorIdParamTypeId, sensorId));
|
tapDials.insert(baseUuid, tapDial);
|
||||||
descriptor.setParams(params);
|
}
|
||||||
emit autoThingsAppeared({descriptor});
|
}
|
||||||
qCDebug(dcPhilipsHue) << "Found new tap dial" << sensorMap.value("name").toString() << model;
|
// Buttons
|
||||||
|
if (sensorMap.value("type").toString() == "ZLLSwitch") {
|
||||||
|
qCDebug(dcPhilipsHue()) << "Found switch from tap dial:" << baseUuid << sensorMap;
|
||||||
|
// Check if we have tap dial for this switch
|
||||||
|
if (tapDials.contains(baseUuid)) {
|
||||||
|
HueTapDial *tapDial = tapDials.value(baseUuid);
|
||||||
|
tapDial->setSwitchUuid(uuid);
|
||||||
|
tapDial->setSwitchId(sensorId.toInt());
|
||||||
|
} else {
|
||||||
|
// Create a tap dial
|
||||||
|
HueTapDial *tapDial = nullptr;
|
||||||
|
tapDial = new HueTapDial(bridge, this);
|
||||||
|
|
||||||
|
tapDial->setModelId(model);
|
||||||
|
tapDial->setUuid(baseUuid);
|
||||||
|
tapDial->setSwitchUuid(uuid);
|
||||||
|
tapDial->setSwitchId(sensorId.toInt());
|
||||||
|
tapDials.insert(baseUuid, tapDial);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Smart Button
|
// Smart Button
|
||||||
|
|
@ -2023,6 +2095,28 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
|
||||||
motionSensor->deleteLater();
|
motionSensor->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create tap dials if there are any new devices found
|
||||||
|
foreach (HueTapDial *tapDial, tapDials.values()) {
|
||||||
|
QString baseUuid = tapDials.key(tapDial);
|
||||||
|
if (tapDial->isValid()) {
|
||||||
|
ThingDescriptor descriptor(tapDialThingClassId, tr("Philips Hue Tap Dial"), baseUuid, thing->id());
|
||||||
|
ParamList params;
|
||||||
|
params.append(Param(tapDialThingModelIdParamTypeId, tapDial->modelId()));
|
||||||
|
params.append(Param(tapDialThingUuidParamTypeId, tapDial->uuid()));
|
||||||
|
params.append(Param(tapDialThingIdRotaryParamTypeId, tapDial->rotaryId()));
|
||||||
|
params.append(Param(tapDialThingUuidRotaryParamTypeId, tapDial->rotaryUuid()));
|
||||||
|
params.append(Param(tapDialThingIdSwitchParamTypeId, tapDial->switchId()));
|
||||||
|
params.append(Param(tapDialThingUuidSwitchParamTypeId, tapDial->switchUuid()));
|
||||||
|
descriptor.setParams(params);
|
||||||
|
qCDebug(dcPhilipsHue()) << "Found new tap dial" << baseUuid << tapDialThingClassId;
|
||||||
|
emit autoThingsAppeared({descriptor});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
tapDials.remove(baseUuid);
|
||||||
|
tapDial->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (HueRemote* remote, remotesToRemove) {
|
foreach (HueRemote* remote, remotesToRemove) {
|
||||||
Thing *remoteThing = m_remotes.value(remote);
|
Thing *remoteThing = m_remotes.value(remote);
|
||||||
if (remoteThing->parentId() == thing->id()) {
|
if (remoteThing->parentId() == thing->id()) {
|
||||||
|
|
@ -2031,6 +2125,14 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (HueTapDial* tapDial, tapDialsToRemove) {
|
||||||
|
Thing *tapDialThing = m_tapDials.value(tapDial);
|
||||||
|
if (tapDialThing->parentId() == thing->id()) {
|
||||||
|
qCDebug(dcPhilipsHue()) << "Hue tap dial disappeared from bridge";
|
||||||
|
emit autoThingDisappeared(tapDialThing->id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (HueMotionSensor* sensor, sensorsToRemove) {
|
foreach (HueMotionSensor* sensor, sensorsToRemove) {
|
||||||
Thing *sensorThing = m_motionSensors.value(sensor);
|
Thing *sensorThing = m_motionSensors.value(sensor);
|
||||||
if (sensorThing->parentId() == thing->id()) {
|
if (sensorThing->parentId() == thing->id()) {
|
||||||
|
|
@ -2191,6 +2293,13 @@ void IntegrationPluginPhilipsHue::processSensorsRefreshResponse(Thing *thing, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tap dials
|
||||||
|
foreach (HueTapDial *tapDial, m_tapDials.keys()) {
|
||||||
|
if (tapDial->hasSensor(sensorId.toInt()) && m_tapDials.value(tapDial)->parentId() == thing->id()) {
|
||||||
|
tapDial->updateStates(sensorMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Motion sensors
|
// Motion sensors
|
||||||
foreach (HueMotionSensor *motionSensor, m_motionSensors.keys()) {
|
foreach (HueMotionSensor *motionSensor, m_motionSensors.keys()) {
|
||||||
if (motionSensor->hasSensor(sensorId.toInt()) && m_motionSensors.value(motionSensor)->parentId() == thing->id()) {
|
if (motionSensor->hasSensor(sensorId.toInt()) && m_motionSensors.value(motionSensor)->parentId() == thing->id()) {
|
||||||
|
|
@ -2273,6 +2382,13 @@ void IntegrationPluginPhilipsHue::bridgeReachableChanged(Thing *thing, bool reac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (HueTapDial *tapDial, m_tapDials.keys()) {
|
||||||
|
if (m_tapDials.value(tapDial)->parentId() == thing->id()) {
|
||||||
|
tapDial->setReachable(false);
|
||||||
|
m_tapDials.value(tapDial)->setStateValue(tapDialConnectedStateTypeId, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (HueMotionSensor *motionSensor, m_motionSensors.keys()) {
|
foreach (HueMotionSensor *motionSensor, m_motionSensors.keys()) {
|
||||||
if (m_motionSensors.value(motionSensor)->parentId() == thing->id()) {
|
if (m_motionSensors.value(motionSensor)->parentId() == thing->id()) {
|
||||||
motionSensor->setReachable(false);
|
motionSensor->setReachable(false);
|
||||||
|
|
@ -2377,6 +2493,15 @@ bool IntegrationPluginPhilipsHue::sensorAlreadyAdded(const QString &uuid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tap Dial consists out of 2 devices
|
||||||
|
if (thing->thingClassId() == tapDialThingClassId) {
|
||||||
|
if (thing->paramValue(tapDialThingUuidRotaryParamTypeId).toString() == uuid) {
|
||||||
|
return true;
|
||||||
|
} else if (thing->paramValue(tapDialThingUuidSwitchParamTypeId).toString() == uuid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Outdoor sensor consits out of 3 sensors
|
// Outdoor sensor consits out of 3 sensors
|
||||||
if (thing->thingClassId() == outdoorSensorThingClassId) {
|
if (thing->thingClassId() == outdoorSensorThingClassId) {
|
||||||
if (thing->paramValue(outdoorSensorThingSensorUuidLightParamTypeId).toString() == uuid) {
|
if (thing->paramValue(outdoorSensorThingSensorUuidLightParamTypeId).toString() == uuid) {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
#include "huelight.h"
|
#include "huelight.h"
|
||||||
#include "hueremote.h"
|
#include "hueremote.h"
|
||||||
#include "huemotionsensor.h"
|
#include "huemotionsensor.h"
|
||||||
|
#include "huetapdial.h"
|
||||||
|
|
||||||
#include "plugintimer.h"
|
#include "plugintimer.h"
|
||||||
#include "network/networkaccessmanager.h"
|
#include "network/networkaccessmanager.h"
|
||||||
|
|
@ -73,7 +74,13 @@ private slots:
|
||||||
void lightStateChanged();
|
void lightStateChanged();
|
||||||
void remoteStateChanged();
|
void remoteStateChanged();
|
||||||
void onRemoteButtonEvent(int buttonCode);
|
void onRemoteButtonEvent(int buttonCode);
|
||||||
void onRemoteRotaryEvent(int rotationCode);
|
|
||||||
|
// Tap Dial
|
||||||
|
void onTapDialReachableChanged(bool reachable);
|
||||||
|
void onTapDialBatteryLevelChanged(int batteryLevel);
|
||||||
|
void onTapDialRotaryEvent(int rotationCode);
|
||||||
|
void onTapDialButtonEvent(int buttonCode);
|
||||||
|
|
||||||
|
|
||||||
// Motion sensor
|
// Motion sensor
|
||||||
void onMotionSensorReachableChanged(bool reachable);
|
void onMotionSensorReachableChanged(bool reachable);
|
||||||
|
|
@ -122,6 +129,7 @@ private:
|
||||||
QHash<HueBridge *, Thing *> m_bridges;
|
QHash<HueBridge *, Thing *> m_bridges;
|
||||||
QHash<HueLight *, Thing *> m_lights;
|
QHash<HueLight *, Thing *> m_lights;
|
||||||
QHash<HueRemote *, Thing *> m_remotes;
|
QHash<HueRemote *, Thing *> m_remotes;
|
||||||
|
QHash<HueTapDial *, Thing *> m_tapDials;
|
||||||
QHash<HueMotionSensor *, Thing *> m_motionSensors;
|
QHash<HueMotionSensor *, Thing *> m_motionSensors;
|
||||||
|
|
||||||
void refreshLight(Thing *thing);
|
void refreshLight(Thing *thing);
|
||||||
|
|
|
||||||
|
|
@ -687,13 +687,6 @@
|
||||||
"type" : "QString",
|
"type" : "QString",
|
||||||
"readOnly": true
|
"readOnly": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "65748463-dd3f-430d-871c-dd7ee4db0b1c",
|
|
||||||
"name": "type",
|
|
||||||
"displayName": "type",
|
|
||||||
"type" : "QString",
|
|
||||||
"readOnly": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "e2365a3c-cdf3-4b1e-b908-e7642e467f20",
|
"id": "e2365a3c-cdf3-4b1e-b908-e7642e467f20",
|
||||||
"name": "uuid",
|
"name": "uuid",
|
||||||
|
|
@ -702,11 +695,32 @@
|
||||||
"readOnly": true
|
"readOnly": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "9263bef9-4dd9-4658-b798-cd39fcb70fee",
|
"id": "dead7cf0-3ecc-4332-8fc6-42d4e71f508c",
|
||||||
"name": "sensorId",
|
"name": "idRotary",
|
||||||
"displayName": "sensor id",
|
"displayName": "Rotary dial id",
|
||||||
"type" : "int",
|
"type" : "int",
|
||||||
"readOnly": true
|
"readOnly": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "267bcb24-b5c1-421d-bc6a-9b8fc7b43696",
|
||||||
|
"name": "uuidRotary",
|
||||||
|
"displayName": "Rotary dial uuid",
|
||||||
|
"type" : "QString",
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5269c70c-49e6-4090-aa57-3c89ee328b1e",
|
||||||
|
"name": "idSwitch",
|
||||||
|
"displayName": "Switch id",
|
||||||
|
"type" : "int",
|
||||||
|
"readOnly": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ae7ce90a-9bfb-45e4-90e4-8e491b374249",
|
||||||
|
"name": "uuidSwitch",
|
||||||
|
"displayName": "Switch uuid",
|
||||||
|
"type" : "QString",
|
||||||
|
"readOnly": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settingsTypes": [
|
"settingsTypes": [
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue