throttle brightness requests

This commit is contained in:
Boernsman 2019-12-27 22:13:32 +01:00
parent cda658f0a2
commit 9014a17618
5 changed files with 294 additions and 89 deletions

View File

@ -36,6 +36,18 @@ DevicePluginYeelight::DevicePluginYeelight()
}
void DevicePluginYeelight::init()
{
m_connectedStateTypeIds.insert(colorBulbDeviceClassId, colorBulbConnectedStateTypeId);
m_connectedStateTypeIds.insert(dimmableBulbDeviceClassId, dimmableBulbConnectedStateTypeId);
m_powerStateTypeIds.insert(colorBulbDeviceClassId, colorBulbPowerStateTypeId);
m_powerStateTypeIds.insert(dimmableBulbDeviceClassId, dimmableBulbPowerStateTypeId);
m_brightnessStateTypeIds.insert(colorBulbDeviceClassId, colorBulbBrightnessStateTypeId);
m_brightnessStateTypeIds.insert(dimmableBulbDeviceClassId, dimmableBulbBrightnessStateTypeId);
}
void DevicePluginYeelight::discoverDevices(DeviceDiscoveryInfo *info)
{
if (info->deviceClassId() == colorBulbDeviceClassId) {
@ -78,7 +90,7 @@ void DevicePluginYeelight::setupDevice(DeviceSetupInfo *info)
m_yeelightConnections.insert(device->id(), yeelight);
connect(yeelight, &Yeelight::connectionChanged, this, &DevicePluginYeelight::onConnectionChanged);
connect(yeelight, &Yeelight::requestExecuted, this, &DevicePluginYeelight::onRequestExecuted);
connect(yeelight, &Yeelight::propertyListReceived, this, &DevicePluginYeelight::onPropertyListReceived);
connect(yeelight, &Yeelight::colorModeNotificationReceived, this, &DevicePluginYeelight::onColorModeNotificationReceived);
connect(yeelight, &Yeelight::powerNotificationReceived, this, &DevicePluginYeelight::onPowerNotificationReceived);
connect(yeelight, &Yeelight::brightnessNotificationReceived, this, &DevicePluginYeelight::onBrightnessNotificationReceived);
connect(yeelight, &Yeelight::colorTemperatureNotificationReceived, this, &DevicePluginYeelight::onColorTemperatureNotificationReceived);
@ -99,31 +111,32 @@ void DevicePluginYeelight::postSetupDevice(Device *device)
Device *device = myDevices().findById(id);
Yeelight *yeelight = m_yeelightConnections.value(id);
if (yeelight->isConnected()) {
QList<Yeelight::Property> properties;
QList<Yeelight::YeelightProperty> properties;
if (device->deviceClassId() == colorBulbDeviceClassId) {
properties << Yeelight::Property::Name;
properties << Yeelight::Property::Ct;
properties << Yeelight::Property::Rgb;
properties << Yeelight::Property::Power;
properties << Yeelight::Property::Bright;
properties << Yeelight::Property::ColorMode;
properties << Yeelight::YeelightProperty::Name;
properties << Yeelight::YeelightProperty::Ct;
properties << Yeelight::YeelightProperty::Rgb;
properties << Yeelight::YeelightProperty::Power;
properties << Yeelight::YeelightProperty::Bright;
properties << Yeelight::YeelightProperty::ColorMode;
} //TODO add white color bulb with other property requests
yeelight->getParam(properties);
} else {
yeelight->connectDevice();
}
}
});
}
m_pluginTimer->timeout();
}
void DevicePluginYeelight::executeAction(DeviceActionInfo *info)
{
Device *device = info->device();
Action action = info->action();
Yeelight *yeelight = m_yeelightConnections.value(device->id());
if (!yeelight)
return info->finish(Device::DeviceErrorHardwareFailure);
if (device->deviceClassId() == colorBulbDeviceClassId) {
Yeelight *yeelight = m_yeelightConnections.value(device->id());
if (action.actionTypeId() == colorBulbPowerActionTypeId) {
bool power = action.param(colorBulbPowerActionPowerParamTypeId).value().toBool();
@ -131,12 +144,23 @@ void DevicePluginYeelight::executeAction(DeviceActionInfo *info)
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();
if (!device->stateValue(colorBulbPowerStateTypeId).toBool())
yeelight->setPower(true);
int requestId = yeelight->setBrightness(brightness);
connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
m_asyncActions.insert(requestId, info);
if (m_pendingBrightnessAction.contains(device->id())) {
//Scrap old info and insert new one
m_pendingBrightnessAction.insert(device->id(), info);
} else {
m_pendingBrightnessAction.insert(device->id(), info);
QTimer::singleShot(500, this, [yeelight, info, this]{
int brightness = info->action().param(colorBulbBrightnessActionBrightnessParamTypeId).value().toInt();
m_pendingBrightnessAction.remove(info->device()->id());
int requestId = yeelight->setBrightness(brightness);
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();
if (!device->stateValue(colorBulbPowerStateTypeId).toBool())
@ -180,6 +204,34 @@ void DevicePluginYeelight::executeAction(DeviceActionInfo *info)
} else {
qCWarning(dcYeelight()) << "Unhandled action";
}
} else if (device->deviceClassId() == dimmableBulbDeviceClassId) {
if (action.actionTypeId() == dimmableBulbPowerActionTypeId) {
bool power = action.param(dimmableBulbPowerActionPowerParamTypeId).value().toBool();
int requestId = yeelight->setPower(power);
connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == dimmableBulbBrightnessActionTypeId) {
int brightness = action.param(dimmableBulbBrightnessActionBrightnessParamTypeId).value().toInt();
if (!device->stateValue(dimmableBulbPowerStateTypeId).toBool())
yeelight->setPower(true);
int requestId = yeelight->setBrightness(brightness);
connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
m_asyncActions.insert(requestId, info);
} else if (action.actionTypeId() == dimmableBulbAlertActionTypeId) {
QString alertType = action.param(dimmableBulbAlertActionAlertParamTypeId).value().toString();
if (!device->stateValue(dimmableBulbPowerStateTypeId).toBool())
yeelight->setPower(true);
if (alertType.contains("15")) { //Flash 15 sec
int requestId = yeelight->flash15s();
connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
m_asyncActions.insert(requestId, info);
} else {
int requestId = yeelight->flash();
connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
m_asyncActions.insert(requestId, info);
}
} else {
qCWarning(dcYeelight()) << "Unhandled action";
}
} else {
qCWarning(dcYeelight()) << "Unhandled device class";
}
@ -187,7 +239,7 @@ void DevicePluginYeelight::executeAction(DeviceActionInfo *info)
void DevicePluginYeelight::deviceRemoved(Device *device)
{
if (device->deviceClassId() == colorBulbDeviceClassId){
if ((device->deviceClassId() == colorBulbDeviceClassId) || (device->deviceClassId() == dimmableBulbDeviceClassId)){
Yeelight *yeelight = m_yeelightConnections.take(device->id());
yeelight->deleteLater();
}
@ -207,7 +259,7 @@ void DevicePluginYeelight::onConnectionChanged(bool connected)
if(!device)
return;
device->setStateValue(colorBulbConnectedStateTypeId, connected);
device->setStateValue(m_connectedStateTypeIds.value(device->deviceClassId()), connected);
}
void DevicePluginYeelight::onRequestExecuted(int requestId, bool success)
@ -222,33 +274,6 @@ void DevicePluginYeelight::onRequestExecuted(int requestId, bool success)
}
}
void DevicePluginYeelight::onPropertyListReceived(QVariantList value)
{
Yeelight *yeelight = static_cast<Yeelight *>(sender());
Device * device = myDevices().findById(m_yeelightConnections.key(yeelight));
if(!device)
return;
/*
* properties << Yeelight::Property::Name;
* properties << Yeelight::Property::Ct;
* properties << Yeelight::Property::Rgb;
* properties << Yeelight::Property::Power;
* properties << Yeelight::Property::Bright;
* properties << Yeelight::Property::ColorMode;
*/
if(value.length() < 6)
return;
device->setName(value[0].toString());
device->setStateValue(colorBulbColorTemperatureStateTypeId, value[1].toInt());
device->setStateValue(colorBulbColorStateTypeId, value[2].toString());
device->setStateValue(colorBulbPowerStateTypeId, (value[3].toString() == "on"));
device->setStateValue(colorBulbBrightnessStateTypeId, value[4].toInt());
device->setStateValue(colorBulbColorModeStateTypeId, value[5].toString());
}
void DevicePluginYeelight::onPowerNotificationReceived(bool status)
{
Yeelight *yeelight = static_cast<Yeelight *>(sender());
@ -256,7 +281,7 @@ void DevicePluginYeelight::onPowerNotificationReceived(bool status)
if(!device)
return;
device->setStateValue(colorBulbPowerStateTypeId, status);
device->setStateValue(m_powerStateTypeIds.value(device->deviceClassId()), status);
}
void DevicePluginYeelight::onBrightnessNotificationReceived(int percentage)
@ -266,7 +291,7 @@ void DevicePluginYeelight::onBrightnessNotificationReceived(int percentage)
if(!device)
return;
device->setStateValue(colorBulbBrightnessStateTypeId, percentage);
device->setStateValue(m_brightnessStateTypeIds.value(device->deviceClassId()), percentage);
}
void DevicePluginYeelight::onColorTemperatureNotificationReceived(int kelvin)
@ -279,7 +304,7 @@ void DevicePluginYeelight::onColorTemperatureNotificationReceived(int kelvin)
device->setStateValue(colorBulbColorTemperatureStateTypeId, kelvin/11.12); //TODO needs proper conversion
}
void DevicePluginYeelight::onRgbNotificationReceived(int rgbColor)
void DevicePluginYeelight::onRgbNotificationReceived(QRgb rgbColor)
{
Yeelight *yeelight = static_cast<Yeelight *>(sender());
Device * device = myDevices().findById(m_yeelightConnections.key(yeelight));
@ -297,3 +322,23 @@ void DevicePluginYeelight::onNameNotificationReceived(const QString &name)
return;
device->setName(name);
}
void DevicePluginYeelight::onColorModeNotificationReceived(Yeelight::YeelightColorMode colorMode)
{
Yeelight *yeelight = static_cast<Yeelight *>(sender());
Device * device = myDevices().findById(m_yeelightConnections.key(yeelight));
if(!device)
return;
switch (colorMode) {
case Yeelight::RGB:
device->setStateValue(colorBulbColorModeStateTypeId, "RGB");
break;
case Yeelight::HSV:
device->setStateValue(colorBulbColorModeStateTypeId, "HSV");
break;
case Yeelight::ColorTemperature:
device->setStateValue(colorBulbColorModeStateTypeId, "Color temperature");
break;
}
}

View File

@ -41,6 +41,7 @@ class DevicePluginYeelight : public DevicePlugin
public:
explicit DevicePluginYeelight();
void init() override;
void discoverDevices(DeviceDiscoveryInfo *info) override;
void setupDevice(DeviceSetupInfo *info) override;
void postSetupDevice(Device *device) override;
@ -61,17 +62,23 @@ private:
QHash<int, DeviceActionInfo *> m_asyncActions;
QHash<DeviceId, Yeelight *> m_yeelightConnections;
QHash<DeviceClassId, StateTypeId> m_connectedStateTypeIds;
QHash<DeviceClassId, StateTypeId> m_powerStateTypeIds;
QHash<DeviceClassId, StateTypeId> m_brightnessStateTypeIds;
QHash<DeviceId, DeviceActionInfo *> m_pendingBrightnessAction;
private slots:
void onDeviceNameChanged();
void onConnectionChanged(bool connected);
void onRequestExecuted(int requestId, bool success);
void onPropertyListReceived(QVariantList value);
void onPowerNotificationReceived(bool status);
void onBrightnessNotificationReceived(int percentage);
void onColorTemperatureNotificationReceived(int kelvin);
void onRgbNotificationReceived(int rgbColor);
void onRgbNotificationReceived(QRgb rgbColor);
void onNameNotificationReceived(const QString &name);
void onColorModeNotificationReceived(Yeelight::YeelightColorMode colorMode);
};
#endif // DEVICEPLUGINYEELIGHT_H

