mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-18 00:43:48 +02:00
API unstability of Yeelight is bugging me
This commit is contained in:
parent
9014a17618
commit
c78d3663d9
@ -1 +1,5 @@
|
||||
# Yeelight
|
||||
|
||||
This plug-in supports dimmable- and color bulbs from yeelight.
|
||||
|
||||
Discovery works with min. firmware version 2.0.6_0065
|
||||
|
||||
@ -46,19 +46,19 @@ void DevicePluginYeelight::init()
|
||||
|
||||
m_brightnessStateTypeIds.insert(colorBulbDeviceClassId, colorBulbBrightnessStateTypeId);
|
||||
m_brightnessStateTypeIds.insert(dimmableBulbDeviceClassId, dimmableBulbBrightnessStateTypeId);
|
||||
|
||||
m_ssdp = new Ssdp(this);
|
||||
m_ssdp->enable();
|
||||
m_ssdp->discover();
|
||||
}
|
||||
|
||||
void DevicePluginYeelight::discoverDevices(DeviceDiscoveryInfo *info)
|
||||
{
|
||||
if (info->deviceClassId() == colorBulbDeviceClassId) {
|
||||
|
||||
DiscoveryJob *discovery = new DiscoveryJob();
|
||||
m_discoveries.insert(info, discovery);
|
||||
|
||||
qCDebug(dcYeelight()) << "Starting UPnP discovery...";
|
||||
Ssdp *ssdp = new Ssdp(this);
|
||||
ssdp->enable();
|
||||
ssdp->discover();
|
||||
/*
|
||||
connect(ssdp, &Ssdp::discovered, this,[info, this](const QString &address, int port, int id, const QString &model) {
|
||||
|
||||
DeviceDescriptor descriptor(colorBulbDeviceClassId, "Yeelight"+ model + "Bulb", address);
|
||||
@ -75,7 +75,7 @@ void DevicePluginYeelight::discoverDevices(DeviceDiscoveryInfo *info)
|
||||
descriptor.setParams(params);
|
||||
qCDebug(dcYeelight()) << "UPnP: Found Yeelight device:" << id;
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,13 +113,15 @@ void DevicePluginYeelight::postSetupDevice(Device *device)
|
||||
if (yeelight->isConnected()) {
|
||||
QList<Yeelight::YeelightProperty> properties;
|
||||
if (device->deviceClassId() == colorBulbDeviceClassId) {
|
||||
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
|
||||
} else if (device->deviceClassId() == colorBulbDeviceClassId) {
|
||||
properties << Yeelight::YeelightProperty::Power;
|
||||
properties << Yeelight::YeelightProperty::Bright;
|
||||
}
|
||||
yeelight->getParam(properties);
|
||||
}
|
||||
}
|
||||
@ -162,14 +164,14 @@ void DevicePluginYeelight::executeAction(DeviceActionInfo *info)
|
||||
});
|
||||
}
|
||||
} else if (action.actionTypeId() == colorBulbColorActionColorParamTypeId) {
|
||||
QRgb color = action.param(colorBulbColorActionColorParamTypeId).value().toUInt();
|
||||
QRgb color = QColor(action.param(colorBulbColorActionColorParamTypeId).value().toString()).rgba();
|
||||
if (!device->stateValue(colorBulbPowerStateTypeId).toBool())
|
||||
yeelight->setPower(true);
|
||||
int requestId = yeelight->setRgb(color);
|
||||
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;
|
||||
int colorTemperature = 6500 - (action.param(colorBulbColorTemperatureActionColorTemperatureParamTypeId).value().toUInt() * -11.12);
|
||||
if (!device->stateValue(colorBulbPowerStateTypeId).toBool())
|
||||
yeelight->setPower(true);
|
||||
int requestId = yeelight->setColorTemperature(colorTemperature);
|
||||
@ -201,6 +203,10 @@ 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() == colorBulbDefaultActionTypeId) {
|
||||
int requestId = yeelight->setDefault();
|
||||
connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
|
||||
m_asyncActions.insert(requestId, info);
|
||||
} else {
|
||||
qCWarning(dcYeelight()) << "Unhandled action";
|
||||
}
|
||||
@ -229,6 +235,10 @@ 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() == dimmableBulbDefaultActionTypeId) {
|
||||
int requestId = yeelight->setDefault();
|
||||
connect(info, &DeviceActionInfo::aborted, this, [requestId, this] {m_asyncActions.remove(requestId);});
|
||||
m_asyncActions.insert(requestId, info);
|
||||
} else {
|
||||
qCWarning(dcYeelight()) << "Unhandled action";
|
||||
}
|
||||
@ -239,7 +249,8 @@ void DevicePluginYeelight::executeAction(DeviceActionInfo *info)
|
||||
|
||||
void DevicePluginYeelight::deviceRemoved(Device *device)
|
||||
{
|
||||
if ((device->deviceClassId() == colorBulbDeviceClassId) || (device->deviceClassId() == dimmableBulbDeviceClassId)){
|
||||
if ((device->deviceClassId() == colorBulbDeviceClassId) ||
|
||||
(device->deviceClassId() == dimmableBulbDeviceClassId)){
|
||||
Yeelight *yeelight = m_yeelightConnections.take(device->id());
|
||||
yeelight->deleteLater();
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include "network/upnp/upnpdiscovery.h"
|
||||
#include "yeelight.h"
|
||||
#include "ssdp.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
@ -49,15 +50,7 @@ public:
|
||||
void deviceRemoved(Device *device) override;
|
||||
|
||||
private:
|
||||
class DiscoveryJob {
|
||||
public:
|
||||
UpnpDiscoveryReply* upnpReply;
|
||||
QNetworkReply* nUpnpReply;
|
||||
DeviceDescriptors results;
|
||||
};
|
||||
QHash<DeviceDiscoveryInfo*, DiscoveryJob*> m_discoveries;
|
||||
QList<QString> m_usedInterfaces;
|
||||
|
||||
Ssdp *m_ssdp = nullptr;
|
||||
PluginTimer *m_pluginTimer = nullptr;
|
||||
QHash<int, DeviceActionInfo *> m_asyncActions;
|
||||
QHash<DeviceId, Yeelight *> m_yeelightConnections;
|
||||
|
||||
@ -53,6 +53,7 @@ bool Ssdp::enable()
|
||||
|
||||
// Bind udp socket and join multicast group
|
||||
m_socket = new QUdpSocket(this);
|
||||
m_socket2 = new QUdpSocket(this);
|
||||
m_port = 1982;
|
||||
m_host = QHostAddress("239.255.255.250");
|
||||
|
||||
@ -67,6 +68,13 @@ bool Ssdp::enable()
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!m_socket2->bind(QHostAddress::AnyIPv4, 34343, QUdpSocket::ShareAddress)){
|
||||
qCWarning(dcYeelight()) << "could not bind to port" << 34343;
|
||||
delete m_socket2;
|
||||
m_socket2 = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!m_socket->joinMulticastGroup(m_host)){
|
||||
qCWarning(dcYeelight()) << "could not join multicast group" << m_host;
|
||||
m_available = false;
|
||||
@ -76,6 +84,7 @@ bool Ssdp::enable()
|
||||
}
|
||||
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
|
||||
connect(m_socket, &QUdpSocket::readyRead, this, &Ssdp::readData);
|
||||
connect(m_socket2, &QUdpSocket::readyRead, this, &Ssdp::readData2);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -84,8 +93,8 @@ void Ssdp::discover()
|
||||
QByteArray searchMessage = QByteArray("M-SEARCH * HTTP/1.1\r\n"
|
||||
"HOST: 239.255.255.250:1982\r\n"
|
||||
"MAN: \"ssdp:discover\"\r\n"
|
||||
"ST: wifi_bulb\r\n\r\n");
|
||||
m_socket->writeDatagram(searchMessage, m_host, m_port);
|
||||
"ST: wifi_bulb\r\n");
|
||||
m_socket2->writeDatagram(searchMessage, m_host, m_port);
|
||||
}
|
||||
|
||||
|
||||
@ -134,6 +143,20 @@ void Ssdp::readData()
|
||||
}
|
||||
}
|
||||
|
||||
void Ssdp::readData2()
|
||||
{
|
||||
QByteArray data;
|
||||
quint16 port;
|
||||
QHostAddress hostAddress;
|
||||
|
||||
// read the answere from the multicast
|
||||
while (m_socket->hasPendingDatagrams()) {
|
||||
data.resize(m_socket->pendingDatagramSize());
|
||||
m_socket->readDatagram(data.data(), data.size(), &hostAddress, &port);
|
||||
}
|
||||
qCDebug(dcYeelight())<< "SSDP message received " << data;
|
||||
}
|
||||
|
||||
|
||||
bool Ssdp::disable()
|
||||
{
|
||||
|
||||
@ -45,6 +45,7 @@ public:
|
||||
bool disable();
|
||||
private:
|
||||
QUdpSocket *m_socket = nullptr;
|
||||
QUdpSocket *m_socket2 = nullptr;
|
||||
QHostAddress m_host;
|
||||
quint16 m_port;
|
||||
|
||||
@ -64,6 +65,7 @@ signals:
|
||||
private slots:
|
||||
void error(QAbstractSocket::SocketError error);
|
||||
void readData();
|
||||
void readData2();
|
||||
};
|
||||
|
||||
#endif // SSDP_H
|
||||
|
||||
@ -145,7 +145,7 @@ int Yeelight::getParam(QList<Yeelight::YeelightProperty> properties)
|
||||
QTimer::singleShot(10000, this, [requestId, this]{m_propertyRequests.remove(requestId);});
|
||||
obj["params"] = params;
|
||||
doc.setObject(obj);
|
||||
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
//qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
m_socket->write(doc.toJson() + "\r\n");
|
||||
return requestId;
|
||||
}
|
||||
@ -161,7 +161,7 @@ int Yeelight::setName(const QString &name)
|
||||
params.append(name);
|
||||
obj["params"] = params;
|
||||
doc.setObject(obj);
|
||||
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
//qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
m_socket->write(doc.toJson() + "\r\n");
|
||||
return requestId;
|
||||
}
|
||||
@ -192,12 +192,12 @@ int Yeelight::setRgb(QRgb color, int msFadeTime)
|
||||
obj["id"] = requestId;
|
||||
obj["method"] = "set_rgb";
|
||||
QJsonArray params;
|
||||
params.append(QVariant(color).toInt());
|
||||
params.append(static_cast<int>(color & 0x00ffffff));
|
||||
params.append("smooth");
|
||||
params.append(msFadeTime);
|
||||
obj["params"] = params;
|
||||
doc.setObject(obj);
|
||||
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
//qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
m_socket->write(doc.toJson() + "\r\n");
|
||||
return requestId;
|
||||
}
|
||||
@ -252,7 +252,7 @@ int Yeelight::setDefault()
|
||||
QJsonArray params;
|
||||
obj["params"] = params;
|
||||
doc.setObject(obj);
|
||||
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
//qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
m_socket->write(doc.toJson() + "\r\n");
|
||||
return requestId;
|
||||
}
|
||||
@ -267,7 +267,7 @@ int Yeelight::startColorFlow()
|
||||
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
|
||||
params.append("2000, 1, 255, 50, 2000, 1, 5000, 50, 2000, 1, 6000, 50"); //Colors
|
||||
obj["params"] = params;
|
||||
doc.setObject(obj);
|
||||
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
@ -298,9 +298,9 @@ int Yeelight::flash()
|
||||
obj["id"] = requestId;
|
||||
obj["method"] = "start_cf";
|
||||
QJsonArray params;
|
||||
params.append(6);
|
||||
params.append(4 * 3);
|
||||
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
|
||||
params.append("50, 2, 6500, 100, 500, 7, 6500, 1, 50, 2, 6500, 1, 500, 7, 6500, 1");
|
||||
obj["params"] = params;
|
||||
doc.setObject(obj);
|
||||
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
@ -316,9 +316,9 @@ int Yeelight::flash15s()
|
||||
obj["id"] = requestId;
|
||||
obj["method"] = "start_cf";
|
||||
QJsonArray params;
|
||||
params.append(30);
|
||||
params.append(4 * 15);
|
||||
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
|
||||
params.append("50, 2, 6500, 100, 500, 7, 6500, 1, 50, 2, 6500, 1, 500, 7, 6500, 1");
|
||||
obj["params"] = params;
|
||||
doc.setObject(obj);
|
||||
qCDebug(dcYeelight()) << "Sending request" << doc.toJson();
|
||||
@ -345,7 +345,7 @@ void Yeelight::onStateChanged(QAbstractSocket::SocketState state)
|
||||
void Yeelight::onReadyRead()
|
||||
{
|
||||
QByteArray data = m_socket->readAll();
|
||||
qCDebug(dcYeelight()) << "Message received" << data;
|
||||
//qCDebug(dcYeelight()) << "Message received" << data;
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||
@ -446,6 +446,7 @@ void Yeelight::onReconnectTimer()
|
||||
{
|
||||
if(!m_socket->isOpen()) {
|
||||
m_socket->connectToHost(m_address, m_port);
|
||||
m_reconnectTimer->start(10 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,9 +7,9 @@ TARGET = $$qtLibraryTarget(nymea_devicepluginyeelight)
|
||||
SOURCES += \
|
||||
devicepluginyeelight.cpp \
|
||||
yeelight.cpp \
|
||||
ssdp.cpp
|
||||
ssdp.cpp \
|
||||
|
||||
HEADERS += \
|
||||
devicepluginyeelight.h \
|
||||
yeelight.h \
|
||||
ssdp.h
|
||||
ssdp.h \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user