SonoffTasmota: Fix Tasmota device setup web command and add support for Shutters on 2CH switches
This commit is contained in:
parent
37fff92942
commit
765b2c6c75
@ -81,16 +81,20 @@ DevicePluginTasmota::DevicePluginTasmota()
|
|||||||
// Helper maps for virtual childs (aka tasmota*)
|
// Helper maps for virtual childs (aka tasmota*)
|
||||||
m_channelParamTypeMap[tasmotaSwitchDeviceClassId] = tasmotaSwitchDeviceChannelNameParamTypeId;
|
m_channelParamTypeMap[tasmotaSwitchDeviceClassId] = tasmotaSwitchDeviceChannelNameParamTypeId;
|
||||||
m_channelParamTypeMap[tasmotaLightDeviceClassId] = tasmotaLightDeviceChannelNameParamTypeId;
|
m_channelParamTypeMap[tasmotaLightDeviceClassId] = tasmotaLightDeviceChannelNameParamTypeId;
|
||||||
|
m_openingChannelParamTypeMap[tasmotaShutterDeviceClassId] = tasmotaShutterDeviceOpeningChannelParamTypeId;
|
||||||
|
m_closingChannelParamTypeMap[tasmotaShutterDeviceClassId] = tasmotaShutterDeviceClosingChannelParamTypeId;
|
||||||
|
|
||||||
m_powerStateTypeMap[tasmotaSwitchDeviceClassId] = tasmotaSwitchPowerStateTypeId;
|
m_powerStateTypeMap[tasmotaSwitchDeviceClassId] = tasmotaSwitchPowerStateTypeId;
|
||||||
m_powerStateTypeMap[tasmotaLightDeviceClassId] = tasmotaLightPowerStateTypeId;
|
m_powerStateTypeMap[tasmotaLightDeviceClassId] = tasmotaLightPowerStateTypeId;
|
||||||
|
|
||||||
|
|
||||||
// Helper maps for all devices
|
// Helper maps for all devices
|
||||||
m_connectedStateTypeMap[sonoff_basicDeviceClassId] = sonoff_basicConnectedStateTypeId;
|
m_connectedStateTypeMap[sonoff_basicDeviceClassId] = sonoff_basicConnectedStateTypeId;
|
||||||
m_connectedStateTypeMap[sonoff_dualDeviceClassId] = sonoff_dualConnectedStateTypeId;
|
m_connectedStateTypeMap[sonoff_dualDeviceClassId] = sonoff_dualConnectedStateTypeId;
|
||||||
m_connectedStateTypeMap[sonoff_quadDeviceClassId] = sonoff_quadConnectedStateTypeId;
|
m_connectedStateTypeMap[sonoff_quadDeviceClassId] = sonoff_quadConnectedStateTypeId;
|
||||||
m_connectedStateTypeMap[tasmotaSwitchDeviceClassId] = tasmotaSwitchConnectedStateTypeId;
|
m_connectedStateTypeMap[tasmotaSwitchDeviceClassId] = tasmotaSwitchConnectedStateTypeId;
|
||||||
m_connectedStateTypeMap[tasmotaLightDeviceClassId] = tasmotaLightConnectedStateTypeId;
|
m_connectedStateTypeMap[tasmotaLightDeviceClassId] = tasmotaLightConnectedStateTypeId;
|
||||||
|
m_connectedStateTypeMap[tasmotaShutterDeviceClassId] = tasmotaShutterConnectedStateTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
DevicePluginTasmota::~DevicePluginTasmota()
|
DevicePluginTasmota::~DevicePluginTasmota()
|
||||||
@ -117,17 +121,27 @@ DeviceManager::DeviceSetupStatus DevicePluginTasmota::setupDevice(Device *device
|
|||||||
return DeviceManager::DeviceSetupStatusFailure;
|
return DeviceManager::DeviceSetupStatusFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url("http://10.10.10.90/sv");
|
QUrl url(QString("http://%1/cm").arg(deviceAddress.toString()));
|
||||||
QUrlQuery query;
|
QUrlQuery query;
|
||||||
query.addQueryItem("w", "2%2C1");
|
QMap<QString, QString> configItems;
|
||||||
query.addQueryItem("mh", channel->serverAddress().toString());
|
configItems.insert("MqttHost", channel->serverAddress().toString());
|
||||||
query.addQueryItem("ml", QString::number(channel->serverPort()));
|
configItems.insert("MqttPort", QString::number(channel->serverPort()));
|
||||||
query.addQueryItem("mc", channel->clientId());
|
configItems.insert("MqttClient", channel->clientId());
|
||||||
query.addQueryItem("mu", channel->username());
|
configItems.insert("MqttUser", channel->username());
|
||||||
query.addQueryItem("mp", channel->password());
|
configItems.insert("MqttPassword", channel->password());
|
||||||
query.addQueryItem("mt", "sonoff");
|
configItems.insert("Topic", "sonoff");
|
||||||
query.addQueryItem("mf", channel->topicPrefix() + "/%topic%/");
|
configItems.insert("FullTopic", channel->topicPrefix() + "/%topic%/");
|
||||||
|
|
||||||
|
QStringList configList;
|
||||||
|
foreach (const QString &key, configItems.keys()) {
|
||||||
|
configList << key + ' ' + configItems.value(key);
|
||||||
|
}
|
||||||
|
QString fullCommand = "Backlog " + configList.join(';');
|
||||||
|
query.addQueryItem("cmnd", fullCommand.toUtf8().toPercentEncoding());
|
||||||
|
|
||||||
|
|
||||||
url.setQuery(query);
|
url.setQuery(query);
|
||||||
|
qCDebug(dcTasmota) << "Configuring Tasmota device:" << url.toString();
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
|
||||||
connect(reply, &QNetworkReply::finished, this, [this, device, channel, reply](){
|
connect(reply, &QNetworkReply::finished, this, [this, device, channel, reply](){
|
||||||
@ -167,9 +181,13 @@ DeviceManager::DeviceSetupStatus DevicePluginTasmota::setupDevice(Device *device
|
|||||||
|
|
||||||
qCDebug(dcTasmota) << "Adding Tasmota connected devices";
|
qCDebug(dcTasmota) << "Adding Tasmota connected devices";
|
||||||
deviceDescriptors.clear();
|
deviceDescriptors.clear();
|
||||||
|
int shutterUpChannel = -1;
|
||||||
|
int shutterDownChannel = -1;
|
||||||
for (int i = 0; i < m_attachedDeviceParamTypeIdMap.value(device->deviceClassId()).count(); i++) {
|
for (int i = 0; i < m_attachedDeviceParamTypeIdMap.value(device->deviceClassId()).count(); i++) {
|
||||||
ParamTypeId attachedDeviceParamTypeId = m_attachedDeviceParamTypeIdMap.value(device->deviceClassId()).at(i);
|
ParamTypeId attachedDeviceParamTypeId = m_attachedDeviceParamTypeIdMap.value(device->deviceClassId()).at(i);
|
||||||
if (device->paramValue(attachedDeviceParamTypeId).toString() == "Light") {
|
QString deviceType = device->paramValue(attachedDeviceParamTypeId).toString();
|
||||||
|
qCDebug(dcTasmota) << "Connected Device" << i + 1 << deviceType;
|
||||||
|
if (deviceType == "Light") {
|
||||||
DeviceDescriptor descriptor(tasmotaLightDeviceClassId, device->name() + " CH" + QString::number(i+1), QString(), device->id());
|
DeviceDescriptor descriptor(tasmotaLightDeviceClassId, device->name() + " CH" + QString::number(i+1), QString(), device->id());
|
||||||
descriptor.setParentDeviceId(device->id());
|
descriptor.setParentDeviceId(device->id());
|
||||||
if (m_attachedDeviceParamTypeIdMap.value(device->deviceClassId()).count() == 1) {
|
if (m_attachedDeviceParamTypeIdMap.value(device->deviceClassId()).count() == 1) {
|
||||||
@ -178,11 +196,27 @@ DeviceManager::DeviceSetupStatus DevicePluginTasmota::setupDevice(Device *device
|
|||||||
descriptor.setParams(ParamList() << Param(tasmotaLightDeviceChannelNameParamTypeId, "POWER" + QString::number(i+1)));
|
descriptor.setParams(ParamList() << Param(tasmotaLightDeviceChannelNameParamTypeId, "POWER" + QString::number(i+1)));
|
||||||
}
|
}
|
||||||
deviceDescriptors << descriptor;
|
deviceDescriptors << descriptor;
|
||||||
|
} else if (deviceType == "Roller Shutter Up") {
|
||||||
|
shutterUpChannel = i+1;
|
||||||
|
} else if (deviceType == "Roller Shutter Down") {
|
||||||
|
shutterDownChannel = i+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!deviceDescriptors.isEmpty()) {
|
if (!deviceDescriptors.isEmpty()) {
|
||||||
emit autoDevicesAppeared(tasmotaLightDeviceClassId, deviceDescriptors);
|
emit autoDevicesAppeared(tasmotaLightDeviceClassId, deviceDescriptors);
|
||||||
}
|
}
|
||||||
|
deviceDescriptors.clear();
|
||||||
|
if (shutterUpChannel != -1 && shutterDownChannel != -1) {
|
||||||
|
qCDebug(dcTasmota) << "Adding Shutter device";
|
||||||
|
DeviceDescriptor descriptor(tasmotaShutterDeviceClassId, device->name() + " Shutter", QString(), device->id());
|
||||||
|
descriptor.setParams(ParamList()
|
||||||
|
<< Param(tasmotaShutterDeviceOpeningChannelParamTypeId, "POWER" + QString::number(shutterUpChannel))
|
||||||
|
<< Param(tasmotaShutterDeviceClosingChannelParamTypeId, "POWER" + QString::number(shutterDownChannel)));
|
||||||
|
deviceDescriptors << descriptor;
|
||||||
|
}
|
||||||
|
if (!deviceDescriptors.isEmpty()) {
|
||||||
|
emit autoDevicesAppeared(tasmotaShutterDeviceClassId, deviceDescriptors);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return DeviceManager::DeviceSetupStatusAsync;
|
return DeviceManager::DeviceSetupStatusAsync;
|
||||||
}
|
}
|
||||||
@ -220,6 +254,30 @@ DeviceManager::DeviceError DevicePluginTasmota::executeAction(Device *device, co
|
|||||||
device->setStateValue(m_powerStateTypeMap.value(device->deviceClassId()), action.param(powerActionParamTypeId).value().toBool());
|
device->setStateValue(m_powerStateTypeMap.value(device->deviceClassId()), action.param(powerActionParamTypeId).value().toBool());
|
||||||
return DeviceManager::DeviceErrorNoError;
|
return DeviceManager::DeviceErrorNoError;
|
||||||
}
|
}
|
||||||
|
if (device->deviceClassId() == tasmotaShutterDeviceClassId) {
|
||||||
|
Device *parentDev = myDevices().findById(device->parentId());
|
||||||
|
MqttChannel *channel = m_mqttChannels.value(parentDev);
|
||||||
|
ParamTypeId openingChannelParamTypeId = m_openingChannelParamTypeMap.value(device->deviceClassId());
|
||||||
|
ParamTypeId closingChannelParamTypeId = m_closingChannelParamTypeMap.value(device->deviceClassId());
|
||||||
|
if (action.actionTypeId() == tasmotaShutterOpenActionTypeId) {
|
||||||
|
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||||
|
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||||
|
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "ON";
|
||||||
|
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "ON");
|
||||||
|
} else if (action.actionTypeId() == tasmotaShutterCloseActionTypeId) {
|
||||||
|
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||||
|
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||||
|
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "ON";
|
||||||
|
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "ON");
|
||||||
|
} else { // Stop
|
||||||
|
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString() << "OFF";
|
||||||
|
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(openingChannelParamTypeId).toString().toLower(), "OFF");
|
||||||
|
qCDebug(dcTasmota) << "Publishing:" << channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString() << "OFF";
|
||||||
|
channel->publish(channel->topicPrefix() + "/sonoff/cmnd/" + device->paramValue(closingChannelParamTypeId).toString().toLower(), "OFF");
|
||||||
|
}
|
||||||
|
return DeviceManager::DeviceErrorNoError;
|
||||||
|
}
|
||||||
|
qCWarning(dcTasmota) << "Unhandled execute action call for device" << device;
|
||||||
return DeviceManager::DeviceErrorDeviceClassNotFound;
|
return DeviceManager::DeviceErrorDeviceClassNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +322,9 @@ void DevicePluginTasmota::onPublishReceived(MqttChannel *channel, const QString
|
|||||||
if (child->paramValue(m_channelParamTypeMap.value(child->deviceClassId())).toString() != channelName) {
|
if (child->paramValue(m_channelParamTypeMap.value(child->deviceClassId())).toString() != channelName) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
child->setStateValue(m_powerStateTypeMap.value(child->deviceClassId()), payload == "ON");
|
if (m_powerStateTypeMap.contains(child->deviceClassId())) {
|
||||||
|
child->setStateValue(m_powerStateTypeMap.value(child->deviceClassId()), payload == "ON");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (topic.startsWith(channel->topicPrefix() + "/sonoff/STATE")) {
|
if (topic.startsWith(channel->topicPrefix() + "/sonoff/STATE")) {
|
||||||
@ -278,9 +338,11 @@ void DevicePluginTasmota::onPublishReceived(MqttChannel *channel, const QString
|
|||||||
if (child->parentId() != dev->id()) {
|
if (child->parentId() != dev->id()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QString childChannel = child->paramValue(m_channelParamTypeMap.value(child->deviceClassId())).toString();
|
if (m_powerStateTypeMap.contains(child->deviceClassId())) {
|
||||||
QString valueString = jsonDoc.toVariant().toMap().value(childChannel).toString();
|
QString childChannel = child->paramValue(m_channelParamTypeMap.value(child->deviceClassId())).toString();
|
||||||
child->setStateValue(m_powerStateTypeMap.value(child->deviceClassId()), valueString == "ON");
|
QString valueString = jsonDoc.toVariant().toMap().value(childChannel).toString();
|
||||||
|
child->setStateValue(m_powerStateTypeMap.value(child->deviceClassId()), valueString == "ON");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,8 @@ private:
|
|||||||
|
|
||||||
// Helpers for child devices (virtual ones, starting with tasmota)
|
// Helpers for child devices (virtual ones, starting with tasmota)
|
||||||
QHash<DeviceClassId, ParamTypeId> m_channelParamTypeMap;
|
QHash<DeviceClassId, ParamTypeId> m_channelParamTypeMap;
|
||||||
|
QHash<DeviceClassId, ParamTypeId> m_openingChannelParamTypeMap;
|
||||||
|
QHash<DeviceClassId, ParamTypeId> m_closingChannelParamTypeMap;
|
||||||
QHash<DeviceClassId, StateTypeId> m_powerStateTypeMap;
|
QHash<DeviceClassId, StateTypeId> m_powerStateTypeMap;
|
||||||
|
|
||||||
// Helpers for both devices
|
// Helpers for both devices
|
||||||
|
|||||||
@ -60,7 +60,7 @@
|
|||||||
"name": "attachedDeviceCH1",
|
"name": "attachedDeviceCH1",
|
||||||
"displayName": "Connected device 1",
|
"displayName": "Connected device 1",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"allowedValues": ["None", "Light"],
|
"allowedValues": ["None", "Light", "Roller Shutter Up", "Roller Shutter Down"],
|
||||||
"defaultValue": "None"
|
"defaultValue": "None"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"name": "attachedDeviceCH2",
|
"name": "attachedDeviceCH2",
|
||||||
"displayName": "Connected device 2",
|
"displayName": "Connected device 2",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"allowedValues": ["None", "Light"],
|
"allowedValues": ["None", "Light", "Roller Shutter Up", "Roller Shutter Down"],
|
||||||
"defaultValue": "None"
|
"defaultValue": "None"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -213,6 +213,54 @@
|
|||||||
"writable": true
|
"writable": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c63b02f2-3695-4e8c-9789-1b8a705f3a53",
|
||||||
|
"name": "tasmotaShutter",
|
||||||
|
"displayName": "Tasmota shutter",
|
||||||
|
"createMethods": ["auto"],
|
||||||
|
"interfaces": ["shutter", "closable", "connectable"],
|
||||||
|
"paramTypes": [
|
||||||
|
{
|
||||||
|
"id": "4d8f113d-f816-4356-b1ff-31df3f4b515f",
|
||||||
|
"name": "openingChannel",
|
||||||
|
"displayName": "Opening channel",
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "600c00fd-6a2c-46cd-8031-2d9a1b1bc710",
|
||||||
|
"name": "closingChannel",
|
||||||
|
"displayName": "Closing channel",
|
||||||
|
"type": "QString"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateTypes": [
|
||||||
|
{
|
||||||
|
"id": "7bbf0bbf-abb3-487e-b5e9-077f7b00d8ef",
|
||||||
|
"name": "connected",
|
||||||
|
"displayName": "Connected",
|
||||||
|
"displayNameEvent": "Connected changed",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actionTypes": [
|
||||||
|
{
|
||||||
|
"id": "8e7fb2f4-2819-4d14-a5ae-95624b097bf7",
|
||||||
|
"name": "open",
|
||||||
|
"displayName": "Open"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "efbe9290-affd-4902-abb7-dd4ea74ccd1b",
|
||||||
|
"name": "close",
|
||||||
|
"displayName": "Close"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c9c9c569-e224-4f63-abed-782cba04d61b",
|
||||||
|
"name": "stop",
|
||||||
|
"displayName": "Stop"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user