View File

@ -143,6 +143,95 @@
"writable": true
}
]
},
{
"id": "5112eb03-7b5a-44a1-994a-01a70c850555",
"name": "dimmableBulb",
"displayName": "Dimmable bulb",
"createMethods": ["user", "discovery"],
"interfaces": ["dimmablelight", "alert", "connectable"],
"paramTypes": [
{
"id": "32f4f50c-a3f2-4379-8838-295024d200b4",
"name": "host",
"displayName": "Host address",
"type" : "QString",
"inputType": "IPv4Address",
"readOnly": true
},
{
"id": "df51023e-7f18-4e11-8c7a-30d153b50952",
"name": "port",
"displayName": "Port",
"type" : "int",
"readOnly": true
},
{
"id": "5a526561-588a-49bd-ae2b-ce3c3b4fd04e",
"name": "id",
"displayName": "Id",
"type" : "QString",
"readOnly": true
}
],
"actionTypes": [
{
"id": "a50780d1-259d-4240-8f71-a0bb5c57362b",
"name": "default",
"displayName": "Set default"
},
{
"id": "ba513820-1ace-4ad2-aa84-b7bd01318bc3",
"name": "alert",
"displayName": "flash",
"paramTypes": [
{
"id": "1c0f4e9e-95fd-4715-8386-9ac28ffa3c6e",
"name": "alert",
"displayName": "alert",
"type": "QString",
"defaultValue": "flash",
"allowedValues": [
"flash",
"flash 15 [s]"
]
}
]
}
],
"stateTypes": [
{
"id": "fcfe37cb-4c9d-4af2-9789-56190c9d8d7f",
"name": "connected",
"displayName": "Reachable",
"displayNameEvent": "Reachable changed",
"defaultValue": false,
"type": "bool"
},
{
"id": "0786e242-1257-437c-9327-f202b427ab1b",
"name": "power",
"displayName": "Power",
"displayNameEvent": "Power changed",
"displayNameAction": "Set power",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "b0db1fd8-cec8-4cd4-acd0-5fc415095e10",
"name": "brightness",
"displayName": "Brightness",
"displayNameEvent": "Brightness changed",
"displayNameAction": "Set brigtness",
"type": "int",
"unit": "Percentage",
"defaultValue": 0,
"minValue": 0,
"maxValue": 100,
"writable": true
}
]
}
]
}

