properly handle all types of panels: HOME, PRO, ADV and HUT

This commit is contained in:
Michael Zanetti 2019-01-07 03:38:34 +01:00
parent 2adbb4c8df
commit 1345fe99ff
3 changed files with 656 additions and 145 deletions

View File

@ -39,6 +39,109 @@
\quotefile plugins/deviceplugins/tasmota/devicepluginanel.json
*/
/*
Example reply for HOME and PRO:
HOME: GET /daten.cfg: Length 13
0: NET-CONTROL ;
1: Mo, 07.01.19 02:24:54;
2: 18;
3: ;
4: 12;
5: 1;
6: Login: <b>user7</b> 10.10.10.128;
7: 4.5 DE;
8: 7648;
9: 0;
10: H;
11: end;
12: NET - Power Control
ADV: GET /daten.cfg: Length 11
0: 1546827738;
1: 64;
2: 0;
3: 37;
4: 1;
5: 19789;
6: 5;
7: 24.7;
8: 9;
9: 2;
10: end
HUT: GET /daten.cfg: Length 18
0: 1546830796;
1: 93;
2: 41;
3: 194;
4: 1;
5: 12587;
6: 14;
7: 24.7;
8: 9;
9: 2;
10: end;
11: s;
12: 1;
13: 22.90;
14: 44.4;
15: 851;
16: 1;
17: 0.00;
HOME/PRO GET strg.cfg: Length 60
0: NET-PWRCTRL_04.5; // device name
1: NET-CONTROL ; // hostname
2: 10.10.10.132; // IP
3: 255.255.255.0; // Netmask
4: 10.10.10.1; // Gateway
5: 00:04:A3:0B:0C:3A; // MAC
6: 80; // Webcontrol port
7: ; // Temp
8: H; // Type
9: ; // ?? (Skipped by upstream code)
Following fields are repeated 8 times each, one for each socket
10: Nr. 1; // Name 1
11: 1; // Stand
12: 0; // Dis
13: Anfangsstatus; // Info
14: ; // TK
end;
NET - Power Control"
ADV: GET /strg.cfg: Length 58
0: Nr.1;0;0;28;K;
5: Nr.2;0;0;28;;
10: Nr.3;1;0;27;;
15: Nr.4;0;0;28;;
20: Nr.5;0;0;28;;
25: Nr.6;0;0;28;;
30: Nr.7;0;0;0;;
35: Nr.8;0;0;28;;
40: end;
41: 0;
42: 0;
43: 0;
44: 1;
45: 0;
46: 0;
47: 0;
48: 1;
49: 10122;
50: 10123;
51: 10124;
52: 8657;
53: 10126;
54: 10127;
55: 10128;
56: 8659;
*/
#include "devicepluginanel.h"
#include "plugininfo.h"
#include "plugintimer.h"
@ -46,11 +149,35 @@
#include <network/networkaccessmanager.h>
#include <QNetworkReply>
#include <QAuthenticator>
#include <QUrlQuery>
DevicePluginAnel::DevicePluginAnel()
{
m_connectedStateTypeIdMap.insert(netPwrCtlDeviceClassId, netPwrCtlConnectedStateTypeId);
m_connectedStateTypeIdMap.insert(netPwrCtlHomeDeviceClassId, netPwrCtlHomeConnectedStateTypeId);
m_connectedStateTypeIdMap.insert(netPwrCtlProDeviceClassId, netPwrCtlProConnectedStateTypeId);
m_connectedStateTypeIdMap.insert(netPwrCtlAdvDeviceClassId, netPwrCtlAdvConnectedStateTypeId);
m_connectedStateTypeIdMap.insert(netPwrCtlHutDeviceClassId, netPwrCtlHutConnectedStateTypeId);
m_connectedStateTypeIdMap.insert(socketDeviceClassId, socketConnectedStateTypeId);
m_ipAddressParamTypeIdMap.insert(netPwrCtlHomeDeviceClassId, netPwrCtlHomeDeviceIpAddressParamTypeId);
m_ipAddressParamTypeIdMap.insert(netPwrCtlProDeviceClassId, netPwrCtlProDeviceIpAddressParamTypeId);
m_ipAddressParamTypeIdMap.insert(netPwrCtlAdvDeviceClassId, netPwrCtlAdvDeviceIpAddressParamTypeId);
m_ipAddressParamTypeIdMap.insert(netPwrCtlHutDeviceClassId, netPwrCtlHutDeviceIpAddressParamTypeId);
m_portParamTypeIdMap.insert(netPwrCtlHomeDeviceClassId, netPwrCtlHomeDevicePortParamTypeId);
m_portParamTypeIdMap.insert(netPwrCtlProDeviceClassId, netPwrCtlProDevicePortParamTypeId);
m_portParamTypeIdMap.insert(netPwrCtlAdvDeviceClassId, netPwrCtlAdvDevicePortParamTypeId);
m_portParamTypeIdMap.insert(netPwrCtlHutDeviceClassId, netPwrCtlHutDevicePortParamTypeId);
m_userParamTypeIdMap.insert(netPwrCtlHomeDeviceClassId, netPwrCtlHomeDeviceUsernameParamTypeId);
m_userParamTypeIdMap.insert(netPwrCtlProDeviceClassId, netPwrCtlProDeviceUsernameParamTypeId);
m_userParamTypeIdMap.insert(netPwrCtlAdvDeviceClassId, netPwrCtlAdvDeviceUsernameParamTypeId);
m_userParamTypeIdMap.insert(netPwrCtlHutDeviceClassId, netPwrCtlHutDeviceUsernameParamTypeId);
m_passParamTypeIdMap.insert(netPwrCtlHomeDeviceClassId, netPwrCtlHomeDevicePasswordParamTypeId);
m_passParamTypeIdMap.insert(netPwrCtlProDeviceClassId, netPwrCtlProDevicePasswordParamTypeId);
m_passParamTypeIdMap.insert(netPwrCtlAdvDeviceClassId, netPwrCtlAdvDevicePasswordParamTypeId);
m_passParamTypeIdMap.insert(netPwrCtlHutDeviceClassId, netPwrCtlHutDevicePasswordParamTypeId);
}
DevicePluginAnel::~DevicePluginAnel()
@ -79,7 +206,7 @@ DeviceManager::DeviceError DevicePluginAnel::discoverDevices(const DeviceClassId
return DeviceManager::DeviceErrorHardwareFailure;
}
QTimer::singleShot(2000, this, [this, searchSocket](){
QTimer::singleShot(2000, this, [this, searchSocket, deviceClassId](){
QList<DeviceDescriptor> descriptorList;
while(searchSocket->hasPendingDatagrams()) {
char buffer[1024];
@ -97,9 +224,15 @@ DeviceManager::DeviceError DevicePluginAnel::discoverDevices(const DeviceClassId
continue;
}
qCDebug(dcAnelElektronik()) << "Found NET-CONTROL:" << senderAddress << parts.at(2) << parts.at(3) << senderAddress.protocol();
ParamTypeId ipAddressParamTypeId = m_ipAddressParamTypeIdMap.value(deviceClassId);
ParamTypeId portParamTypeId = m_portParamTypeIdMap.value(deviceClassId);
ParamTypeId userParamTypeId = m_userParamTypeIdMap.value(deviceClassId);
ParamTypeId passParamTypeId = m_passParamTypeIdMap.value(deviceClassId);
bool existing = false;
foreach (Device *existingDev, myDevices()) {
if (existingDev->deviceClassId() == netPwrCtlDeviceClassId && existingDev->paramValue(netPwrCtlDeviceIpAddressParamTypeId).toString() == senderAddress.toString()) {
if (existingDev->deviceClassId() == deviceClassId && existingDev->paramValue(ipAddressParamTypeId).toString() == senderAddress.toString()) {
existing = true;
}
}
@ -107,16 +240,16 @@ DeviceManager::DeviceError DevicePluginAnel::discoverDevices(const DeviceClassId
qCDebug(dcAnelElektronik()) << "Already have device" << senderAddress << "in configured devices. Skipping...";
continue;
}
DeviceDescriptor d(netPwrCtlDeviceClassId, parts.at(2), senderAddress.toString());
DeviceDescriptor d(deviceClassId, parts.at(2), senderAddress.toString());
ParamList params;
params << Param(netPwrCtlDeviceIpAddressParamTypeId, senderAddress.toString());
params << Param(netPwrCtlDevicePortParamTypeId, parts.at(3).toInt());
params << Param(netPwrCtlDeviceUsernameParamTypeId, "user7");
params << Param(netPwrCtlDevicePasswordParamTypeId, "anel");
params << Param(ipAddressParamTypeId, senderAddress.toString());
params << Param(portParamTypeId, parts.at(3).toInt());
params << Param(userParamTypeId, "user7");
params << Param(passParamTypeId, "anel");
d.setParams(params);
descriptorList << d;
}
emit devicesDiscovered(netPwrCtlDeviceClassId, descriptorList);
emit devicesDiscovered(deviceClassId, descriptorList);
searchSocket->deleteLater();
});
return DeviceManager::DeviceErrorAsync;
@ -124,95 +257,13 @@ DeviceManager::DeviceError DevicePluginAnel::discoverDevices(const DeviceClassId
DeviceManager::DeviceSetupStatus DevicePluginAnel::setupDevice(Device *device)
{
if (device->deviceClassId() == netPwrCtlDeviceClassId) {
// int sendPort = device->paramValue(netPwrCtlHomeDeviceSendPortParamTypeId).toInt();
// int receivePort = device->paramValue(netPwrCtlHomeDeviceReceivePortParamTypeId).toInt();
QNetworkRequest request;
request.setUrl(QUrl("http://" + device->paramValue(netPwrCtlDeviceIpAddressParamTypeId).toString() + ":" + device->paramValue(netPwrCtlDevicePortParamTypeId).toString() + "/strg.cfg"));
QString username = device->paramValue(netPwrCtlDeviceUsernameParamTypeId).toString();
QString password = device->paramValue(netPwrCtlDevicePasswordParamTypeId).toString();
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
qCDebug(dcAnelElektronik()) << "SetupDevice fetching:" << request.url() << request.rawHeader("Authorization") << username << password;
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, device, [this, device, reply](){
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcAnelElektronik()) << "Error fetching state for" << device->name() << reply->error() << reply->errorString();
device->setStateValue(netPwrCtlConnectedStateTypeId, false);
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
return;
}
device->setStateValue(netPwrCtlConnectedStateTypeId, true);
QByteArray data = reply->readAll();
QStringList parts = QString(data).split(';');
int startIndex = parts.indexOf("end") - 58;
if (startIndex < 0 || !parts.at(startIndex + 1).startsWith("NET-CONTROL")) {
qCWarning(dcAnelElektronik()) << "Bad data from panel:" << data << "Length:" << parts.length();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
return;
}
// At this point we're done with gathering information about the panel. Setup defintely succeeded for the gateway device
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
// If we haven't set up childs for this gateway yet, let's do it now
foreach (Device *child, myDevices()) {
if (child->parentId() == device->id()) {
// Already have childs for this panel. We're done here
return;
}
}
// Example reply:
// NET-PWRCTRL_04.5; // device name
// NET-CONTROL ; // hostname
// 10.10.10.132; // IP
// 255.255.255.0; // Netmask
// 10.10.10.1; // Gateway
// 00:04:A3:0B:0C:3A; // MAC
// 80; // Webcontrol port
// ; // Temp
// H; // Type
// ; // ?? (Skipped by upstream code)
// Following fields are repeated 1 times each, one for each socket
// Nr. 1; // Name 1
// 1; // Stand
// 0; // Dis
// Anfangsstatus; // Info
// ; // TK
// end;
// NET - Power Control"
// Lets add the child devices now
int childs = -1;
QString type = parts.at(startIndex + 8);
if (type == "H") {
childs = 3;
} else {
childs = 8;
}
QList<DeviceDescriptor> descriptorList;
for (int i = 0; i < childs; i++) {
QString deviceName = parts.at(startIndex + 10 + i);
DeviceDescriptor d(socketDeviceClassId, deviceName, device->name(), device->id());
d.setParams(ParamList() << Param(socketDeviceNumberParamTypeId, i));
descriptorList << d;
}
emit autoDevicesAppeared(socketDeviceClassId, descriptorList);
});
return DeviceManager::DeviceSetupStatusAsync;
if (device->deviceClassId() == netPwrCtlHomeDeviceClassId
|| device->deviceClassId() == netPwrCtlProDeviceClassId) {
return setupHomeProDevice(device);
}
if (device->deviceClassId() == netPwrCtlAdvDeviceClassId
|| device->deviceClassId() == netPwrCtlHutDeviceClassId) {
return setupAdvDevice(device);
}
if (device->deviceClassId() == socketDeviceClassId) {
@ -240,14 +291,17 @@ void DevicePluginAnel::deviceRemoved(Device *device)
DeviceManager::DeviceError DevicePluginAnel::executeAction(Device *device, const Action &action)
{
if (device->deviceClassId() == socketDeviceClassId) {
Device *parentDevice = myDevices().findById(device->parentId());
if (action.actionTypeId() == socketPowerActionTypeId) {
QUrl url("http://" + parentDevice->paramValue(netPwrCtlDeviceIpAddressParamTypeId).toString() + ":" + parentDevice->paramValue(netPwrCtlDevicePortParamTypeId).toString() + "/ctrl.htm");
Device *parentDevice = myDevices().findById(device->parentId());
QString ipAddress = parentDevice->paramValue(m_ipAddressParamTypeIdMap.value(parentDevice->deviceClassId())).toString();
int port = parentDevice->paramValue(m_portParamTypeIdMap.value(parentDevice->deviceClassId())).toInt();
QString username = parentDevice->paramValue(m_userParamTypeIdMap.value(parentDevice->deviceClassId())).toString();
QString password = parentDevice->paramValue(m_passParamTypeIdMap.value(parentDevice->deviceClassId())).toString();
QUrl url(QString("http://%1:%2/ctrl.htm").arg(ipAddress).arg(port));
QNetworkRequest request(url);
QString username = parentDevice->paramValue(netPwrCtlDeviceUsernameParamTypeId).toString();
QString password = parentDevice->paramValue(netPwrCtlDevicePasswordParamTypeId).toString();
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
QByteArray data = QString("F%1=%2").arg(device->paramValue(socketDeviceNumberParamTypeId).toString(), action.param(socketPowerActionPowerParamTypeId).value().toBool() == true ? "1" : "0").toUtf8();
@ -270,47 +324,15 @@ DeviceManager::DeviceError DevicePluginAnel::executeAction(Device *device, const
void DevicePluginAnel::refreshStates()
{
foreach (Device *device, myDevices()) {
if (device->deviceClassId() != netPwrCtlDeviceClassId) {
continue;
if (device->deviceClassId() == netPwrCtlHomeDeviceClassId
|| device->deviceClassId() == netPwrCtlProDeviceClassId) {
refreshHomePro(device);
}
if (device->deviceClassId() == netPwrCtlAdvDeviceClassId
|| device->deviceClassId() == netPwrCtlHutDeviceClassId) {
refreshAdv(device);
}
QUrl url(QUrl("http://" + device->paramValue(netPwrCtlDeviceIpAddressParamTypeId).toString() + ":" + device->paramValue(netPwrCtlDevicePortParamTypeId).toString() + "/strg.cfg"));
// qCDebug(dcAnelElektronik()) << "Fetching state from:" << url.toString();
QNetworkRequest request;
request.setUrl(url);
QString username = device->paramValue(netPwrCtlDeviceUsernameParamTypeId).toString();
QString password = device->paramValue(netPwrCtlDevicePasswordParamTypeId).toString();
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, device, [this, device, reply](){
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcAnelElektronik()) << "Error fetching state for" << device->name();
setConnectedState(device, false);
return;
}
QByteArray data = reply->readAll();
// qCDebug(dcAnelElektronik()) << "States reply:" << data;
QStringList parts = QString(data).split(';');
int startIndex = parts.indexOf("end") - 58;
if (startIndex < 0 || !parts.at(startIndex + 1).startsWith("NET-CONTROL")) {
qCWarning(dcAnelElektronik()) << "Bad data from Panel" << device->name() << data;
// This happens sometimes as the panel replies with packets we didn't request... Just ignore it...
return;
}
setConnectedState(device, true);
foreach (Device *child, myDevices()) {
if (child->parentId() == device->id()) {
int number = child->paramValue(socketDeviceNumberParamTypeId).toInt();
child->setStateValue(socketPowerStateTypeId, parts.value(startIndex + 20 + number).toInt() == 1);
}
}
});
}
}
void DevicePluginAnel::setConnectedState(Device *device, bool connected)
@ -322,3 +344,299 @@ void DevicePluginAnel::setConnectedState(Device *device, bool connected)
}
}
}
DeviceManager::DeviceSetupStatus DevicePluginAnel::setupHomeProDevice(Device *device)
{
QString ipAddress = device->paramValue(m_ipAddressParamTypeIdMap.value(device->deviceClassId())).toString();
int port = device->paramValue(m_portParamTypeIdMap.value(device->deviceClassId())).toInt();
QString username = device->paramValue(m_userParamTypeIdMap.value(device->deviceClassId())).toString();
QString password = device->paramValue(m_passParamTypeIdMap.value(device->deviceClassId())).toString();
QNetworkRequest request;
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
qCDebug(dcAnelElektronik()) << "SetupDevice fetching:" << request.url() << request.rawHeader("Authorization") << username << password;
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, device, [this, device, reply](){
StateTypeId connectedStateTypeId = m_connectedStateTypeIdMap.value(device->deviceClassId());
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcAnelElektronik()) << "Error fetching state for" << device->name() << reply->error() << reply->errorString();
device->setStateValue(connectedStateTypeId, false);
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
return;
}
device->setStateValue(connectedStateTypeId, true);
QByteArray data = reply->readAll();
QStringList parts = QString(data).split(';');
int startIndex = parts.indexOf("end") - 58;
if (startIndex < 0 || !parts.at(startIndex).startsWith("NET-PWRCTRL") || parts.length() < 60) {
qCWarning(dcAnelElektronik()) << "Bad data from panel:" << data << "Length:" << parts.length();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
return;
}
// At this point we're done with gathering information about the panel. Setup defintely succeeded for the gateway device
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
// If we haven't set up childs for this gateway yet, let's do it now
foreach (Device *child, myDevices()) {
if (child->parentId() == device->id()) {
// Already have childs for this panel. We're done here
return;
}
}
// Lets add the child devices now
int childs = -1;
QString type = parts.at(startIndex + 8);
if (type == "H") {
childs = 3;
} else {
childs = 8;
}
QList<DeviceDescriptor> descriptorList;
for (int i = 0; i < childs; i++) {
QString deviceName = parts.at(startIndex + 10 + i);
DeviceDescriptor d(socketDeviceClassId, deviceName, device->name(), device->id());
d.setParams(ParamList() << Param(socketDeviceNumberParamTypeId, i));
descriptorList << d;
}
emit autoDevicesAppeared(socketDeviceClassId, descriptorList);
});
return DeviceManager::DeviceSetupStatusAsync;
}
DeviceManager::DeviceSetupStatus DevicePluginAnel::setupAdvDevice(Device *device)
{
QString ipAddress = device->paramValue(m_ipAddressParamTypeIdMap.value(device->deviceClassId())).toString();
int port = device->paramValue(m_portParamTypeIdMap.value(device->deviceClassId())).toInt();
QString username = device->paramValue(m_userParamTypeIdMap.value(device->deviceClassId())).toString();
QString password = device->paramValue(m_passParamTypeIdMap.value(device->deviceClassId())).toString();
QNetworkRequest request;
request.setUrl(QUrl(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port)));
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username).arg(password).toUtf8().toBase64());
qCDebug(dcAnelElektronik()) << "SetupDevice fetching:" << request.url() << request.rawHeader("Authorization") << username << password;
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, device, [this, device, reply](){
StateTypeId connectedStateTypeId = m_connectedStateTypeIdMap.value(device->deviceClassId());
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcAnelElektronik()) << "Error fetching state for" << device->name() << reply->error() << reply->errorString();
device->setStateValue(connectedStateTypeId, false);
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
return;
}
device->setStateValue(connectedStateTypeId, true);
QByteArray data = reply->readAll();
QStringList parts = QString(data).split(';');
int startIndex = parts.indexOf("end") - 40;
if (startIndex < 0 || parts.length() < 58) {
qCWarning(dcAnelElektronik()) << "Bad data from panel:" << data << "Length:" << parts.length();
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
return;
}
// At this point we're done with gathering information about the panel. Setup defintely succeeded for the gateway device
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
// If we haven't set up childs for this gateway yet, let's do it now
foreach (Device *child, myDevices()) {
if (child->parentId() == device->id()) {
// Already have childs for this panel. We're done here
return;
}
}
QList<DeviceDescriptor> descriptorList;
for (int i = 0; i < 8; i++) {
QString deviceName = parts.at(startIndex + (i * 5));
DeviceDescriptor d(socketDeviceClassId, deviceName, device->name(), device->id());
d.setParams(ParamList() << Param(socketDeviceNumberParamTypeId, i));
descriptorList << d;
}
emit autoDevicesAppeared(socketDeviceClassId, descriptorList);
});
return DeviceManager::DeviceSetupStatusAsync;
}
void DevicePluginAnel::refreshHomePro(Device *device)
{
QString ipAddress = device->paramValue(m_ipAddressParamTypeIdMap.value(device->deviceClassId())).toString();
int port = device->paramValue(m_portParamTypeIdMap.value(device->deviceClassId())).toInt();
QString username = device->paramValue(m_userParamTypeIdMap.value(device->deviceClassId())).toString();
QString password = device->paramValue(m_passParamTypeIdMap.value(device->deviceClassId())).toString();
QUrl url(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port));
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, device, [this, device, reply](){
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcAnelElektronik()) << "Error fetching state for" << device->name();
setConnectedState(device, false);
return;
}
QByteArray data = reply->readAll();
// qCDebug(dcAnelElektronik()) << "States reply:" << data;
QStringList parts = QString(data).split(';');
int startIndex = parts.indexOf("end") - 58;
if (startIndex < 0 || !parts.at(startIndex).startsWith("NET-PWRCTRL")) {
qCWarning(dcAnelElektronik()) << "Bad data from Panel" << device->name() << data;
// This happens sometimes when multiple clients are talking to the panel... Just ignore it...
return;
}
setConnectedState(device, true);
// The temp sensor seems to have a bit of jitter. Reduce sample rate to avoid spamming the log
quint32 samples = device->property("tempSamples").toUInt();
if (samples % 15 == 0 && device->deviceClassId() == netPwrCtlProDeviceClassId) {
bool ok;
double tempValue = parts.at(startIndex + 7).toDouble(&ok);
if (ok) {
device->setStateValue(netPwrCtlProTemperatureStateTypeId, tempValue);
} else {
qCWarning(dcAnelElektronik()) << "Error reading temperature value from data:" << parts.at(startIndex + 7);
}
}
device->setProperty("tempSamples", ++samples);
foreach (Device *child, myDevices()) {
if (child->parentId() == device->id()) {
int number = child->paramValue(socketDeviceNumberParamTypeId).toInt();
child->setStateValue(socketPowerStateTypeId, parts.value(startIndex + 20 + number).toInt() == 1);
}
}
});
}
void DevicePluginAnel::refreshAdv(Device *device)
{
QString ipAddress = device->paramValue(m_ipAddressParamTypeIdMap.value(device->deviceClassId())).toString();
int port = device->paramValue(m_portParamTypeIdMap.value(device->deviceClassId())).toInt();
QString username = device->paramValue(m_userParamTypeIdMap.value(device->deviceClassId())).toString();
QString password = device->paramValue(m_passParamTypeIdMap.value(device->deviceClassId())).toString();
QUrl url(QString("http://%1:%2/strg.cfg").arg(ipAddress).arg(port));
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, device, [this, device, reply](){
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcAnelElektronik()) << "Error fetching state for" << device->name();
setConnectedState(device, false);
return;
}
QByteArray data = reply->readAll();
// qCDebug(dcAnelElektronik()) << "States reply:" << data;
QStringList parts = QString(data).split(';');
int startIndex = parts.indexOf("end") - 40;
if (startIndex < 0 || parts.count() < 58) {
qCWarning(dcAnelElektronik()) << "Bad data from Panel" << device->name() << data << "Length:" << parts.length();
// This happens sometimes when multiple clients are talking to the panel... Just ignore it...
return;
}
setConnectedState(device, true);
foreach (Device *child, myDevices()) {
if (child->parentId() == device->id()) {
int number = child->paramValue(socketDeviceNumberParamTypeId).toInt();
child->setStateValue(socketPowerStateTypeId, parts.value(startIndex + (number * 5) + 1).toInt() == 1);
}
}
// The temp sensor seems to have a bit of jitter. Reduce sample rate to avoid spamming the log
quint32 samples = device->property("tempSamples").toUInt();
if (samples % 15 == 0) {
refreshAdvTemp(device);
}
device->setProperty("tempSamples", ++samples);
});
}
void DevicePluginAnel::refreshAdvTemp(Device *device)
{
QString ipAddress = device->paramValue(m_ipAddressParamTypeIdMap.value(device->deviceClassId())).toString();
int port = device->paramValue(m_portParamTypeIdMap.value(device->deviceClassId())).toInt();
QString username = device->paramValue(m_userParamTypeIdMap.value(device->deviceClassId())).toString();
QString password = device->paramValue(m_passParamTypeIdMap.value(device->deviceClassId())).toString();
QUrl url(QString("http://%1:%2/daten.cfg").arg(ipAddress).arg(port));
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("Authorization", "Basic " + QString("%1:%2").arg(username, password).toUtf8().toBase64());
QNetworkReply *reply = hardwareManager()->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, device, [this, device, reply](){
if (reply->error() != QNetworkReply::NoError) {
qCWarning(dcAnelElektronik()) << "Error fetching temp for" << device->name();
setConnectedState(device, false);
return;
}
QByteArray data = reply->readAll();
qCDebug(dcAnelElektronik()) << "Temp reply:" << data;
QStringList parts = QString(data).split(';');
int startIndex = parts.indexOf("end") - 10;
if (startIndex < 0) {
qCWarning(dcAnelElektronik()) << "Bad data from Panel" << device->name() << data << "Length:" << parts.length();
// This happens sometimes when multiple clients are talking to the panel... Just ignore it...
return;
}
if (device->deviceClassId() == netPwrCtlAdvDeviceClassId) {
bool ok;
double temp = parts.at(7).toDouble(&ok);
if (ok) {
device->setStateValue(netPwrCtlAdvTemperatureStateTypeId, temp);
} else {
qCWarning(dcAnelElektronik()) << "Error fetching temperature value:" << data;
}
} else { // HUT
if (parts.length() < 18) {
qCWarning(dcAnelElektronik()) << "Data too short for HUT device" << data;
return;
}
bool ok;
double temp = parts.at(13).toDouble(&ok);
if (ok) {
device->setStateValue(netPwrCtlHutTemperatureStateTypeId, temp);
} else {
qCWarning(dcAnelElektronik()) << "Error fetching temperature value:" << data;
}
double humidity = parts.at(14).toDouble(&ok);
if (ok) {
device->setStateValue(netPwrCtlHutHumidityStateTypeId, humidity);
} else {
qCWarning(dcAnelElektronik()) << "Error fetching humidity value:" << data;
}
int lux = parts.at(15).toInt(&ok);
if (ok) {
device->setStateValue(netPwrCtlHutLightIntensityStateTypeId, lux);
} else {
qCWarning(dcAnelElektronik()) << "Error fetching light intensity value:" << data;
}
}
});
}

