Merge PR #690: Shelly: Rework Gen 2 device handling
commit
bd5eb8d6b0
|
|
@ -61,142 +61,6 @@ static QHash<QString, QString> updateStatusMap = {
|
|||
{"unknown", "idle"}
|
||||
};
|
||||
|
||||
static QHash<ThingClassId, StateTypeId> colorTemperatureStateTypeMap = {
|
||||
{shellyRgbw2ThingClassId, shellyRgbw2ColorTemperatureStateTypeId},
|
||||
};
|
||||
|
||||
// Actions and their params
|
||||
static QHash<ActionTypeId, ThingClassId> rebootActionTypeMap = {
|
||||
{shelly1RebootActionTypeId, shelly1ThingClassId},
|
||||
{shelly1pmRebootActionTypeId, shelly1pmThingClassId},
|
||||
{shelly1lRebootActionTypeId, shelly1lThingClassId},
|
||||
{shellyPlugRebootActionTypeId, shellyPlugThingClassId},
|
||||
{shellyPlusPlugRebootActionTypeId, shellyPlusPlugThingClassId},
|
||||
{shellyRgbw2RebootActionTypeId, shellyRgbw2ThingClassId},
|
||||
{shellyDimmerRebootActionTypeId, shellyDimmerThingClassId},
|
||||
{shelly2RebootActionTypeId, shelly2ThingClassId},
|
||||
{shelly25RebootActionTypeId, shelly25ThingClassId},
|
||||
{shellyI3RebootActionTypeId, shellyI3ThingClassId},
|
||||
{shellyTrvRebootActionTypeId, shellyTrvThingClassId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> powerActionTypesMap = {
|
||||
{shelly1PowerActionTypeId, shelly1ThingClassId},
|
||||
{shelly1pmPowerActionTypeId, shelly1pmThingClassId},
|
||||
{shelly1lPowerActionTypeId, shelly1lThingClassId},
|
||||
{shellyPlugPowerActionTypeId, shellyPlugThingClassId},
|
||||
{shellyPlusPlugPowerActionTypeId, shellyPlusPlugThingClassId},
|
||||
{shellyEmPowerActionTypeId, shellyEmThingClassId},
|
||||
{shellyEm3PowerActionTypeId, shellyEm3ThingClassId},
|
||||
{shelly2Channel1ActionTypeId, shelly2ThingClassId},
|
||||
{shelly2Channel2ActionTypeId, shelly2ThingClassId},
|
||||
{shelly25Channel1ActionTypeId, shelly25ThingClassId},
|
||||
{shelly25Channel2ActionTypeId, shelly25ThingClassId}
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> powerActionParamTypesMap = {
|
||||
{shelly1PowerActionTypeId, shelly1PowerActionPowerParamTypeId},
|
||||
{shelly1pmPowerActionTypeId, shelly1pmPowerActionPowerParamTypeId},
|
||||
{shelly1lPowerActionTypeId, shelly1lPowerActionPowerParamTypeId},
|
||||
{shellyPlugPowerActionTypeId, shellyPlugPowerActionPowerParamTypeId},
|
||||
{shellyPlusPlugPowerActionTypeId, shellyPlusPlugPowerActionPowerParamTypeId},
|
||||
{shellyEmPowerActionTypeId, shellyEmPowerActionPowerParamTypeId},
|
||||
{shellyEm3PowerActionTypeId, shellyEm3PowerActionPowerParamTypeId},
|
||||
{shelly2Channel1ActionTypeId, shelly2Channel1ActionChannel1ParamTypeId},
|
||||
{shelly2Channel2ActionTypeId, shelly2Channel2ActionChannel2ParamTypeId},
|
||||
{shelly25Channel1ActionTypeId, shelly25Channel1ActionChannel1ParamTypeId},
|
||||
{shelly25Channel2ActionTypeId, shelly25Channel2ActionChannel2ParamTypeId}
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> colorPowerActionTypesMap = {
|
||||
{shellyRgbw2PowerActionTypeId, shellyRgbw2ThingClassId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> colorPowerActionParamTypesMap = {
|
||||
{shellyRgbw2PowerActionPowerParamTypeId, shellyRgbw2PowerActionTypeId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> colorActionTypesMap = {
|
||||
{shellyRgbw2ColorActionTypeId, shellyRgbw2ThingClassId},
|
||||
};
|
||||
|
||||
static QHash<ParamTypeId, ActionTypeId> colorActionParamTypesMap = {
|
||||
{shellyRgbw2ColorActionTypeId, shellyRgbw2ColorActionTypeId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> colorBrightnessActionTypesMap = {
|
||||
{shellyRgbw2BrightnessActionTypeId, shellyRgbw2ThingClassId},
|
||||
};
|
||||
|
||||
static QHash<ParamTypeId, ActionTypeId> colorBrightnessActionParamTypesMap = {
|
||||
{shellyRgbw2BrightnessActionBrightnessParamTypeId, shellyRgbw2BrightnessActionTypeId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> colorTemperatureActionTypesMap = {
|
||||
{shellyRgbw2ColorTemperatureActionTypeId, shellyRgbw2ThingClassId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> colorTemperatureActionParamTypesMap = {
|
||||
{shellyRgbw2ColorTemperatureActionTypeId, shellyRgbw2ColorTemperatureActionColorTemperatureParamTypeId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> dimmablePowerActionTypesMap = {
|
||||
{shellyDimmerPowerActionTypeId, shellyDimmerThingClassId},
|
||||
};
|
||||
|
||||
static QHash<ParamTypeId, ActionTypeId> dimmablePowerActionParamTypesMap = {
|
||||
{shellyDimmerPowerActionTypeId, shellyDimmerPowerActionPowerParamTypeId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> dimmableBrightnessActionTypesMap = {
|
||||
{shellyDimmerBrightnessActionTypeId, shellyDimmerThingClassId},
|
||||
};
|
||||
|
||||
static QHash<ParamTypeId, ActionTypeId> dimmableBrightnessActionParamTypesMap = {
|
||||
{shellyDimmerBrightnessActionTypeId, shellyDimmerBrightnessActionBrightnessParamTypeId},
|
||||
};
|
||||
|
||||
static QHash<ActionTypeId, ThingClassId> updateActionTypesMap = {
|
||||
{shelly1PerformUpdateActionTypeId, shelly1ThingClassId},
|
||||
{shelly1pmPerformUpdateActionTypeId, shelly1pmThingClassId},
|
||||
{shelly1lPerformUpdateActionTypeId, shelly1lThingClassId},
|
||||
{shelly2PerformUpdateActionTypeId, shelly2ThingClassId},
|
||||
{shelly25PerformUpdateActionTypeId, shelly25ThingClassId},
|
||||
{shellyPlugPerformUpdateActionTypeId, shellyPlugThingClassId},
|
||||
{shellyPlusPlugPerformUpdateActionTypeId, shellyPlusPlugThingClassId},
|
||||
{shellyRgbw2PerformUpdateActionTypeId, shellyRgbw2ThingClassId},
|
||||
{shellyDimmerPerformUpdateActionTypeId, shellyDimmerThingClassId},
|
||||
{shellyButton1PerformUpdateActionTypeId, shellyButton1ThingClassId},
|
||||
{shellyEmPerformUpdateActionTypeId, shellyEmThingClassId},
|
||||
{shellyEm3PerformUpdateActionTypeId, shellyEm3ThingClassId},
|
||||
{shellyHTPerformUpdateActionTypeId, shellyHTThingClassId},
|
||||
{shellyI3PerformUpdateActionTypeId, shellyI3ThingClassId},
|
||||
{shellyMotionPerformUpdateActionTypeId, shellyMotionThingClassId},
|
||||
{shellyTrvPerformUpdateActionTypeId, shellyTrvThingClassId},
|
||||
{shellyFloodPerformUpdateActionTypeId, shellyFloodThingClassId},
|
||||
{shellySmokePerformUpdateActionTypeId, shellySmokeThingClassId},
|
||||
{shellyGasPerformUpdateActionTypeId, shellyGasThingClassId}
|
||||
};
|
||||
|
||||
// Settings
|
||||
static QHash<ThingClassId, ParamTypeId> longpushMinDurationSettingIds = {
|
||||
{shellyI3ThingClassId, shellyI3SettingsLongpushMinDurationParamTypeId}
|
||||
};
|
||||
static QHash<ThingClassId, ParamTypeId> longpushMaxDurationSettingIds = {
|
||||
{shellyButton1ThingClassId, shellyButton1SettingsLongpushMaxDurationParamTypeId},
|
||||
{shellyI3ThingClassId, shellyI3SettingsLongpushMaxDurationParamTypeId}
|
||||
};
|
||||
static QHash<ThingClassId, ParamTypeId> multipushTimeBetweenPushesSettingIds = {
|
||||
{shellyButton1ThingClassId, shellyButton1SettingsMultipushTimeBetweenPushesParamTypeId},
|
||||
{shellyI3ThingClassId, shellyI3SettingsMultipushTimeBetweenPushesParamTypeId}
|
||||
};
|
||||
static QHash<ThingClassId, ParamTypeId> defaultStateSettingIds = {
|
||||
{shellyPlusPlugThingClassId, shellyPlusPlugSettingsDefaultStateParamTypeId}
|
||||
};
|
||||
static QHash<ThingClassId, ParamTypeId> ledModeSettingIds = {
|
||||
{shellyPlusPlugThingClassId, shellyPlusPlugSettingsLedModeParamTypeId}
|
||||
};
|
||||
|
||||
IntegrationPluginShelly::IntegrationPluginShelly()
|
||||
{
|
||||
}
|
||||
|
|
@ -220,9 +84,13 @@ void IntegrationPluginShelly::discoverThings(ThingDiscoveryInfo *info)
|
|||
qCDebug(dcShelly()) << "Have entry" << entry;
|
||||
QRegExp namePattern;
|
||||
if (info->thingClassId() == shelly1ThingClassId) {
|
||||
namePattern = QRegExp("^(shelly1|ShellyPlus1)-[0-9A-Z]+$");
|
||||
namePattern = QRegExp("^shelly1-[0-9A-Z]+$");
|
||||
} else if (info->thingClassId() == shellyPlus1ThingClassId) {
|
||||
namePattern = QRegExp("^ShellyPlus1-[0-9A-Z]+$");
|
||||
} else if (info->thingClassId() == shelly1pmThingClassId) {
|
||||
namePattern = QRegExp("^(shelly1pm|ShellyPlus1PM)-[0-9A-Z]+$");
|
||||
namePattern = QRegExp("^shelly1pm-[0-9A-Z]+$");
|
||||
} else if (info->thingClassId() == shellyPlus1pmThingClassId) {
|
||||
namePattern = QRegExp("^ShellyPlus1PM-[0-9A-Z]+$");
|
||||
} else if (info->thingClassId() == shelly1lThingClassId) {
|
||||
namePattern = QRegExp("^shelly1l-[0-9A-Z]+$");
|
||||
} else if (info->thingClassId() == shellyPlugThingClassId) {
|
||||
|
|
@ -290,6 +158,55 @@ void IntegrationPluginShelly::discoverThings(ThingDiscoveryInfo *info)
|
|||
info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
|
||||
void IntegrationPluginShelly::startPairing(ThingPairingInfo *info)
|
||||
{
|
||||
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter the password for your Shelly device. By default this is empty."));
|
||||
}
|
||||
|
||||
void IntegrationPluginShelly::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password)
|
||||
{
|
||||
Q_UNUSED(username)
|
||||
|
||||
qCDebug(dcShelly) << "Confirm pairing called";
|
||||
ThingClass thingClass = supportedThings().findById(info->thingClassId());
|
||||
QString shellyId = info->params().paramValue(thingClass.paramTypes().findByName("id").id()).toString();
|
||||
ZeroConfServiceEntry zeroConfEntry;
|
||||
foreach (const ZeroConfServiceEntry &entry, m_zeroconfBrowser->serviceEntries()) {
|
||||
if (entry.name() == shellyId) {
|
||||
zeroConfEntry = entry;
|
||||
}
|
||||
}
|
||||
QHostAddress address = zeroConfEntry.hostAddress();
|
||||
|
||||
if (address.isNull()) {
|
||||
qCWarning(dcShelly()) << "Unable to determine Shelly's network address. Failed to set up device.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Unable to find the thing in the network."));
|
||||
return;
|
||||
}
|
||||
|
||||
ShellyJsonRpcClient *client = new ShellyJsonRpcClient(info);
|
||||
client->open(address, "admin", password, shellyId);
|
||||
connect(client, &ShellyJsonRpcClient::stateChanged, info, [info, client, this, password](QAbstractSocket::SocketState state) {
|
||||
qCDebug(dcShelly()) << "Websocket state changed:" << state;
|
||||
// GetDeviceInfo wouldn't require authentication if enabled, so if the setup is changed to fetch some info from GetDeviceInfo,
|
||||
// make sure to not just replace the GetStatus call, or authentication verification won't work any more.
|
||||
ShellyRpcReply *reply = client->sendRequest("Shelly.GetStatus");
|
||||
connect(reply, &ShellyRpcReply::finished, info, [info, client, this, password](ShellyRpcReply::Status status, const QVariantMap &/*response*/){
|
||||
if (status != ShellyRpcReply::StatusSuccess) {
|
||||
qCWarning(dcShelly) << "Error during shelly paring";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
qCDebug(dcShelly) << "Pairing successful!";
|
||||
pluginStorage()->beginGroup(info->thingId().toString());
|
||||
pluginStorage()->setValue("password", password);
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginShelly::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
|
|
@ -338,6 +255,13 @@ void IntegrationPluginShelly::thingRemoved(Thing *thing)
|
|||
if (m_rpcClients.contains(thing)) {
|
||||
m_rpcClients.remove(thing); // Deleted by parenting
|
||||
}
|
||||
|
||||
if (thing->parentId().isNull()) { // Only parents (gen1 and gen2) store stuff in the storage
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
pluginStorage()->remove("");
|
||||
pluginStorage()->endGroup();
|
||||
}
|
||||
|
||||
qCDebug(dcShelly()) << "Device removed" << thing->name();
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +280,8 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
url.setPassword(thing->paramValue("password").toString());
|
||||
}
|
||||
|
||||
if (rebootActionTypeMap.contains(action.actionTypeId())) {
|
||||
ActionType actionType = thing->thingClass().actionTypes().findById(action.actionTypeId());
|
||||
if (actionType.name() == "reboot") {
|
||||
if (isGen2(shellyId)) {
|
||||
ShellyRpcReply *reply = m_rpcClients.value(thing)->sendRequest("Shelly.Reboot");
|
||||
connect(reply, &ShellyRpcReply::finished, info, [info](ShellyRpcReply::Status status, const QVariantMap &/*response*/){
|
||||
|
|
@ -376,59 +301,28 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (updateActionTypesMap.contains(action.actionTypeId())) {
|
||||
url.setPath("/ota");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("update", "true");
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [info, reply](){
|
||||
info->finish(reply->error() == QNetworkReply::NoError ? Thing::ThingErrorNoError : Thing::ThingErrorHardwareFailure);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (powerActionTypesMap.contains(action.actionTypeId())) {
|
||||
int relay = 1;
|
||||
QHash<ActionTypeId, int> actionChannelMap = {
|
||||
{shelly25Channel1ActionTypeId, 1},
|
||||
{shelly25Channel2ActionTypeId, 2}
|
||||
};
|
||||
if (!thing->thingClass().paramTypes().findByName("channel").id().isNull()) {
|
||||
relay = thing->paramValue("channel").toInt();
|
||||
} else if (actionChannelMap.contains(action.actionTypeId())) {
|
||||
relay = actionChannelMap.value(action.actionTypeId());
|
||||
}
|
||||
|
||||
ParamTypeId powerParamTypeId = powerActionParamTypesMap.value(action.actionTypeId());
|
||||
bool on = action.param(powerParamTypeId).value().toBool();
|
||||
|
||||
if (actionType.name() == "performUpdate") {
|
||||
if (isGen2(shellyId)) {
|
||||
QVariantMap params;
|
||||
params.insert("id", relay - 1);
|
||||
params.insert("on", on);
|
||||
ShellyRpcReply *reply = m_rpcClients.value(thing)->sendRequest("Switch.Set", params); // Switch.Set not supported by Shelly Plus 2PM in shutter mode; will return error "No handler for Switch.Set"
|
||||
ShellyRpcReply *reply = m_rpcClients.value(thing)->sendRequest("Shelly.Update");
|
||||
connect(reply, &ShellyRpcReply::finished, info, [info](ShellyRpcReply::Status status, const QVariantMap &/*response*/){
|
||||
info->finish(status == ShellyRpcReply::StatusSuccess ? Thing::ThingErrorNoError : Thing::ThingErrorHardwareFailure);
|
||||
});
|
||||
} else {
|
||||
url.setPath(QString("/relay/%1").arg(relay - 1));
|
||||
url.setPath("/ota");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("turn", on ? "on" : "off");
|
||||
query.addQueryItem("update", "true");
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [info, reply, on](){
|
||||
info->thing()->setStateValue("power", on);
|
||||
connect(reply, &QNetworkReply::finished, info, [info, reply](){
|
||||
info->finish(reply->error() == QNetworkReply::NoError ? Thing::ThingErrorNoError : Thing::ThingErrorHardwareFailure);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (colorPowerActionTypesMap.contains(action.actionTypeId())) {
|
||||
ParamTypeId colorPowerParamTypeId = colorPowerActionParamTypesMap.value(action.actionTypeId());
|
||||
if (action.actionTypeId() == shellyRgbw2PowerActionTypeId) {
|
||||
ParamTypeId colorPowerParamTypeId = shellyRgbw2PowerActionPowerParamTypeId;
|
||||
bool on = action.param(colorPowerParamTypeId).value().toBool();
|
||||
url.setPath("/color/0");
|
||||
QUrlQuery query;
|
||||
|
|
@ -443,8 +337,9 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (colorActionTypesMap.contains(action.actionTypeId())) {
|
||||
ParamTypeId colorParamTypeId = colorActionParamTypesMap.value(action.actionTypeId());
|
||||
|
||||
if (action.actionTypeId() == shellyRgbw2ColorActionTypeId) {
|
||||
ParamTypeId colorParamTypeId = shellyRgbw2ColorActionColorParamTypeId;
|
||||
QColor color = action.param(colorParamTypeId).value().value<QColor>();
|
||||
url.setPath("/color/0");
|
||||
QUrlQuery query;
|
||||
|
|
@ -476,9 +371,8 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (colorTemperatureStateTypeMap.contains(action.actionTypeId())) {
|
||||
ParamTypeId colorTemperatureParamTypeId = colorTemperatureActionParamTypesMap.value(action.actionTypeId());
|
||||
int ct = action.param(colorTemperatureParamTypeId).value().toInt();
|
||||
if (action.actionTypeId() == shellyRgbw2ColorTemperatureActionTypeId) {
|
||||
int ct = action.param(shellyRgbw2ColorTemperatureActionColorTemperatureParamTypeId).value().toInt();
|
||||
url.setPath("/color/0");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("red", QString::number(qMin(255, ct * 255 / 50)));
|
||||
|
|
@ -495,8 +389,8 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (colorBrightnessActionTypesMap.contains(action.actionTypeId())) {
|
||||
ParamTypeId brightnessParamTypeId = colorBrightnessActionParamTypesMap.value(action.actionTypeId());
|
||||
if (action.actionTypeId() == shellyRgbw2BrightnessActionTypeId) {
|
||||
ParamTypeId brightnessParamTypeId = shellyRgbw2BrightnessActionBrightnessParamTypeId;
|
||||
int brightness = action.param(brightnessParamTypeId).value().toInt();
|
||||
url.setPath("/color/0");
|
||||
QUrlQuery query;
|
||||
|
|
@ -511,8 +405,8 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (dimmablePowerActionTypesMap.contains(action.actionTypeId())) {
|
||||
ParamTypeId powerParamTypeId = dimmablePowerActionParamTypesMap.value(action.actionTypeId());
|
||||
if (action.actionTypeId() == shellyDimmerPowerActionTypeId) {
|
||||
ParamTypeId powerParamTypeId = shellyDimmerPowerActionPowerParamTypeId;
|
||||
bool on = action.param(powerParamTypeId).value().toBool();
|
||||
url.setPath("/light/0");
|
||||
QUrlQuery query;
|
||||
|
|
@ -527,8 +421,8 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (dimmableBrightnessActionTypesMap.contains(action.actionTypeId())) {
|
||||
ParamTypeId brightnessParamTypeId = dimmableBrightnessActionParamTypesMap.value(action.actionTypeId());
|
||||
if (action.actionTypeId() == shellyDimmerBrightnessActionTypeId) {
|
||||
ParamTypeId brightnessParamTypeId = shellyDimmerBrightnessActionBrightnessParamTypeId;
|
||||
int brightness = action.param(brightnessParamTypeId).value().toInt();
|
||||
url.setPath("/light/0");
|
||||
QUrlQuery query;
|
||||
|
|
@ -779,6 +673,44 @@ void IntegrationPluginShelly::executeAction(ThingActionInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (actionType.name() == "power") {
|
||||
int relay = 1;
|
||||
QHash<ActionTypeId, int> actionChannelMap = {
|
||||
{shelly25Channel1ActionTypeId, 1},
|
||||
{shelly25Channel2ActionTypeId, 2}
|
||||
};
|
||||
if (!thing->thingClass().paramTypes().findByName("channel").id().isNull()) {
|
||||
relay = thing->paramValue("channel").toInt();
|
||||
} else if (actionChannelMap.contains(action.actionTypeId())) {
|
||||
relay = actionChannelMap.value(action.actionTypeId());
|
||||
}
|
||||
|
||||
ParamTypeId powerParamTypeId = actionType.id();
|
||||
bool on = action.param(powerParamTypeId).value().toBool();
|
||||
|
||||
if (isGen2(shellyId)) {
|
||||
QVariantMap params;
|
||||
params.insert("id", relay - 1);
|
||||
params.insert("on", on);
|
||||
ShellyRpcReply *reply = m_rpcClients.value(thing)->sendRequest("Switch.Set", params); // Switch.Set not supported by Shelly Plus 2PM in shutter mode; will return error "No handler for Switch.Set"
|
||||
connect(reply, &ShellyRpcReply::finished, info, [info](ShellyRpcReply::Status status, const QVariantMap &/*response*/){
|
||||
info->finish(status == ShellyRpcReply::StatusSuccess ? Thing::ThingErrorNoError : Thing::ThingErrorHardwareFailure);
|
||||
});
|
||||
} else {
|
||||
url.setPath(QString("/relay/%1").arg(relay - 1));
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("turn", on ? "on" : "off");
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [info, reply, on](){
|
||||
info->thing()->setStateValue("power", on);
|
||||
info->finish(reply->error() == QNetworkReply::NoError ? Thing::ThingErrorNoError : Thing::ThingErrorHardwareFailure);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
qCWarning(dcShelly()) << "Unhandled execute action" << info->action().actionTypeId() << "call for device" << thing;
|
||||
}
|
||||
|
||||
|
|
@ -1205,6 +1137,10 @@ void IntegrationPluginShelly::onMulticastMessageReceived(const QHostAddress &sou
|
|||
void IntegrationPluginShelly::updateStatus()
|
||||
{
|
||||
foreach (Thing *thing, myThings().filterByParentId(ThingId())) {
|
||||
if (!thing->setupComplete()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isGen2(thing->paramValue("id").toString())) {
|
||||
fetchStatusGen2(thing);
|
||||
} else {
|
||||
|
|
@ -1327,6 +1263,7 @@ void IntegrationPluginShelly::fetchStatusGen2(Thing *thing)
|
|||
qCWarning(dcShelly()) << "Error updating status from shelly:" << status;
|
||||
return;
|
||||
}
|
||||
qCDebug(dcShelly()) << thing->name() << "Status reply:" << response;
|
||||
int signalStrength = qMin(100, qMax(0, (response.value("wifi").toMap().value("rssi").toInt() + 100) * 2));
|
||||
thing->setStateValue("connected", true);
|
||||
thing->setStateValue("signalStrength", signalStrength);
|
||||
|
|
@ -1342,8 +1279,25 @@ void IntegrationPluginShelly::fetchStatusGen2(Thing *thing)
|
|||
qCWarning(dcShelly()) << "Error updating device info from shelly:" << status;
|
||||
return;
|
||||
}
|
||||
qCDebug(dcShelly()) << thing->name() << "GetDeviceInfo reply:" << response;
|
||||
thing->setStateValue("currentVersion", response.value("ver").toString());
|
||||
});
|
||||
ShellyRpcReply *updateReply = client->sendRequest("Shelly.CheckForUpdate");
|
||||
connect(updateReply, &ShellyRpcReply::finished, thing, [thing](ShellyRpcReply::Status status, const QVariantMap &response){
|
||||
if (status != ShellyRpcReply::StatusSuccess) {
|
||||
qCWarning(dcShelly()) << "Error chcking for updates from shelly:" << status;
|
||||
return;
|
||||
}
|
||||
qCDebug(dcShelly()) << thing->name() << "CheckForUpdate reply:" << response;
|
||||
if (response.contains("stable")) {
|
||||
thing->setStateValue("availableVersion", response.value("stable").toMap().value("version").toString());
|
||||
thing->setStateValue("updateStatus", "available");
|
||||
} else {
|
||||
thing->setStateValue("availableVersion", "");
|
||||
thing->setStateValue("updateStatus", "idle");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginShelly::setupGen1(ThingSetupInfo *info)
|
||||
|
|
@ -1626,7 +1580,9 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
QString password = info->thing()->paramValue("password").toString();
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
QString password = pluginStorage()->value("password").toString();
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
ShellyJsonRpcClient *client = new ShellyJsonRpcClient(info->thing());
|
||||
client->open(address, "admin", password, shellyId);
|
||||
|
|
@ -1644,7 +1600,7 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
qCDebug(dcShelly) << "Init response:" << response;
|
||||
m_rpcClients.insert(info->thing(), client);
|
||||
|
||||
if (info->thing()->thingClassId() == shelly1pmThingClassId) {
|
||||
if (info->thing()->thingClassId() == shellyPlus1pmThingClassId || info->thing()->thingClassId() == shellyPlus1ThingClassId) {
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
|
|
@ -1656,8 +1612,8 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (info->thing()->thingClassId() == shelly25ThingClassId) {
|
||||
// Make sure the shelly 2.5 is in the mode we expect it to be (roller/cover or relay/switch)
|
||||
if (info->thing()->thingClassId() == shellyPlus25ThingClassId) {
|
||||
// Make sure the shelly plus 2PM is in the mode we expect it to be (roller/cover or relay/switch)
|
||||
bool rollerMode = info->thing()->paramValue("rollerMode").toBool();
|
||||
QVariantMap params;
|
||||
if(rollerMode) {
|
||||
|
|
@ -1666,39 +1622,39 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
params.insert("name", "switch");
|
||||
}
|
||||
ShellyRpcReply *reply2 = client->sendRequest("Shelly.SetProfile", params);
|
||||
connect(reply2, &ShellyRpcReply::finished, info, [info](ShellyRpcReply::Status status, const QVariantMap &/*response*/){
|
||||
connect(reply2, &ShellyRpcReply::finished, info, [this, info, rollerMode](ShellyRpcReply::Status status, const QVariantMap &/*response*/){
|
||||
if (status != ShellyRpcReply::StatusSuccess) {
|
||||
qCWarning(dcShelly) << "Error during shelly setup";
|
||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Unable to configure shelly device."));
|
||||
return;
|
||||
}
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
if (myThings().filterByParentId(info->thing()->id()).count() == 0) {
|
||||
ThingDescriptors children;
|
||||
ThingDescriptor switchChild(shellySwitchThingClassId, info->thing()->name() + " switch 1", QString(), info->thing()->id());
|
||||
switchChild.setParams(ParamList() << Param(shellySwitchThingChannelParamTypeId, 1));
|
||||
children.append(switchChild);
|
||||
ThingDescriptor switch2Child(shellySwitchThingClassId, info->thing()->name() + " switch 2", QString(), info->thing()->id());
|
||||
switch2Child.setParams(ParamList() << Param(shellySwitchThingChannelParamTypeId, 2));
|
||||
children.append(switch2Child);
|
||||
if (myThings().filterByParentId(info->thing()->id()).count() == 0) {
|
||||
ThingDescriptors children;
|
||||
ThingDescriptor switchChild(shellySwitchThingClassId, info->thing()->name() + " switch 1", QString(), info->thing()->id());
|
||||
switchChild.setParams(ParamList() << Param(shellySwitchThingChannelParamTypeId, 1));
|
||||
children.append(switchChild);
|
||||
ThingDescriptor switch2Child(shellySwitchThingClassId, info->thing()->name() + " switch 2", QString(), info->thing()->id());
|
||||
switch2Child.setParams(ParamList() << Param(shellySwitchThingChannelParamTypeId, 2));
|
||||
children.append(switch2Child);
|
||||
|
||||
if (rollerMode == true) {
|
||||
ThingDescriptor rollerShutterChild(shellyRollerThingClassId, info->thing()->name() + " connected shutter", QString(), info->thing()->id());
|
||||
rollerShutterChild.setParams(ParamList() << Param(shellyRollerThingChannelParamTypeId, 1));
|
||||
children.append(rollerShutterChild);
|
||||
// Create 2 measurement channels for Shelly Plus 2PM (unless in roller mode)
|
||||
} else {
|
||||
ThingDescriptor channelChild(shellyPowerMeterChannelThingClassId, info->thing()->name() + " channel 1", QString(), info->thing()->id());
|
||||
channelChild.setParams(ParamList() << Param(shellyPowerMeterChannelThingChannelParamTypeId, 1));
|
||||
children.append(channelChild);
|
||||
ThingDescriptor channel2Child(shellyPowerMeterChannelThingClassId, info->thing()->name() + " channel 2", QString(), info->thing()->id());
|
||||
channel2Child.setParams(ParamList() << Param(shellyPowerMeterChannelThingChannelParamTypeId, 2));
|
||||
children.append(channel2Child);
|
||||
if (rollerMode == true) {
|
||||
ThingDescriptor rollerShutterChild(shellyRollerThingClassId, info->thing()->name() + " connected shutter", QString(), info->thing()->id());
|
||||
rollerShutterChild.setParams(ParamList() << Param(shellyRollerThingChannelParamTypeId, 1));
|
||||
children.append(rollerShutterChild);
|
||||
// Create 2 measurement channels for Shelly Plus 2PM (unless in roller mode)
|
||||
} else {
|
||||
ThingDescriptor channelChild(shellyPowerMeterChannelThingClassId, info->thing()->name() + " channel 1", QString(), info->thing()->id());
|
||||
channelChild.setParams(ParamList() << Param(shellyPowerMeterChannelThingChannelParamTypeId, 1));
|
||||
children.append(channelChild);
|
||||
ThingDescriptor channel2Child(shellyPowerMeterChannelThingClassId, info->thing()->name() + " channel 2", QString(), info->thing()->id());
|
||||
channel2Child.setParams(ParamList() << Param(shellyPowerMeterChannelThingChannelParamTypeId, 2));
|
||||
children.append(channel2Child);
|
||||
}
|
||||
emit autoThingsAppeared(children);
|
||||
}
|
||||
emit autoThingsAppeared(children);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -1707,7 +1663,7 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
// Set default state & led mode of the Plus Plug (S)
|
||||
QString defaultState = "off";
|
||||
QString ledMode = "switch";
|
||||
defaultState = info->thing()->setting(defaultStateSettingIds.value(info->thing()->thingClassId())).toString();
|
||||
defaultState = info->thing()->setting("defaultState").toString();
|
||||
QVariantMap config;
|
||||
config.insert("initial_state", defaultState);
|
||||
QVariantMap params;
|
||||
|
|
@ -1724,7 +1680,7 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
ledMode = info->thing()->setting(ledModeSettingIds.value(info->thing()->thingClassId())).toString();
|
||||
ledMode = info->thing()->setting("ledMode").toString();
|
||||
QVariantMap leds;
|
||||
leds.insert("mode", ledMode);
|
||||
QVariantMap config2;
|
||||
|
|
@ -1751,16 +1707,20 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
});
|
||||
});
|
||||
|
||||
connect(client, &ShellyJsonRpcClient::stateChanged, thing, [thing, client, this](QAbstractSocket::SocketState state) {
|
||||
connect(client, &ShellyJsonRpcClient::stateChanged, thing, [thing, client, password, shellyId, this](QAbstractSocket::SocketState state) {
|
||||
thing->setStateValue("connected", state == QAbstractSocket::ConnectedState);
|
||||
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
child->setStateValue("connected", state == QAbstractSocket::ConnectedState);
|
||||
}
|
||||
|
||||
if (state == QAbstractSocket::UnconnectedState) {
|
||||
QTimer::singleShot(1000, thing, [this, client, thing](){
|
||||
client->open(getIP(thing), "admin", thing->paramValue("password").toString(), thing->paramValue("id").toString());
|
||||
QTimer::singleShot(1000, thing, [this, client, thing, password, shellyId](){
|
||||
client->open(getIP(thing), "admin", password, shellyId);
|
||||
});
|
||||
} else {
|
||||
if (thing->setupStatus() == Thing::ThingSetupStatusComplete) {
|
||||
fetchStatusGen2(thing);
|
||||
}
|
||||
}
|
||||
});
|
||||
connect(client, &ShellyJsonRpcClient::notificationReceived, thing, [thing, this](const QVariantMap ¬ification){
|
||||
|
|
@ -1865,7 +1825,8 @@ void IntegrationPluginShelly::setupGen2(ThingSetupInfo *info)
|
|||
thing->setStateValue(shellyPro3EMEnergyConsumedPhaseBStateTypeId, emdata0.value("b_total_act_energy").toDouble() / 1000);
|
||||
thing->setStateValue(shellyPro3EMEnergyProducedPhaseBStateTypeId, emdata0.value("b_total_act_ret_energy").toDouble() / 1000);
|
||||
thing->setStateValue(shellyPro3EMEnergyConsumedPhaseCStateTypeId, emdata0.value("c_total_act_energy").toDouble() / 1000);
|
||||
thing->setStateValue(shellyPro3EMEnergyProducedPhaseCStateTypeId, emdata0.value("c_total_act_ret_energy").toDouble() / 1000); thing->setStateValue(shellyPro3EMTotalEnergyConsumedStateTypeId, emdata0.value("total_act").toDouble() / 1000);
|
||||
thing->setStateValue(shellyPro3EMEnergyProducedPhaseCStateTypeId, emdata0.value("c_total_act_ret_energy").toDouble() / 1000);
|
||||
thing->setStateValue(shellyPro3EMTotalEnergyConsumedStateTypeId, emdata0.value("total_act").toDouble() / 1000);
|
||||
thing->setStateValue(shellyPro3EMTotalEnergyProducedStateTypeId, emdata0.value("total_act_ret").toDouble() / 1000);
|
||||
}
|
||||
});
|
||||
|
|
@ -2007,6 +1968,7 @@ QHostAddress IntegrationPluginShelly::getIP(Thing *thing) const
|
|||
}
|
||||
|
||||
QString shellyId = d->paramValue("id").toString();
|
||||
|
||||
ZeroConfServiceEntry zeroConfEntry;
|
||||
foreach (const ZeroConfServiceEntry &entry, m_zeroconfBrowser->serviceEntries()) {
|
||||
if (entry.name() == shellyId) {
|
||||
|
|
@ -2033,9 +1995,9 @@ QHostAddress IntegrationPluginShelly::getIP(Thing *thing) const
|
|||
bool IntegrationPluginShelly::isGen2(const QString &shellyId) const
|
||||
{
|
||||
return shellyId.contains("Plus")
|
||||
|| shellyId.contains("Pro")
|
||||
|| shellyId.startsWith("ShellyPlug") // Plus plug variants don't have Plus in the name, but are camelcased as opposed to 1st gen plugs
|
||||
;
|
||||
|| shellyId.contains("Pro")
|
||||
|| shellyId.startsWith("ShellyPlug") // Plus plug variants don't have Plus in the name, but are camelcased as opposed to 1st gen plugs
|
||||
;
|
||||
}
|
||||
|
||||
void IntegrationPluginShelly::handleInputEvent(Thing *thing, const QString &buttonName, const QString &inputEventString, int inputEventCount)
|
||||
|
|
|
|||
|
|
@ -57,8 +57,11 @@ public:
|
|||
explicit IntegrationPluginShelly();
|
||||
~IntegrationPluginShelly() override;
|
||||
|
||||
|
||||
void init() override;
|
||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||
void startPairing(ThingPairingInfo *info) override;
|
||||
void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &password) override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
{
|
||||
"id": "f810b66a-7177-4397-9771-4229abaabbb6",
|
||||
"name": "shelly1",
|
||||
"displayName": "Shelly 1/Plus 1",
|
||||
"displayName": "Shelly 1",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": [ "gateway", "wirelessconnectable", "update" ],
|
||||
"paramTypes": [
|
||||
|
|
@ -115,10 +115,98 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "83766db4-a553-4df7-aeff-35fb18c01f3a",
|
||||
"name": "shellyPlus1",
|
||||
"displayName": "Shelly Plus 1",
|
||||
"createMethods": ["discovery"],
|
||||
"setupMethod": "enterpin",
|
||||
"interfaces": [ "gateway", "wirelessconnectable", "update" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "41cf8c80-b641-46fd-a329-2b81ecf9d445",
|
||||
"name":"id",
|
||||
"displayName": "Shelly ID",
|
||||
"type": "QString",
|
||||
"readOnly": true
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "231365ce-45d6-4087-8ed6-1de3b0ef0485",
|
||||
"name": "power",
|
||||
"displayName": "Powered",
|
||||
"displayNameEvent": "Turned on/off",
|
||||
"displayNameAction": "Turn on/off",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true,
|
||||
"ioType": "digitalOutput"
|
||||
},
|
||||
{
|
||||
"id": "30c5bbb2-7b02-445b-af16-8a082321383b",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "f2b1f70c-dab0-474d-81bd-816ff3c63f47",
|
||||
"name": "signalStrength",
|
||||
"displayName": "Signal strength",
|
||||
"displayNameEvent": "Signal strength changed",
|
||||
"type": "uint",
|
||||
"unit": "Percentage",
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "2c312a9e-ae76-4042-8030-89c8c86320e9",
|
||||
"name": "updateStatus",
|
||||
"displayName": "Update status",
|
||||
"displayNameEvent": "Update status changed",
|
||||
"type": "QString",
|
||||
"possibleValues": ["idle", "available", "updating"],
|
||||
"defaultValue": "idle"
|
||||
},
|
||||
{
|
||||
"id": "3fed15bd-500b-4cce-9b21-a931f411b587",
|
||||
"name": "currentVersion",
|
||||
"displayName": "Firmware version",
|
||||
"displayNameEvent": "Firmware version changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "d236c735-012c-44c7-919e-809cae89de55",
|
||||
"name": "availableVersion",
|
||||
"displayName": "Available firmware version",
|
||||
"displayNameEvent": "Available firmware version changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "212aaf17-faf1-4495-8475-0718b9b39628",
|
||||
"name": "reboot",
|
||||
"displayName": "Reboot"
|
||||
},
|
||||
{
|
||||
"id": "fa3a8bd6-182f-443f-ae41-d2c4aee6339d",
|
||||
"name": "performUpdate",
|
||||
"displayName": "Update firmware"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "30e74e9f-57f4-4bbc-b0df-f2c4f28b2f06",
|
||||
"name": "shelly1pm",
|
||||
"displayName": "Shelly 1PM/Plus 1PM",
|
||||
"displayName": "Shelly 1PM",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": [ "gateway", "smartmeterconsumer", "wirelessconnectable", "update" ],
|
||||
"paramTypes": [
|
||||
|
|
@ -241,6 +329,105 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4c497fe1-c399-463a-9a73-0c5f4ebac100",
|
||||
"name": "shellyPlus1pm",
|
||||
"displayName": "Shelly Plus 1PM",
|
||||
"createMethods": ["discovery"],
|
||||
"setupMethod": "enterpin",
|
||||
"interfaces": [ "gateway", "smartmeterconsumer", "wirelessconnectable", "update" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "0d97dbf6-0545-4953-ad71-4888df37df70",
|
||||
"name":"id",
|
||||
"displayName": "Shelly ID",
|
||||
"type": "QString",
|
||||
"readOnly": true
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "bc425ba1-7776-4004-ba67-b256db7c511d",
|
||||
"name": "power",
|
||||
"displayName": "Powered",
|
||||
"displayNameAction": "Turn on/off",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true,
|
||||
"ioType": "digitalOutput"
|
||||
},
|
||||
{
|
||||
"id": "1b0ecbb2-5ed6-439e-81fb-5788ed8679e2",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "bffa3472-a09f-4e85-9d31-0b966e415cd2",
|
||||
"name": "signalStrength",
|
||||
"displayName": "Signal strength",
|
||||
"type": "uint",
|
||||
"unit": "Percentage",
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "c9515efd-f16a-4a29-97e1-516d1d5a6a93",
|
||||
"name": "updateStatus",
|
||||
"displayName": "Update status",
|
||||
"type": "QString",
|
||||
"possibleValues": ["idle", "available", "updating"],
|
||||
"defaultValue": "idle"
|
||||
},
|
||||
{
|
||||
"id": "e3859bc0-f96d-4fa1-958b-0e087a39a0e6",
|
||||
"name": "currentVersion",
|
||||
"displayName": "Firmware version",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "0dda20f7-e13e-494d-8351-c4401ded6c1e",
|
||||
"name": "availableVersion",
|
||||
"displayName": "Available firmware version",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "76e87d1f-bc65-4f63-b692-106861827633",
|
||||
"name": "totalEnergyConsumed",
|
||||
"displayName": "Total energy consumed",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "40e63755-7220-4c7c-9c6a-fe5d7e230a35",
|
||||
"name": "currentPower",
|
||||
"displayName": "Current power consumption",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "b18211d8-528b-4bff-93c2-ce6a8b55759e",
|
||||
"name": "reboot",
|
||||
"displayName": "Reboot"
|
||||
},
|
||||
{
|
||||
"id": "0cabc075-9abc-49be-a50d-e8a8d7637d03",
|
||||
"name": "performUpdate",
|
||||
"displayName": "Update firmware"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "20754114-1591-48b5-af2f-8c9966adb7c4",
|
||||
"name": "shelly1l",
|
||||
|
|
@ -495,7 +682,7 @@
|
|||
{
|
||||
"id": "465efb0d-da68-4177-a040-940c7f451e29",
|
||||
"name": "shelly25",
|
||||
"displayName": "Shelly 2.5/Shelly Plus 2PM",
|
||||
"displayName": "Shelly 2.5",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": [ "gateway", "wirelessconnectable", "update" ],
|
||||
"paramTypes": [
|
||||
|
|
@ -617,10 +804,116 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "86b037f5-c7f8-4778-b6d1-2b11c4ba1027",
|
||||
"name": "shellyPlus25",
|
||||
"displayName": "Shelly Plus 2PM",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": [ "gateway", "wirelessconnectable", "update" ],
|
||||
"setupMethod": "enterpin",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "0cd68080-5da5-44c6-a1c2-12af086a16de",
|
||||
"name":"id",
|
||||
"displayName": "Shelly ID",
|
||||
"type": "QString",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "0b45bc3d-f598-484b-8de4-03bc67b90664",
|
||||
"name": "rollerMode",
|
||||
"displayName": "Roller shutter mode",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "8f4fe4d4-7036-4a1a-9960-091a4a7f6f02",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "01158eee-3605-45c2-8b6d-2c0a69321c5b",
|
||||
"name": "signalStrength",
|
||||
"displayName": "Signal strength",
|
||||
"displayNameEvent": "Signal strength changed",
|
||||
"type": "uint",
|
||||
"unit": "Percentage",
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "395a188b-c2e2-40d1-a5f2-9ed4a9ff558f",
|
||||
"name": "updateStatus",
|
||||
"displayName": "Update status",
|
||||
"displayNameEvent": "Update status changed",
|
||||
"type": "QString",
|
||||
"possibleValues": ["idle", "available", "updating"],
|
||||
"defaultValue": "idle"
|
||||
},
|
||||
{
|
||||
"id": "c1f5d20a-3b06-4405-afca-20dfd41e3a34",
|
||||
"name": "currentVersion",
|
||||
"displayName": "Firmware version",
|
||||
"displayNameEvent": "Firmware version changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "32134deb-8e37-4d65-ae10-aad0cb44ff7b",
|
||||
"name": "availableVersion",
|
||||
"displayName": "Available firmware version",
|
||||
"displayNameEvent": "Available firmware version changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "bf969a1f-aa8a-40aa-8e50-af37b8b0ffe6",
|
||||
"name": "channel1",
|
||||
"displayName": "Power channel 1",
|
||||
"displayNameEvent": "Channel 1 turned on or off",
|
||||
"displayNameAction": "Turn channel 1 on or off",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true,
|
||||
"ioType": "digitalOutput"
|
||||
},
|
||||
{
|
||||
"id": "43b41b49-def1-469b-b993-788647dc8839",
|
||||
"name": "channel2",
|
||||
"displayName": "Power channel 2",
|
||||
"displayNameEvent": "Channel 2 turned on or off",
|
||||
"displayNameAction": "Turn channel 2 on or off",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true,
|
||||
"ioType": "digitalOutput"
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "7714490b-117d-4d25-a695-9e151997f128",
|
||||
"name": "reboot",
|
||||
"displayName": "Reboot"
|
||||
},
|
||||
{
|
||||
"id": "9d5e04b8-cac4-49ce-9e32-efc3a06beb4b",
|
||||
"name": "performUpdate",
|
||||
"displayName": "Update firmware"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2c470ea4-6ef2-4aa2-b2f3-b6d8750ac577",
|
||||
"name": "shellyPlusPlug",
|
||||
"displayName": "Shelly Plus Plug S",
|
||||
"displayName": "Shelly Plus Plug S/US/UK/IT",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": [ "powersocket", "smartmeterconsumer", "wirelessconnectable", "update" ],
|
||||
"paramTypes": [
|
||||
|
|
|
|||
Loading…
Reference in New Issue