View File

@ -41,6 +41,10 @@ Yeelight::Yeelight(NetworkAccessManager *networkManager, const QHostAddress &add
connect(m_socket, &QTcpSocket::stateChanged, this, &Yeelight::onStateChanged);
connect(m_socket, &QTcpSocket::readyRead, this, &Yeelight::onReadyRead);
m_socket->connectToHost(address, port);
m_reconnectTimer = new QTimer(this);
m_reconnectTimer->setSingleShot(true);
connect(m_reconnectTimer, &QTimer::timeout, this, &Yeelight::onReconnectTimer);
}
bool Yeelight::isConnected()
@ -54,7 +58,7 @@ void Yeelight::connectDevice()
}
int Yeelight::getParam(QList<Yeelight::Property> properties)
int Yeelight::getParam(QList<Yeelight::YeelightProperty> properties)
{
int requestId = static_cast<int>(QRandomGenerator::global()->generate());
QJsonDocument doc;
@ -62,81 +66,83 @@ int Yeelight::getParam(QList<Yeelight::Property> properties)
obj["id"] = requestId;
obj["method"] = "get_prop";
QJsonArray params;
m_propertyRequests.insert(requestId, properties);
foreach (Property property, properties) {
foreach (YeelightProperty property, properties) {
switch (property) {
case Property::Ct:
case YeelightProperty::Ct:
params.append("ct");
break;
case Property::Power:
case YeelightProperty::Power:
params.append("power");
break;
case Property::Bright:
case YeelightProperty::Bright:
params.append("bright");
break;
case Property::Hue:
case YeelightProperty::Hue:
params.append("hue");
break;
case Property::Rgb:
case YeelightProperty::Rgb:
params.append("rgb");
break;
case Property::Sat:
case YeelightProperty::Sat:
params.append("sat");
break;
case Property::Name:
case YeelightProperty::Name:
params.append("name");
break;
case Property::BgCt:
case YeelightProperty::BgCt:
params.append("bg_ct");
break;
case Property::NlBr:
case YeelightProperty::NlBr:
params.append("nl_br");
break;
case Property::BgHue:
case YeelightProperty::BgHue:
params.append("bg_hue");
break;
case Property::BgRgb:
case YeelightProperty::BgRgb:
params.append("bg_rgb");
break;
case Property::BgSat:
case YeelightProperty::BgSat:
params.append("bg_sat");
break;
case Property::BgLmode:
case YeelightProperty::BgLmode:
params.append("bg_lmode");
break;
case Property::BgPower:
case YeelightProperty::BgPower:
params.append("bg_power");
break;
case Property::Flowing:
case YeelightProperty::Flowing:
params.append("flowing");
break;
case Property::MusicOn:
case YeelightProperty::MusicOn:
params.append("music_on");
break;
case Property::BgBright:
case YeelightProperty::BgBright:
params.append("bg_bright");
break;
case Property::DelayOff:
case YeelightProperty::DelayOff:
params.append("delay_off");
break;
case Property::BgFlowing:
case YeelightProperty::BgFlowing:
params.append("bg_flowing");
break;
case Property::ColorMode:
case YeelightProperty::ColorMode:
params.append("color_mode");
break;
case Property::ActiveMode:
case YeelightProperty::ActiveMode:
params.append("active_mode");
break;
case Property::FlowParams:
case YeelightProperty::FlowParams:
params.append("flow_params");
break;
case Property::BgFlowParams:
case YeelightProperty::BgFlowParams:
params.append("bg_flow_params");
break;
}
}
QTimer::singleShot(10000, this, [requestId, this]{m_propertyRequests.remove(requestId);});
obj["params"] = params;
doc.setObject(obj);
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
@ -326,6 +332,10 @@ void Yeelight::onStateChanged(QAbstractSocket::SocketState state)
case QAbstractSocket::SocketState::ConnectedState:
emit connectionChanged(true);
break;
case QAbstractSocket::SocketState::UnconnectedState:
m_reconnectTimer->start(10 * 1000);
emit connectionChanged(false);
break;
default:
emit connectionChanged(false);
break;
@ -344,7 +354,17 @@ void Yeelight::onReadyRead()
return;
}
QVariantMap map = doc.toVariant().toMap();
if (map.contains("method")) {
if (map.contains("error")) {
if(map.contains("id")) {
emit requestExecuted(map["id"].toInt(), false);
}
QVariantMap error = map["error"].toMap();
int code = error["code"].toInt();
QString message = error["message"].toString();
qCWarning(dcYeelight()) << "Error received: Code" << code << message;
emit errorReceived(code, message);
}else if (map.contains("method")) {
if (map["method"] == "props") {
QVariantMap params = map["params"].toMap();
if (params.contains("power")) {
@ -357,7 +377,7 @@ void Yeelight::onReadyRead()
emit colorTemperatureNotificationReceived(params["ct"].toInt());
}
if (params.contains("rgb")) {
emit rgbNotificationReceived(params["rgb"].toInt());
emit rgbNotificationReceived(QRgb(params["rgb"].toInt()));
}
if (params.contains("hue")) {
emit hueNotificationReceived(params["hue"].toInt());
@ -366,7 +386,7 @@ void Yeelight::onReadyRead()
emit nameNotificationReceived(params["name"].toString());
}
if (params.contains("color_mode")) {
//emit colorModeNotificationReceived(static_cast<ColorMode>((params["color_mode"].toInt())));
emit colorModeNotificationReceived(YeelightColorMode(params["color_mode"].toInt()));
}
if (params.contains("sat")) {
emit saturationNotificationReceived(params["sat"].toInt());
@ -378,14 +398,55 @@ void Yeelight::onReadyRead()
if ((result.length() == 1)) {
if (result.first().toString() == "ok") {
emit requestExecuted(id, true);
} else {
//TODO parse error, status code and error string
//emit errorReceived()
}
} else {
emit propertyListReceived(result);
if (m_propertyRequests.contains(id)) {
QList<YeelightProperty> properties = m_propertyRequests.take(id);
foreach (YeelightProperty property, properties) {
if (result.isEmpty()){
qCWarning(dcYeelight()) << "Value count does not match properties" << properties.count();
break;
}
QVariant value = result.takeFirst();
switch (property) {
case YeelightProperty::Name:
emit nameNotificationReceived(value.toString());
break;
case YeelightProperty::Ct:
emit colorTemperatureNotificationReceived(value.toInt());
break;
case YeelightProperty::Rgb:
emit rgbNotificationReceived(QRgb(value.toInt()));
break;
case YeelightProperty::Hue:
emit hueNotificationReceived(value.toInt());
break;
case YeelightProperty::Bright:
emit brightnessNotificationReceived(value.toInt());
break;
case YeelightProperty::Power:
emit powerNotificationReceived((value.toString() == "on"));
break;
case YeelightProperty::ColorMode:
emit colorModeNotificationReceived(YeelightColorMode(value.toInt()));
break;
case YeelightProperty::Sat:
emit saturationNotificationReceived(value.toInt());
break;
default:
qCWarning(dcYeelight()) << "Unhandled Yeelight property";
}
}
}
}
}
}
void Yeelight::onReconnectTimer()
{
if(!m_socket->isOpen()) {
m_socket->connectToHost(m_address, m_port);
}
}

View File

@ -37,13 +37,13 @@ class Yeelight : public QObject
{
Q_OBJECT
public:
enum ColorMode {
enum YeelightColorMode {
RGB = 1,
Temperature,
ColorTemperature,
HSV
};
enum Property {
enum YeelightProperty {
Power, //on: smart LED is turned on / off: smart LED is turned off
Bright, //Brightness percentage. Range 1 ~ 100
Ct, //Color temperature. Range 1700 ~ 6500(k)
@ -73,7 +73,7 @@ public:
bool isConnected();
void connectDevice();
int getParam(QList<Property> properties);
int getParam(QList<YeelightProperty> properties);
int setName(const QString &name);
int setColorTemperature(int mirad, int msFadeTime=500);
int setRgb(QRgb color, int msFadeTime = 500);
@ -86,19 +86,22 @@ public:
int flash15s();
private:
QTimer *m_reconnectTimer = nullptr;
QTcpSocket *m_socket = nullptr;
QHostAddress m_address;
quint16 m_port;
NetworkAccessManager *m_networkManager = nullptr;
QHash<int, QList<YeelightProperty>> m_propertyRequests;
private slots:
void onStateChanged(QAbstractSocket::SocketState state);
void onReadyRead();
void onReconnectTimer();
signals:
void connectionChanged(bool connected);
void requestExecuted(int requestId, bool success);
void propertyListReceived(QVariantList value);
void errorReceived(int code, const QString &message);
/*
* Whenever there is state change of smart LED, it will send a notification message
@ -106,14 +109,14 @@ signals:
* will get the latest state of the smart LED in time without having to poll the status
* from time to time.
*/
void notificationReceived(Property property, QVariant value);
void notificationReceived(YeelightProperty property, QVariant value);
void powerNotificationReceived(bool status);
void brightnessNotificationReceived(int percentage);
void colorTemperatureNotificationReceived(int kelvin);
void rgbNotificationReceived(int rgbColor);
void rgbNotificationReceived(QRgb rgbColor);
void hueNotificationReceived(int hueColor);
void nameNotificationReceived(const QString &name);
void saturationNotificationReceived(int percentage);
//void colorModeNotificationReceived(ColorMode colorMode);
void colorModeNotificationReceived(YeelightColorMode colorMode);
};
#endif // YEELIGHT_H