Merge PR #381: Shelly: Add support for shelly i3
This commit is contained in:
commit
c91efd2d54
@ -14,6 +14,8 @@ The currently supported devices are:
|
||||
* Shelly Button 1
|
||||
* Shelly 3EM
|
||||
* Shelly H+T
|
||||
* Shelly i3
|
||||
|
||||
|
||||
## Requirements
|
||||
Shelly devices communicate with via MQTT. This means, in order to add Shelly devices to nymea, the nymea instance is required
|
||||
|
||||
@ -69,6 +69,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_idParamTypeMap[shellyButton1ThingClassId] = shellyButton1ThingIdParamTypeId;
|
||||
m_idParamTypeMap[shellyEm3ThingClassId] = shellyEm3ThingIdParamTypeId;
|
||||
m_idParamTypeMap[shellyHTThingClassId] = shellyHTThingIdParamTypeId;
|
||||
m_idParamTypeMap[shellyI3ThingClassId] = shellyI3ThingIdParamTypeId;
|
||||
|
||||
m_usernameParamTypeMap[shelly1ThingClassId] = shelly1ThingUsernameParamTypeId;
|
||||
m_usernameParamTypeMap[shelly1pmThingClassId] = shelly1pmThingUsernameParamTypeId;
|
||||
@ -81,6 +82,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_usernameParamTypeMap[shellyButton1ThingClassId] = shellyButton1ThingUsernameParamTypeId;
|
||||
m_usernameParamTypeMap[shellyEm3ThingClassId] = shellyEm3ThingUsernameParamTypeId;
|
||||
m_usernameParamTypeMap[shellyHTThingClassId] = shellyHTThingUsernameParamTypeId;
|
||||
m_usernameParamTypeMap[shellyI3ThingClassId] = shellyI3ThingUsernameParamTypeId;
|
||||
|
||||
m_passwordParamTypeMap[shelly1ThingClassId] = shelly1ThingPasswordParamTypeId;
|
||||
m_passwordParamTypeMap[shelly1pmThingClassId] = shelly1pmThingPasswordParamTypeId;
|
||||
@ -93,6 +95,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_passwordParamTypeMap[shellyButton1ThingClassId] = shellyButton1ThingPasswordParamTypeId;
|
||||
m_passwordParamTypeMap[shellyEm3ThingClassId] = shellyEm3ThingPasswordParamTypeId;
|
||||
m_passwordParamTypeMap[shellyHTThingClassId] = shellyHTThingPasswordParamTypeId;
|
||||
m_passwordParamTypeMap[shellyI3ThingClassId] = shellyI3ThingPasswordParamTypeId;
|
||||
|
||||
m_connectedDeviceParamTypeMap[shelly2ThingClassId] = shelly2ThingConnectedDevice1ParamTypeId;
|
||||
m_connectedDeviceParamTypeMap[shelly25ThingClassId] = shelly25ThingConnectedDevice1ParamTypeId;
|
||||
@ -128,6 +131,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_connectedStateTypesMap[shellyLightPMThingClassId] = shellyLightPMConnectedStateTypeId;
|
||||
m_connectedStateTypesMap[shellySocketPMThingClassId] = shellySocketPMConnectedStateTypeId;
|
||||
m_connectedStateTypesMap[shellyRollerThingClassId] = shellyRollerConnectedStateTypeId;
|
||||
m_connectedStateTypesMap[shellyI3ThingClassId] = shellyI3ConnectedStateTypeId;
|
||||
|
||||
m_signalStrengthStateTypesMap[shelly1ThingClassId] = shelly1SignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypesMap[shelly1pmThingClassId] = shelly1pmSignalStrengthStateTypeId;
|
||||
@ -148,6 +152,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_signalStrengthStateTypesMap[shellyLightPMThingClassId] = shellyLightPMSignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypesMap[shellySocketPMThingClassId] = shellySocketPMSignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypesMap[shellyRollerThingClassId] = shellyRollerSignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypesMap[shellyI3ThingClassId] = shellyI3SignalStrengthStateTypeId;
|
||||
|
||||
m_powerStateTypeMap[shelly1ThingClassId] = shelly1PowerStateTypeId;
|
||||
m_powerStateTypeMap[shelly1pmThingClassId] = shelly1pmPowerStateTypeId;
|
||||
@ -198,6 +203,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_updateStatusStateTypesMap[shellyButton1ThingClassId] = shellyButton1UpdateStatusStateTypeId;
|
||||
m_updateStatusStateTypesMap[shellyEm3ThingClassId] = shellyEm3UpdateStatusStateTypeId;
|
||||
m_updateStatusStateTypesMap[shellyHTThingClassId] = shellyHTUpdateStatusStateTypeId;
|
||||
m_updateStatusStateTypesMap[shellyI3ThingClassId] = shellyI3UpdateStatusStateTypeId;
|
||||
|
||||
m_currentVersionStateTypesMap[shelly1ThingClassId] = shelly1CurrentVersionStateTypeId;
|
||||
m_currentVersionStateTypesMap[shelly1pmThingClassId] = shelly1pmCurrentVersionStateTypeId;
|
||||
@ -210,6 +216,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_currentVersionStateTypesMap[shellyButton1ThingClassId] = shellyButton1CurrentVersionStateTypeId;
|
||||
m_currentVersionStateTypesMap[shellyEm3ThingClassId] = shellyEm3CurrentVersionStateTypeId;
|
||||
m_currentVersionStateTypesMap[shellyHTThingClassId] = shellyHTCurrentVersionStateTypeId;
|
||||
m_currentVersionStateTypesMap[shellyI3ThingClassId] = shellyI3CurrentVersionStateTypeId;
|
||||
|
||||
m_availableVersionStateTypesMap[shelly1ThingClassId] = shelly1AvailableVersionStateTypeId;
|
||||
m_availableVersionStateTypesMap[shelly1pmThingClassId] = shelly1pmAvailableVersionStateTypeId;
|
||||
@ -222,6 +229,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_availableVersionStateTypesMap[shellyButton1ThingClassId] = shellyButton1AvailableVersionStateTypeId;
|
||||
m_availableVersionStateTypesMap[shellyEm3ThingClassId] = shellyEm3AvailableVersionStateTypeId;
|
||||
m_availableVersionStateTypesMap[shellyHTThingClassId] = shellyHTAvailableVersionStateTypeId;
|
||||
m_availableVersionStateTypesMap[shellyI3ThingClassId] = shellyI3AvailableVersionStateTypeId;
|
||||
|
||||
m_batteryLevelStateTypeMap[shellyButton1ThingClassId] = shellyButton1BatteryLevelStateTypeId;
|
||||
m_batteryLevelStateTypeMap[shellyHTThingClassId] = shellyHTBatteryLevelStateTypeId;
|
||||
@ -238,6 +246,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_rebootActionTypeMap[shellyDimmerRebootActionTypeId] = shellyDimmerThingClassId;
|
||||
m_rebootActionTypeMap[shelly2RebootActionTypeId] = shelly2ThingClassId;
|
||||
m_rebootActionTypeMap[shelly25RebootActionTypeId] = shelly25ThingClassId;
|
||||
m_rebootActionTypeMap[shellyI3RebootActionTypeId] = shellyI3ThingClassId;
|
||||
|
||||
m_powerActionTypesMap[shelly1PowerActionTypeId] = shelly1ThingClassId;
|
||||
m_powerActionTypesMap[shelly1pmPowerActionTypeId] = shelly1pmThingClassId;
|
||||
@ -296,6 +305,7 @@ IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
m_updateActionTypesMap[shellyButton1PerformUpdateActionTypeId] = shellyButton1ThingClassId;
|
||||
m_updateActionTypesMap[shellyEm3PerformUpdateActionTypeId] = shellyEm3ThingClassId;
|
||||
m_updateActionTypesMap[shellyHTPerformUpdateActionTypeId] = shellyHTThingClassId;
|
||||
m_updateActionTypesMap[shellyI3PerformUpdateActionTypeId] = shellyI3ThingClassId;
|
||||
}
|
||||
|
||||
IntegrationPluginShelly::~IntegrationPluginShelly()
|
||||
@ -334,6 +344,8 @@ void IntegrationPluginShelly::discoverThings(ThingDiscoveryInfo *info)
|
||||
namePattern = QRegExp("^shellyem3-[0-9A-Z]+$");
|
||||
} else if (info->thingClassId() == shellyHTThingClassId) {
|
||||
namePattern = QRegExp("shellyht-[0-9A-Z]+$");
|
||||
} else if (info->thingClassId() == shellyI3ThingClassId) {
|
||||
namePattern = QRegExp("shellyix3-[0-9A-Z]+$");
|
||||
}
|
||||
if (!entry.name().contains(namePattern)) {
|
||||
continue;
|
||||
@ -659,6 +671,25 @@ void IntegrationPluginShelly::onPublishReceived(MqttChannel *channel, const QStr
|
||||
// "1" or "0"
|
||||
// Emit event button pressed
|
||||
bool on = payload == "1";
|
||||
if (thing->thingClassId() == shellyI3ThingClassId) {
|
||||
if (channel == 0) {
|
||||
if (thing->stateValue(shellyI3Input1StateTypeId).toBool() != on) {
|
||||
thing->setStateValue(shellyI3Input1StateTypeId, on);
|
||||
emit emitEvent(Event(shellyI3Input1EventTypeId, thing->id()));
|
||||
}
|
||||
} else if (channel == 1) {
|
||||
if (thing->stateValue(shellyI3Input2StateTypeId).toBool() != on) {
|
||||
thing->setStateValue(shellyI3Input2StateTypeId, on);
|
||||
emit emitEvent(Event(shellyI3Input2EventTypeId, thing->id()));
|
||||
}
|
||||
} else {
|
||||
if (thing->stateValue(shellyI3Input3StateTypeId).toBool() != on) {
|
||||
thing->setStateValue(shellyI3Input3StateTypeId, on);
|
||||
emit emitEvent(Event(shellyI3Input3EventTypeId, thing->id()));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
if (child->thingClassId() == shellySwitchThingClassId && child->paramValue(shellySwitchThingChannelParamTypeId).toInt() == channel + 1) {
|
||||
if (child->stateValue(shellySwitchPowerStateTypeId).toBool() != on) {
|
||||
@ -680,7 +711,6 @@ void IntegrationPluginShelly::onPublishReceived(MqttChannel *channel, const QStr
|
||||
if (m_powerStateTypeMap.contains(thing->thingClassId())) {
|
||||
thing->setStateValue(m_powerStateTypeMap.value(thing->thingClassId()), on);
|
||||
}
|
||||
|
||||
// And switch all childs of this shelly too
|
||||
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
if (m_powerStateTypeMap.contains(child->thingClassId())) {
|
||||
@ -817,8 +847,8 @@ void IntegrationPluginShelly::onPublishReceived(MqttChannel *channel, const QStr
|
||||
}
|
||||
}
|
||||
|
||||
if (topic == "shellies/" + shellyId + "/input_event/0") {
|
||||
if (thing->thingClassId() == shellyButton1ThingClassId) {
|
||||
if (topic.startsWith("shellies/" + shellyId + "/input_event/")) {
|
||||
if (thing->thingClassId() == shellyButton1ThingClassId) { // it can be only at channel 0
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
@ -834,6 +864,37 @@ void IntegrationPluginShelly::onPublishReceived(MqttChannel *channel, const QStr
|
||||
QString param = QString::number(event.length());
|
||||
thing->emitEvent(eventTypeId, ParamList() << Param(paramTypeId, param));
|
||||
}
|
||||
if (thing->thingClassId() == shellyI3ThingClassId) {
|
||||
int channel = topic.split("/").last().toInt();
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcShelly()) << "Failed to parse JSON from shelly:" << error.errorString() << qUtf8Printable(payload);
|
||||
return;
|
||||
}
|
||||
QString event = jsonDoc.toVariant().toMap().value("event").toString();
|
||||
if (event.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
QString param = "";
|
||||
EventTypeId eventTypeId = shellyI3LongPressedEventTypeId;;
|
||||
ParamTypeId paramTypeId = shellyI3LongPressedEventButtonNameParamTypeId;
|
||||
ParamTypeId param2TypeId = shellyI3LongPressedEventOriginParamTypeId;
|
||||
if (event == "L") {
|
||||
param = "1";
|
||||
} else if (event == "SL") {
|
||||
param = "2";
|
||||
} else if (event == "LS") {
|
||||
param = "3";
|
||||
} else { // short press
|
||||
param = QString::number(event.length());
|
||||
eventTypeId = shellyI3PressedEventTypeId;
|
||||
paramTypeId = shellyI3PressedEventButtonNameParamTypeId;
|
||||
param2TypeId = shellyI3PressedEventOriginParamTypeId;
|
||||
}
|
||||
QString usedSwitch = QString::number(channel + 1);
|
||||
thing->emitEvent(eventTypeId, ParamList() << Param(paramTypeId, param) << Param(param2TypeId, usedSwitch));
|
||||
}
|
||||
}
|
||||
|
||||
topicMatcher = QRegExp("shellies/" + shellyId + "/emeter/[0-2]/.*");
|
||||
|
||||
@ -1103,6 +1103,164 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a4557bcc-bdae-4178-b774-5881a8ae490a",
|
||||
"name": "shellyI3",
|
||||
"displayName": "Shelly I3",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": [ "longpressmultibutton", "wirelessconnectable", "update" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "12431172-432b-496e-a6b7-7465753a0bd9",
|
||||
"name":"id",
|
||||
"displayName": "Shelly ID",
|
||||
"type": "QString",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "34a20277-bf0c-4fd5-8ae1-b3019681fa82",
|
||||
"name": "username",
|
||||
"displayName": "Username (optional)",
|
||||
"type": "QString"
|
||||
},
|
||||
{
|
||||
"id": "ccc56409-1424-4bf7-8dac-84431c3e7a84",
|
||||
"name": "password",
|
||||
"displayName": "Password (optional)",
|
||||
"type": "QString"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "9b17b10d-07ee-4a3d-813f-ef37e79e7241",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "54fc5565-5d40-4847-b59e-95bfd8845381",
|
||||
"name": "signalStrength",
|
||||
"displayName": "Signal strength",
|
||||
"displayNameEvent": "Signal strength changed",
|
||||
"type": "uint",
|
||||
"unit": "Percentage",
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"defaultValue": 100
|
||||
},
|
||||
{
|
||||
"id": "61e98cc9-4449-4fb2-818e-692303244ce2",
|
||||
"name": "input1",
|
||||
"displayName": "Input 1",
|
||||
"displayNameEvent": "Input 1 changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"ioType" : "digitalInput"
|
||||
},
|
||||
{
|
||||
"id": "04497ff2-a231-4d3d-adeb-66275a3b128b",
|
||||
"name": "input2",
|
||||
"displayName": "Input 2",
|
||||
"displayNameEvent": "Input 2 changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"ioType" : "digitalInput"
|
||||
},
|
||||
{
|
||||
"id": "5895fc2d-19a4-40c2-8522-7c4462e55a3e",
|
||||
"name": "input3",
|
||||
"displayName": "Input 3",
|
||||
"displayNameEvent": "Input 3 changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"ioType" : "digitalInput"
|
||||
},
|
||||
{
|
||||
"id": "889d7f2c-488c-4c91-905d-8669125d5c8b",
|
||||
"name": "updateStatus",
|
||||
"displayName": "Update status",
|
||||
"displayNameEvent": "Update status changed",
|
||||
"type": "QString",
|
||||
"possibleValues": ["idle", "available", "updating"],
|
||||
"defaultValue": "idle"
|
||||
},
|
||||
{
|
||||
"id": "33e7d186-7c6b-4c4e-89c3-80362ef76615",
|
||||
"name": "currentVersion",
|
||||
"displayName": "Firmware version",
|
||||
"displayNameEvent": "Firmware version changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "c3ff6d31-7301-412f-9aff-72ac36ba83c9",
|
||||
"name": "availableVersion",
|
||||
"displayName": "Available firmware version",
|
||||
"displayNameEvent": "Available firmware version changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"eventTypes": [
|
||||
{
|
||||
"id": "79648810-b2f4-4aa5-902f-2875242e7bf8",
|
||||
"name": "pressed",
|
||||
"displayName": "Short Pressed",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "146313a1-cfb6-4732-a1be-86ec575bcbdb",
|
||||
"name": "buttonName",
|
||||
"displayName": "Count",
|
||||
"type": "QString",
|
||||
"allowedValues": ["1", "2", "3"]
|
||||
},
|
||||
{
|
||||
"id": "0ed31339-7457-443c-b6e3-3b8ce3fc2bd8",
|
||||
"name": "origin",
|
||||
"displayName": "Switch",
|
||||
"type": "QString",
|
||||
"allowedValues": ["1", "2", "3"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bb966833-a7a6-4ad7-b5f5-057b38ebb036",
|
||||
"name": "longPressed",
|
||||
"displayName": "Long Pressed",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "99683cf9-930e-4f10-94f2-73bb32092639",
|
||||
"name": "buttonName",
|
||||
"displayName": "Count",
|
||||
"type": "QString",
|
||||
"allowedValues": ["1", "2", "3"]
|
||||
},
|
||||
{
|
||||
"id": "866d6db6-e989-4b19-93c3-cc4aa7453c9e",
|
||||
"name": "origin",
|
||||
"displayName": "Switch",
|
||||
"type": "QString",
|
||||
"allowedValues": ["1", "2", "3"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "162e7791-6890-4075-8e57-a4c15b9359bb",
|
||||
"name": "reboot",
|
||||
"displayName": "Reboot"
|
||||
},
|
||||
{
|
||||
"id": "1c677ecb-c54e-4c95-a3f7-e68fabeeda08",
|
||||
"name": "performUpdate",
|
||||
"displayName": "Update firmware"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cc75be5c-8e34-4f72-a55d-c96e4c85d4be",
|
||||
"name": "shellyHT",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user