From c076034ad519ae3c05fb9851f8e22749fa8e3e50 Mon Sep 17 00:00:00 2001 From: Boernsman Date: Fri, 27 Dec 2019 09:16:27 +0100 Subject: [PATCH] added color flow and alert interface --- yeelight/devicepluginyeelight.cpp | 45 +++++++++++++++++-- yeelight/devicepluginyeelight.json | 34 ++++++++++++++- yeelight/ssdp.cpp | 22 ++++++++++ yeelight/ssdp.h | 22 ++++++++++ yeelight/yeelight.cpp | 69 ++++++++++++++++++++++++++++++ yeelight/yeelight.h | 13 +++++- 6 files changed, 198 insertions(+), 7 deletions(-) diff --git a/yeelight/devicepluginyeelight.cpp b/yeelight/devicepluginyeelight.cpp index 061ed9c9..870a7f2c 100644 --- a/yeelight/devicepluginyeelight.cpp +++ b/yeelight/devicepluginyeelight.cpp @@ -121,16 +121,53 @@ void DevicePluginYeelight::executeAction(DeviceActionInfo *info) if (action.actionTypeId() == colorBulbPowerActionTypeId) { bool power = action.param(colorBulbPowerActionPowerParamTypeId).value().toBool(); - yeelight->setPower(power); + int requestId = yeelight->setPower(power); + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); } else if (action.actionTypeId() == colorBulbBrightnessActionTypeId) { int brightness = action.param(colorBulbBrightnessActionBrightnessParamTypeId).value().toInt(); - yeelight->setBrightness(brightness); + int requestId = yeelight->setBrightness(brightness); + //TODO turn on if off + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); } else if (action.actionTypeId() == colorBulbColorActionColorParamTypeId) { QRgb color = action.param(colorBulbColorActionColorParamTypeId).value().toUInt(); - yeelight->setRgb(color); + int requestId = yeelight->setRgb(color); + //TODO turn on if off + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); } else if (action.actionTypeId() == colorBulbColorTemperatureActionTypeId) { int colorTemperature = action.param(colorBulbColorTemperatureActionColorTemperatureParamTypeId).value().toUInt() * 11.12; - yeelight->setColorTemperature(colorTemperature); + int requestId = yeelight->setColorTemperature(colorTemperature); + //TODO turn on if off + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); + } else if (action.actionTypeId() == colorBulbEffectActionTypeId) { + QString effect = action.param(colorBulbEffectActionEffectParamTypeId).value().toString(); + if (effect.contains("non")) { + int requestId = yeelight->stopColorFlow(); + //TODO turn on if off + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); + } else { + int requestId = yeelight->startColorFlow(); + //TODO turn on if off + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); + } + } else if (action.actionTypeId() == colorBulbAlertActionTypeId) { + QString alertType = action.param(colorBulbAlertActionAlertParamTypeId).value().toString(); + if (alertType.contains("15s")) { + int requestId = yeelight->flash15s(); + //TODO turn on if off + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); + } else { + int requestId = yeelight->flash(); + //TODO turn on if off + connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);}); + m_asyncActions.insert(requestId, info); + } } } } diff --git a/yeelight/devicepluginyeelight.json b/yeelight/devicepluginyeelight.json index f71da70b..4afb9ae1 100644 --- a/yeelight/devicepluginyeelight.json +++ b/yeelight/devicepluginyeelight.json @@ -13,7 +13,7 @@ "name": "colorBulb", "displayName": "Color bulb", "createMethods": ["user", "discovery"], - "interfaces": ["colorlight", "connectable"], + "interfaces": ["colorlight", "alert", "connectable"], "paramTypes": [ { "id": "a603ff66-0da8-42e8-942b-1632a22adefb", @@ -43,6 +43,24 @@ "id": "e80aea31-7ac0-4f71-9650-efb70ea1e768", "name": "default", "displayName": "Set default" + }, + { + "id": "ef558b8b-c4a1-4485-bd89-70749cc185b7", + "name": "alert", + "displayName": "flash", + "paramTypes": [ + { + "id": "944c9ab8-0f46-42f7-b814-8b72f9ca5407", + "name": "alert", + "displayName": "alert", + "type": "QString", + "defaultValue": "flash", + "allowedValues": [ + "flash", + "flash 15 [s]" + ] + } + ] } ], "stateTypes": [ @@ -100,6 +118,20 @@ "maxValue": 100, "writable": true }, + { + "id": "97082528-392c-4af3-8fe4-ff643045812f", + "name": "effect", + "displayName": "effect", + "displayNameEvent": "effect changed", + "displayNameAction": "Set effect", + "type": "QString", + "defaultValue": "none", + "possibleValues": [ + "none", + "color loop" + ], + "writable": true + }, { "id": "6babaf04-0247-447c-b429-d39f3d330f45", "name": "colorMode", diff --git a/yeelight/ssdp.cpp b/yeelight/ssdp.cpp index baaa23f4..82b97171 100644 --- a/yeelight/ssdp.cpp +++ b/yeelight/ssdp.cpp @@ -1,3 +1,25 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2020 Bernhard Trinnes * + * * + * This file is part of nymea. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "ssdp.h" #include "extern-plugininfo.h" diff --git a/yeelight/ssdp.h b/yeelight/ssdp.h index da7fbb12..8d439592 100644 --- a/yeelight/ssdp.h +++ b/yeelight/ssdp.h @@ -1,3 +1,25 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2020 Bernhard Trinnes * + * * + * This file is part of nymea. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef SSDP_H #define SSDP_H diff --git a/yeelight/yeelight.cpp b/yeelight/yeelight.cpp index 5080403c..2a1aae6d 100644 --- a/yeelight/yeelight.cpp +++ b/yeelight/yeelight.cpp @@ -251,6 +251,75 @@ int Yeelight::setDefault() return requestId; } +int Yeelight::startColorFlow() +{ + int requestId = static_cast(QRandomGenerator::global()->generate()); + QJsonDocument doc; + QJsonObject obj; + obj["id"] = requestId; + obj["method"] = "start_cf"; + QJsonArray params; + params.append(0); //0 means infinite loop on the state changing + params.append(0); //LED recover to the state before the color flow started + params.append("2000, 1, 255, -1, 2000, 1, 16711680, -1, 2000, 1, 65280, -1,"); //Colors + obj["params"] = params; + doc.setObject(obj); + qCDebug(dcYeelight()) << "Sending request" << doc.toJson(); + m_socket->write(doc.toJson() + "\r\n"); + return requestId; +} + +int Yeelight::stopColorFlow() +{ + int requestId = static_cast(QRandomGenerator::global()->generate()); + QJsonDocument doc; + QJsonObject obj; + obj["id"] = requestId; + obj["method"] = "stop_cf"; + QJsonArray params; + obj["params"] = params; + doc.setObject(obj); + qCDebug(dcYeelight()) << "Sending request" << doc.toJson(); + m_socket->write(doc.toJson() + "\r\n"); + return requestId; +} + +int Yeelight::flash() +{ + int requestId = static_cast(QRandomGenerator::global()->generate()); + QJsonDocument doc; + QJsonObject obj; + obj["id"] = requestId; + obj["method"] = "start_cf"; + QJsonArray params; + params.append(6); + params.append(0); //LED recover to the state before the color flow started + params.append("500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0,"); //Colors + obj["params"] = params; + doc.setObject(obj); + qCDebug(dcYeelight()) << "Sending request" << doc.toJson(); + m_socket->write(doc.toJson() + "\r\n"); + return requestId; +} + +int Yeelight::flash15s() +{ + int requestId = static_cast(QRandomGenerator::global()->generate()); + QJsonDocument doc; + QJsonObject obj; + obj["id"] = requestId; + obj["method"] = "start_cf"; + QJsonArray params; + params.append(30); + params.append(0); //LED recover to the state before the color flow started + params.append("500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0, 500, 2, 4000, 100, 500, 7, 0, 0"); //Colors + obj["params"] = params; + doc.setObject(obj); + qCDebug(dcYeelight()) << "Sending request" << doc.toJson(); + m_socket->write(doc.toJson() + "\r\n"); + return requestId; +} + void Yeelight::onStateChanged(QAbstractSocket::SocketState state) { switch (state) { diff --git a/yeelight/yeelight.h b/yeelight/yeelight.h index 4730576d..f3bee88b 100644 --- a/yeelight/yeelight.h +++ b/yeelight/yeelight.h @@ -80,10 +80,12 @@ public: int setBrightness(int percentage, int msFadeTime = 500); int setPower(bool power, int msFadeTime = 500); int setDefault(); - + int startColorFlow(); + int stopColorFlow(); + int flash(); + int flash15s(); private: - QTcpSocket *m_socket = nullptr; QHostAddress m_address; quint16 m_port; @@ -97,6 +99,13 @@ signals: void connectionChanged(bool connected); void requestExecuted(int requestId, bool success); void propertyListReceived(QVariantList value); + + /* + * Whenever there is state change of smart LED, it will send a notification message + * to all connected 3rd party devices. This is to make sure all 3rd party devices + * will get the latest state of the smart LED in time without having to poll the status + * from time to time. + */ void notificationReveiced(Property property, QVariant value); }; #endif // YEELIGHT_H