properly handle all types of panels: HOME, PRO, ADV and HUT
This commit is contained in:
parent
2adbb4c8df
commit
1345fe99ff
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user