View File

@ -53,10 +53,21 @@ private slots:
private:
void setConnectedState(Device *device, bool connected);
DeviceManager::DeviceSetupStatus setupHomeProDevice(Device *device);
DeviceManager::DeviceSetupStatus setupAdvDevice(Device *device);
void refreshHomePro(Device *device);
void refreshAdv(Device *device);
void refreshAdvTemp(Device *device);
private:
PluginTimer *m_pollTimer = nullptr;
QHash<DeviceClassId, StateTypeId> m_connectedStateTypeIdMap;
QHash<DeviceClassId, ParamTypeId> m_ipAddressParamTypeIdMap;
QHash<DeviceClassId, ParamTypeId> m_portParamTypeIdMap;
QHash<DeviceClassId, ParamTypeId> m_userParamTypeIdMap;
QHash<DeviceClassId, ParamTypeId> m_passParamTypeIdMap;
};
#endif // DEVICEPLUGINANEL_H

View File

@ -10,8 +10,8 @@
"deviceClasses": [
{
"id": "d70433ac-9738-49ca-932f-6d3e20bcc6d4",
"name": "netPwrCtl",
"displayName": "NET-PwrCtl",
"name": "netPwrCtlHome",
"displayName": "NET-PwrCtl HOME",
"createMethods": ["user", "discovery"],
"interfaces": [ "gateway" ],
"paramTypes": [
@ -53,6 +53,188 @@
}
]
},
{
"id": "1492f911-1c09-42ce-b920-084548a689ea",
"name": "netPwrCtlPro",
"displayName": "NET-PwrCtl PRO",
"createMethods": ["user", "discovery"],
"interfaces": [ "gateway", "temperaturesensor" ],
"paramTypes": [
{
"id": "b1cf9a4f-9c2a-4ab4-a920-46f0b8a8b988",
"name":"ipAddress",
"displayName": "IP address",
"type": "QString"
},
{
"id": "31540acc-949f-454f-9987-982e97ce7d21",
"name": "port",
"displayName": "Web control Port",
"type": "int",
"defaultValue": 80
},
{
"id": "f9cae7eb-a534-404f-b041-6e5a6720494e",
"name": "username",
"displayName": "Username",
"type": "QString"
},
{
"id": "dac97153-074a-481a-8057-1936bfb63b6e",
"name": "password",
"displayName": "Password",
"type": "QString"
}
],
"stateTypes": [
{
"id": "820c54bd-0d4f-4e13-8160-a8efa77c9db5",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "2973ec1e-9c26-45ad-a97b-dd5eccbf650a",
"name": "temperature",
"displayName": "Temperature",
"displayNameEvent": "Temperature changed",
"type": "double",
"defaultValue": 0,
"unit": "DegreeCelsius"
}
]
},
{
"id": "99987919-d32d-4d8f-938c-bcf9683003b6",
"name": "netPwrCtlAdv",
"displayName": "NET-PwrCtl ADV",
"createMethods": ["user", "discovery"],
"interfaces": [ "gateway", "temperaturesensor" ],
"paramTypes": [
{
"id": "5d98ead0-e445-492c-821c-ae169af648e4",
"name":"ipAddress",
"displayName": "IP address",
"type": "QString"
},
{
"id": "1913912f-2579-4e8a-9e23-af1de4a2ef72",
"name": "port",
"displayName": "Web control Port",
"type": "int",
"defaultValue": 80
},
{
"id": "0eeaa6f0-7232-4d6e-8637-6e21f58a2018",
"name": "username",
"displayName": "Username",
"type": "QString"
},
{
"id": "14a8c3bd-27a6-440c-a2ba-139fabc870a1",
"name": "password",
"displayName": "Password",
"type": "QString"
}
],
"stateTypes": [
{
"id": "d143b775-e004-4119-a317-6c508686d473",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "aed7464a-6c36-4858-adb7-776d97c5498e",
"name": "temperature",
"displayName": "Temperature",
"displayNameEvent": "Temperature changed",
"type": "double",
"defaultValue": 0,
"unit": "DegreeCelsius"
}
]
},
{
"id": "bc9a90e0-b320-46f1-8d7b-2d24f40af5ea",
"name": "netPwrCtlHut",
"displayName": "NET-PwrCtl HUT",
"createMethods": ["user", "discovery"],
"interfaces": [ "gateway", "temperaturesensor", "humiditysensor", "lightsensor" ],
"paramTypes": [
{
"id": "fb34919c-3ca0-47b3-a14a-7986b5ce24e2",
"name":"ipAddress",
"displayName": "IP address",
"type": "QString"
},
{
"id": "35010dff-dde9-4acf-a60b-cf92b7edc2a5",
"name": "port",
"displayName": "Web control Port",
"type": "int",
"defaultValue": 80
},
{
"id": "3bf3db56-4fe4-4c87-a5cd-7c1f1acb6408",
"name": "username",
"displayName": "Username",
"type": "QString"
},
{
"id": "d5f315b9-99ff-4e69-95c8-97cb81d1e8d7",
"name": "password",
"displayName": "Password",
"type": "QString"
}
],
"stateTypes": [
{
"id": "3b30c586-4756-4903-8405-b00bc9d34685",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "7689239c-e6c3-48cc-ae90-bd1cad44b631",
"name": "temperature",
"displayName": "Temperature",
"displayNameEvent": "Temperature changed",
"type": "double",
"defaultValue": 0,
"unit": "DegreeCelsius"
},
{
"id": "6e38c9f7-cdd7-4909-9312-2047812d1883",
"name": "humidity",
"displayName": "Humidity",
"displayNameEvent": "Humidity changed",
"type": "double",
"defaultValue": 0,
"minValue": 0,
"maxValue": 100,
"unit": "Percentage"
},
{
"id": "60792bc4-fc67-47f6-8c3f-45717a072d59",
"name": "lightIntensity",
"displayName": "Light intensity",
"displayNameEvent": "Light intensity changed",
"type": "double",
"defaultValue": 0,
"unit": "Lux"
}
]
},
{
"id": "9d8da004-a8a1-457f-a8ee-b86133828a49",
"name": "socket",