SMA: Update to networkdevice interface
This commit is contained in:
parent
36f9f3c512
commit
f3b51cae4d
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -64,28 +64,39 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info)
|
||||
webBoxDiscovery->deleteLater();
|
||||
ThingDescriptors descriptors;
|
||||
foreach (const NetworkDeviceInfo &networkDeviceInfo, webBoxDiscovery->discoveryResults()) {
|
||||
QString title = "SMA Sunny WebBox (" + networkDeviceInfo.address().toString() + ")";
|
||||
QString title = "SMA Sunny WebBox";
|
||||
QString description;
|
||||
if (networkDeviceInfo.macAddressManufacturer().isEmpty()) {
|
||||
description = networkDeviceInfo.macAddress();
|
||||
} else {
|
||||
description = networkDeviceInfo.macAddress() + " (" + networkDeviceInfo.macAddressManufacturer() + ")";
|
||||
MacAddressInfo macInfo;
|
||||
switch (networkDeviceInfo.monitorMode()) {
|
||||
case NetworkDeviceInfo::MonitorModeMac:
|
||||
macInfo = networkDeviceInfo.macAddressInfos().constFirst();
|
||||
description = networkDeviceInfo.address().toString();
|
||||
if (!macInfo.vendorName().isEmpty())
|
||||
description += " - " + networkDeviceInfo.macAddressInfos().constFirst().vendorName();
|
||||
break;
|
||||
case NetworkDeviceInfo::MonitorModeHostName:
|
||||
description = networkDeviceInfo.address().toString();
|
||||
break;
|
||||
case NetworkDeviceInfo::MonitorModeIp:
|
||||
description = "Interface: " + networkDeviceInfo.networkInterface().name();
|
||||
break;
|
||||
}
|
||||
|
||||
ThingDescriptor descriptor(sunnyWebBoxThingClassId, title, description);
|
||||
|
||||
// Check for reconfiguration
|
||||
foreach (Thing *existingThing, myThings()) {
|
||||
if (existingThing->paramValue(sunnyWebBoxThingMacAddressParamTypeId).toString() == networkDeviceInfo.macAddress()) {
|
||||
descriptor.setThingId(existingThing->id());
|
||||
break;
|
||||
}
|
||||
ParamList params;
|
||||
params << Param(sunnyWebBoxThingAddressParamTypeId, networkDeviceInfo.thingParamValueAddress());
|
||||
params << Param(sunnyWebBoxThingHostNameParamTypeId, networkDeviceInfo.thingParamValueHostName());
|
||||
params << Param(sunnyWebBoxThingMacAddressParamTypeId, networkDeviceInfo.thingParamValueMacAddress());
|
||||
descriptor.setParams(params);
|
||||
|
||||
// Check if we already have set up this device
|
||||
Thing *existingThing = myThings().findByParams(params);
|
||||
if (existingThing) {
|
||||
qCDebug(dcSma()) << "This thing already exists in the system:" << networkDeviceInfo;
|
||||
descriptor.setThingId(existingThing->id());
|
||||
}
|
||||
|
||||
ParamList params;
|
||||
params << Param(sunnyWebBoxThingHostParamTypeId, networkDeviceInfo.address().toString());
|
||||
params << Param(sunnyWebBoxThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
|
||||
descriptor.setParams(params);
|
||||
descriptors.append(descriptor);
|
||||
}
|
||||
info->addThingDescriptors(descriptors);
|
||||
@ -163,8 +174,6 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info)
|
||||
connect(speedwireDiscovery, &SpeedwireDiscovery::discoveryFinished, this, [=](){
|
||||
qCDebug(dcSma()) << "Speed wire discovery finished.";
|
||||
speedwireDiscovery->deleteLater();
|
||||
|
||||
ThingDescriptors descriptors;
|
||||
foreach (const SpeedwireDiscovery::SpeedwireDiscoveryResult &result, speedwireDiscovery->discoveryResult()) {
|
||||
|
||||
if (result.deviceType != Speedwire::DeviceTypeInverter)
|
||||
@ -188,15 +197,16 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info)
|
||||
}
|
||||
|
||||
ParamList params;
|
||||
params << Param(speedwireInverterThingHostParamTypeId, result.address.toString());
|
||||
params << Param(speedwireInverterThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress());
|
||||
params << Param(speedwireInverterThingMacAddressParamTypeId, result.networkDeviceInfo.thingParamValueMacAddress());
|
||||
params << Param(speedwireInverterThingHostNameParamTypeId, result.networkDeviceInfo.thingParamValueHostName());
|
||||
params << Param(speedwireInverterThingAddressParamTypeId, result.networkDeviceInfo.thingParamValueAddress());
|
||||
params << Param(speedwireInverterThingSerialNumberParamTypeId, result.serialNumber);
|
||||
params << Param(speedwireInverterThingModelIdParamTypeId, result.modelId);
|
||||
descriptor.setParams(params);
|
||||
descriptors.append(descriptor);
|
||||
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
|
||||
info->addThingDescriptors(descriptors);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
@ -225,7 +235,9 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info)
|
||||
}
|
||||
|
||||
ParamList params;
|
||||
params << Param(modbusSolarInverterThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress());
|
||||
params << Param(modbusSolarInverterThingMacAddressParamTypeId, result.networkDeviceInfo.thingParamValueMacAddress());
|
||||
params << Param(modbusSolarInverterThingHostNameParamTypeId, result.networkDeviceInfo.thingParamValueHostName());
|
||||
params << Param(modbusSolarInverterThingAddressParamTypeId, result.networkDeviceInfo.thingParamValueAddress());
|
||||
params << Param(modbusSolarInverterThingPortParamTypeId, result.port);
|
||||
params << Param(modbusSolarInverterThingSlaveIdParamTypeId, result.modbusAddress);
|
||||
params << Param(modbusSolarInverterThingSerialNumberParamTypeId, result.serialNumber);
|
||||
@ -259,7 +271,9 @@ void IntegrationPluginSma::discoverThings(ThingDiscoveryInfo *info)
|
||||
}
|
||||
|
||||
ParamList params;
|
||||
params << Param(modbusBatteryInverterThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress());
|
||||
params << Param(modbusBatteryInverterThingMacAddressParamTypeId, result.networkDeviceInfo.thingParamValueMacAddress());
|
||||
params << Param(modbusBatteryInverterThingAddressParamTypeId, result.networkDeviceInfo.thingParamValueAddress());
|
||||
params << Param(modbusBatteryInverterThingHostNameParamTypeId, result.networkDeviceInfo.thingParamValueHostName());
|
||||
params << Param(modbusBatteryInverterThingPortParamTypeId, result.port);
|
||||
params << Param(modbusBatteryInverterThingSlaveIdParamTypeId, result.modbusAddress);
|
||||
params << Param(modbusBatteryInverterThingSerialNumberParamTypeId, result.serialNumber);
|
||||
@ -305,25 +319,42 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info)
|
||||
qCDebug(dcSma()) << "Setup thing" << thing << thing->params();
|
||||
|
||||
if (thing->thingClassId() == sunnyWebBoxThingClassId) {
|
||||
// Check if a Sunny WebBox is already added with this mac address
|
||||
foreach (SunnyWebBox *sunnyWebBox, m_sunnyWebBoxes.values()) {
|
||||
if (sunnyWebBox->macAddress() == thing->paramValue(sunnyWebBoxThingMacAddressParamTypeId).toString()){
|
||||
qCWarning(dcSma()) << "Thing with mac address" << thing->paramValue(sunnyWebBoxThingMacAddressParamTypeId).toString() << " already added!";
|
||||
info->finish(Thing::ThingErrorThingInUse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_sunnyWebBoxes.contains(thing)) {
|
||||
qCDebug(dcSma()) << "Setup after reconfiguration, cleaning up...";
|
||||
m_sunnyWebBoxes.take(thing)->deleteLater();
|
||||
|
||||
if (m_monitors.contains(thing)) {
|
||||
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
|
||||
}
|
||||
}
|
||||
|
||||
SunnyWebBox *sunnyWebBox = new SunnyWebBox(hardwareManager()->networkManager(), QHostAddress(thing->paramValue(sunnyWebBoxThingHostParamTypeId).toString()), this);
|
||||
sunnyWebBox->setMacAddress(thing->paramValue(sunnyWebBoxThingMacAddressParamTypeId).toString());
|
||||
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
|
||||
if (!monitor) {
|
||||
qCWarning(dcSma()) << "Unable to register monitor with the given params" << thing << thing->params();
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Unable to set up the connection with this configuration, please reconfigure the connection."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_monitors.insert(thing, monitor);
|
||||
|
||||
// Make sure the monitor gets cleaned up when setup gets aborted
|
||||
connect(info, &ThingSetupInfo::aborted, monitor, [this, thing](){
|
||||
if (m_monitors.contains(thing)) {
|
||||
qCDebug(dcSma()) << "Unregistering monitor because setup has been aborted.";
|
||||
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
|
||||
}
|
||||
});
|
||||
|
||||
SunnyWebBox *sunnyWebBox = new SunnyWebBox(hardwareManager()->networkManager(), monitor->networkDeviceInfo().address(), this);
|
||||
connect(info, &ThingSetupInfo::aborted, sunnyWebBox, &SunnyWebBox::deleteLater);
|
||||
connect(sunnyWebBox, &SunnyWebBox::destroyed, this, [thing, this] { m_sunnyWebBoxes.remove(thing);});
|
||||
connect(monitor, &NetworkDeviceMonitor::reachableChanged, this, [sunnyWebBox, monitor](bool reachable){
|
||||
qCDebug(dcSma()) << "SunnyWebBox: monitor reachable changed" << monitor;
|
||||
if (reachable) {
|
||||
sunnyWebBox->setHostAddress(monitor->networkDeviceInfo().address());
|
||||
}
|
||||
});
|
||||
|
||||
QString requestId = sunnyWebBox->getPlantOverview();
|
||||
connect(sunnyWebBox, &SunnyWebBox::plantOverviewReceived, info, [=] (const QString &messageId, SunnyWebBox::Overview overview) {
|
||||
@ -388,18 +419,36 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info)
|
||||
|
||||
} else if (thing->thingClassId() == speedwireInverterThingClassId) {
|
||||
|
||||
QHostAddress address = QHostAddress(thing->paramValue(speedwireInverterThingHostParamTypeId).toString());
|
||||
if (m_speedwireInverters.contains(thing)) {
|
||||
qCDebug(dcSma()) << "Reconfiguring existing thing" << thing->name();
|
||||
m_speedwireInverters.take(thing)->deleteLater();
|
||||
|
||||
// FIXME: use the monitor here since the IP might change
|
||||
if (m_monitors.contains(thing)) {
|
||||
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
|
||||
}
|
||||
}
|
||||
|
||||
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
|
||||
if (!monitor) {
|
||||
qCWarning(dcSma()) << "Unable to register monitor with the given params" << thing << thing->params();
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Unable to set up the connection with this configuration, please reconfigure the connection."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_monitors.insert(thing, monitor);
|
||||
|
||||
// Make sure the monitor gets cleaned up when setup gets aborted
|
||||
connect(info, &ThingSetupInfo::aborted, monitor, [this, thing](){
|
||||
if (m_monitors.contains(thing)) {
|
||||
qCDebug(dcSma()) << "Unregistering monitor because setup has been aborted.";
|
||||
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
|
||||
}
|
||||
});
|
||||
|
||||
quint32 serialNumber = static_cast<quint32>(thing->paramValue(speedwireInverterThingSerialNumberParamTypeId).toUInt());
|
||||
quint16 modelId = static_cast<quint16>(thing->paramValue(speedwireInverterThingModelIdParamTypeId).toUInt());
|
||||
|
||||
if (m_speedwireInverters.contains(thing)) {
|
||||
m_speedwireInverters.take(thing)->deleteLater();
|
||||
}
|
||||
|
||||
SpeedwireInverter *inverter = new SpeedwireInverter(getSpeedwireInterface(), address, modelId, serialNumber, this);
|
||||
SpeedwireInverter *inverter = new SpeedwireInverter(getSpeedwireInterface(), monitor, modelId, serialNumber, this);
|
||||
qCDebug(dcSma()) << "Inverter: Interface initialized successfully.";
|
||||
|
||||
QString password;
|
||||
@ -519,15 +568,14 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
MacAddress macAddress = MacAddress(thing->paramValue(modbusSolarInverterThingMacAddressParamTypeId).toString());
|
||||
if (!macAddress.isValid()) {
|
||||
qCWarning(dcSma()) << "The configured mac address is not valid" << thing->params();
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The MAC address is not known. Please reconfigure the thing."));
|
||||
// Create the monitor
|
||||
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
|
||||
if (!monitor) {
|
||||
qCWarning(dcSma()) << "Unable to register monitor with the given params" << thing << thing->params();
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Unable to set up the connection with this configuration, please reconfigure the connection."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the monitor
|
||||
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(macAddress);
|
||||
m_monitors.insert(thing, monitor);
|
||||
|
||||
QHostAddress address = monitor->networkDeviceInfo().address();
|
||||
@ -571,15 +619,14 @@ void IntegrationPluginSma::setupThing(ThingSetupInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
MacAddress macAddress = MacAddress(thing->paramValue(modbusBatteryInverterThingMacAddressParamTypeId).toString());
|
||||
if (!macAddress.isValid()) {
|
||||
qCWarning(dcSma()) << "The configured mac address is not valid" << thing->params();
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The MAC address is not known. Please reconfigure the thing."));
|
||||
// Create the monitor
|
||||
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
|
||||
if (!monitor) {
|
||||
qCWarning(dcSma()) << "Unable to register monitor with the given params" << thing << thing->params();
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Unable to set up the connection with this configuration, please reconfigure the connection."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the monitor
|
||||
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(macAddress);
|
||||
m_monitors.insert(thing, monitor);
|
||||
|
||||
QHostAddress address = monitor->networkDeviceInfo().address();
|
||||
|
||||
@ -13,15 +13,23 @@
|
||||
"name": "sunnyWebBox",
|
||||
"displayName": "SMA Sunny WebBox",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"interfaces": ["solarinverter"],
|
||||
"interfaces": ["solarinverter", "connectable", "networkdevice"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "864d4162-e3ce-48b8-b8ac-c1b971b52d42",
|
||||
"name": "host",
|
||||
"name": "address",
|
||||
"displayName": "Host address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": "192.168.0.168"
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "19e1f60a-f7c3-4e40-b971-7cae25db1def",
|
||||
"name": "hostName",
|
||||
"displayName": "Host name",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "03f32361-4e13-4597-a346-af8d16a986b3",
|
||||
@ -30,7 +38,7 @@
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"readOnly": true,
|
||||
"defaultValue": "00:00:00:00:00:00"
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
@ -286,15 +294,23 @@
|
||||
"displayName": "SMA Inverter",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"setupMethod": "EnterPin",
|
||||
"interfaces": [ "solarinverter", "connectable"],
|
||||
"interfaces": [ "solarinverter", "connectable", "networkdevice"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "c8098d53-69eb-4d0b-9f07-e43c4a0ea9a9",
|
||||
"name": "host",
|
||||
"name": "address",
|
||||
"displayName": "Host address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": "192.168.0.168"
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "d72e1831-04f2-4bd6-a86d-d767e92868ef",
|
||||
"name": "hostName",
|
||||
"displayName": "Host name",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "7df0ab60-0f11-4495-8e0d-508ba2b6d858",
|
||||
@ -537,8 +553,24 @@
|
||||
"name": "modbusSolarInverter",
|
||||
"displayName": "SMA Solar Inverter (Modbus)",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"interfaces": [ "solarinverter" ],
|
||||
"interfaces": [ "solarinverter", "connectable", "networkdevice" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "07720ebe-2e4b-4d8e-a0c0-88ad21879375",
|
||||
"name": "address",
|
||||
"displayName": "Host address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "e5e420c7-eb99-45c4-bb44-06218ebec8a2",
|
||||
"name": "hostName",
|
||||
"displayName": "Host name",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "3cea46a0-9535-4612-9971-19167109e63c",
|
||||
"name":"macAddress",
|
||||
@ -699,8 +731,24 @@
|
||||
"name": "modbusBatteryInverter",
|
||||
"displayName": "SMA Battery Inverter (Modbus)",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"interfaces": [ "energystorage", "connectable" ],
|
||||
"interfaces": [ "energystorage", "connectable", "networkdevice" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "75d5d4ec-6f0c-44e8-bc30-a533f4a1001a",
|
||||
"name": "address",
|
||||
"displayName": "Host address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "8a8a17aa-5e10-4232-bab6-77cc386d59e6",
|
||||
"name": "hostName",
|
||||
"displayName": "Host name",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "03a5a009-0edc-4370-924a-785e7fcee30a",
|
||||
"name":"macAddress",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -45,20 +45,20 @@ SmaModbusBatteryInverterDiscovery::SmaModbusBatteryInverterDiscovery(NetworkDevi
|
||||
qCDebug(dcSma()) << "Discovery: Grace period timer triggered.";
|
||||
finishDiscovery();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void SmaModbusBatteryInverterDiscovery::startDiscovery()
|
||||
{
|
||||
qCInfo(dcSma()) << "Discovery: Searching for SMA battery inverters in the network...";
|
||||
NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();
|
||||
m_startDateTime = QDateTime::currentDateTime();
|
||||
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &SmaModbusBatteryInverterDiscovery::checkNetworkDevice);
|
||||
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &SmaModbusBatteryInverterDiscovery::checkNetworkDevice);
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
|
||||
qCDebug(dcSma()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices";
|
||||
m_networkDeviceInfos = discoveryReply->networkDeviceInfos();
|
||||
m_gracePeriodTimer.start();
|
||||
discoveryReply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
@ -67,11 +67,11 @@ QList<SmaModbusBatteryInverterDiscovery::Result> SmaModbusBatteryInverterDiscove
|
||||
return m_discoveryResults;
|
||||
}
|
||||
|
||||
void SmaModbusBatteryInverterDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo)
|
||||
void SmaModbusBatteryInverterDiscovery::checkNetworkDevice(const QHostAddress &address)
|
||||
{
|
||||
qCInfo(dcSma()) << "Checking network device:" << networkDeviceInfo << "Port:" << m_port << "Slave ID:" << m_modbusAddress;
|
||||
qCInfo(dcSma()) << "Checking network device:" << address << "Port:" << m_port << "Slave ID:" << m_modbusAddress;
|
||||
|
||||
SmaBatteryInverterModbusTcpConnection *connection = new SmaBatteryInverterModbusTcpConnection(networkDeviceInfo.address(), m_port, m_modbusAddress, this);
|
||||
SmaBatteryInverterModbusTcpConnection *connection = new SmaBatteryInverterModbusTcpConnection(address, m_port, m_modbusAddress, this);
|
||||
m_connections.append(connection);
|
||||
|
||||
connect(connection, &SmaBatteryInverterModbusTcpConnection::reachableChanged, this, [=](bool reachable){
|
||||
@ -82,13 +82,13 @@ void SmaModbusBatteryInverterDiscovery::checkNetworkDevice(const NetworkDeviceIn
|
||||
|
||||
connect(connection, &SmaBatteryInverterModbusTcpConnection::initializationFinished, this, [=](bool success){
|
||||
if (!success) {
|
||||
qCInfo(dcSma()) << "Discovery: Initialization failed on" << networkDeviceInfo.address().toString() << "Skipping result...";;
|
||||
qCInfo(dcSma()) << "Discovery: Initialization failed on" << address.toString() << "Skipping result...";;
|
||||
cleanupConnection(connection);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->deviceClass() != Sma::DeviceClassBatteryInverter) {
|
||||
qCInfo(dcSma()) << "Discovery: Initialization successful for" << networkDeviceInfo.address().toString() << "but the device class is not a battery inverter. Skipping result...";;
|
||||
qCInfo(dcSma()) << "Discovery: Initialization successful for" << address.toString() << "but the device class is not a battery inverter. Skipping result...";;
|
||||
cleanupConnection(connection);
|
||||
return;
|
||||
}
|
||||
@ -99,7 +99,7 @@ void SmaModbusBatteryInverterDiscovery::checkNetworkDevice(const NetworkDeviceIn
|
||||
result.port = m_port;
|
||||
result.modbusAddress = m_modbusAddress;
|
||||
result.softwareVersion = Sma::buildSoftwareVersionString(connection->softwarePackage());
|
||||
result.networkDeviceInfo = networkDeviceInfo;
|
||||
result.address = address;
|
||||
m_discoveryResults.append(result);
|
||||
|
||||
qCInfo(dcSma()) << "Discovery: --> Found";
|
||||
@ -112,18 +112,17 @@ void SmaModbusBatteryInverterDiscovery::checkNetworkDevice(const NetworkDeviceIn
|
||||
});
|
||||
|
||||
if (!connection->initialize()) {
|
||||
qCDebug(dcSma()) << "Discovery: Unable to initialize connection on" << networkDeviceInfo.address().toString();
|
||||
qCDebug(dcSma()) << "Discovery: Unable to initialize connection on" << address.toString();
|
||||
cleanupConnection(connection);
|
||||
}
|
||||
});
|
||||
|
||||
connect(connection, &SmaBatteryInverterModbusTcpConnection::checkReachabilityFailed, this, [=](){
|
||||
qCDebug(dcSma()) << "Discovery: Checking reachability failed on" << networkDeviceInfo.address().toString();
|
||||
qCDebug(dcSma()) << "Discovery: Checking reachability failed on" << address.toString();
|
||||
cleanupConnection(connection);
|
||||
});
|
||||
|
||||
connection->connectDevice();
|
||||
|
||||
}
|
||||
|
||||
void SmaModbusBatteryInverterDiscovery::cleanupConnection(SmaBatteryInverterModbusTcpConnection *connection)
|
||||
@ -137,12 +136,16 @@ void SmaModbusBatteryInverterDiscovery::finishDiscovery()
|
||||
{
|
||||
qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch();
|
||||
|
||||
// Fill in all network device infos we have
|
||||
for (int i = 0; i < m_discoveryResults.count(); i++)
|
||||
m_discoveryResults[i].networkDeviceInfo = m_networkDeviceInfos.get(m_discoveryResults.at(i).address);
|
||||
|
||||
// Cleanup any leftovers...we don't care any more
|
||||
foreach (SmaBatteryInverterModbusTcpConnection *connection, m_connections)
|
||||
cleanupConnection(connection);
|
||||
|
||||
qCInfo(dcSma()) << "Discovery: Finished the discovery process. Found" << m_discoveryResults.count()
|
||||
<< "SMA battery inverters in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
|
||||
<< "SMA battery inverters in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
|
||||
m_gracePeriodTimer.stop();
|
||||
|
||||
emit discoveryFinished();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -49,6 +49,7 @@ public:
|
||||
int port;
|
||||
int modbusAddress;
|
||||
QString softwareVersion;
|
||||
QHostAddress address;
|
||||
NetworkDeviceInfo networkDeviceInfo;
|
||||
};
|
||||
|
||||
@ -67,11 +68,11 @@ private:
|
||||
QTimer m_gracePeriodTimer;
|
||||
QDateTime m_startDateTime;
|
||||
|
||||
NetworkDeviceInfos m_networkDeviceInfos;
|
||||
QList<SmaBatteryInverterModbusTcpConnection *> m_connections;
|
||||
|
||||
QList<Result> m_discoveryResults;
|
||||
|
||||
void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo);
|
||||
void checkNetworkDevice(const QHostAddress &address);
|
||||
void cleanupConnection(SmaBatteryInverterModbusTcpConnection *connection);
|
||||
|
||||
void finishDiscovery();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2022, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -36,9 +36,9 @@
|
||||
|
||||
SmaModbusSolarInverterDiscovery::SmaModbusSolarInverterDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port, quint16 modbusAddress,QObject *parent)
|
||||
: QObject{parent},
|
||||
m_networkDeviceDiscovery{networkDeviceDiscovery},
|
||||
m_port{port},
|
||||
m_modbusAddress{modbusAddress}
|
||||
m_networkDeviceDiscovery{networkDeviceDiscovery},
|
||||
m_port{port},
|
||||
m_modbusAddress{modbusAddress}
|
||||
{
|
||||
|
||||
}
|
||||
@ -47,21 +47,14 @@ void SmaModbusSolarInverterDiscovery::startDiscovery()
|
||||
{
|
||||
qCInfo(dcSma()) << "Discovery: Start searching for SMA modbus inverters in the network...";
|
||||
NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();
|
||||
m_startDateTime = QDateTime::currentDateTime();
|
||||
|
||||
// Imedialty check any new device gets discovered
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &SmaModbusSolarInverterDiscovery::checkNetworkDevice);
|
||||
|
||||
// Check what might be left on finished
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &SmaModbusSolarInverterDiscovery::checkNetworkDevice);
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [this, discoveryReply](){
|
||||
qCDebug(dcSma()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices";
|
||||
|
||||
// Send a report request to nework device info not sent already...
|
||||
foreach (const NetworkDeviceInfo &networkDeviceInfo, discoveryReply->networkDeviceInfos()) {
|
||||
if (!m_verifiedNetworkDeviceInfos.contains(networkDeviceInfo)) {
|
||||
checkNetworkDevice(networkDeviceInfo);
|
||||
}
|
||||
}
|
||||
m_networkDeviceInfos = discoveryReply->networkDeviceInfos();
|
||||
|
||||
// Give the last connections added right before the network discovery finished a chance to check the device...
|
||||
QTimer::singleShot(3000, this, [this](){
|
||||
@ -76,19 +69,10 @@ QList<SmaModbusSolarInverterDiscovery::SmaModbusDiscoveryResult> SmaModbusSolarI
|
||||
return m_discoveryResults;
|
||||
}
|
||||
|
||||
void SmaModbusSolarInverterDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo)
|
||||
void SmaModbusSolarInverterDiscovery::checkNetworkDevice(const QHostAddress &address)
|
||||
{
|
||||
// Create a kostal connection and try to initialize it.
|
||||
// Only if initialized successfully and all information have been fetched correctly from
|
||||
// the device we can assume this is what we are locking for (ip, port, modbus address, correct registers).
|
||||
// We cloud tough also filter the result only for certain software versions, manufactueres or whatever...
|
||||
|
||||
if (m_verifiedNetworkDeviceInfos.contains(networkDeviceInfo))
|
||||
return;
|
||||
|
||||
SmaSolarInverterModbusTcpConnection *connection = new SmaSolarInverterModbusTcpConnection(networkDeviceInfo.address(), m_port, m_modbusAddress, this);
|
||||
SmaSolarInverterModbusTcpConnection *connection = new SmaSolarInverterModbusTcpConnection(address, m_port, m_modbusAddress, this);
|
||||
m_connections.append(connection);
|
||||
m_verifiedNetworkDeviceInfos.append(networkDeviceInfo);
|
||||
|
||||
connect(connection, &SmaSolarInverterModbusTcpConnection::reachableChanged, this, [=](bool reachable){
|
||||
if (!reachable) {
|
||||
@ -100,13 +84,13 @@ void SmaModbusSolarInverterDiscovery::checkNetworkDevice(const NetworkDeviceInfo
|
||||
// Modbus TCP connected...ok, let's try to initialize it!
|
||||
connect(connection, &SmaSolarInverterModbusTcpConnection::initializationFinished, this, [=](bool success){
|
||||
if (!success) {
|
||||
qCDebug(dcSma()) << "Discovery: Initialization failed on" << networkDeviceInfo.address().toString() << "Continue...";;
|
||||
qCDebug(dcSma()) << "Discovery: Initialization failed on" << address.toString() << "Continue...";;
|
||||
cleanupConnection(connection);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->deviceClass() != Sma::DeviceClassSolarInverter) {
|
||||
qCDebug(dcSma()) << "Discovery: Initialization successfull for" << networkDeviceInfo.address().toString() << "but the device class is not an inverter. Continue...";;
|
||||
qCDebug(dcSma()) << "Discovery: Initialization successfull for" << address.toString() << "but the device class is not an inverter. Continue...";;
|
||||
cleanupConnection(connection);
|
||||
return;
|
||||
}
|
||||
@ -118,14 +102,14 @@ void SmaModbusSolarInverterDiscovery::checkNetworkDevice(const NetworkDeviceInfo
|
||||
result.port = m_port;
|
||||
result.modbusAddress = m_modbusAddress;
|
||||
result.softwareVersion = Sma::buildSoftwareVersionString(connection->softwarePackage());
|
||||
result.networkDeviceInfo = networkDeviceInfo;
|
||||
result.address = address;
|
||||
m_discoveryResults.append(result);
|
||||
|
||||
qCDebug(dcSma()) << "Discovery: --> Found" << result.productName;
|
||||
qCDebug(dcSma()) << "Discovery: Device name:" << result.deviceName;
|
||||
qCDebug(dcSma()) << "Discovery: Serial number:" << result.serialNumber;
|
||||
qCDebug(dcSma()) << "Discovery: Software version:" << result.softwareVersion;
|
||||
qCDebug(dcSma()) << "Discovery: " << result.networkDeviceInfo;
|
||||
qCDebug(dcSma()) << "Discovery: Device name:" << result.deviceName;
|
||||
qCDebug(dcSma()) << "Discovery: Serial number:" << result.serialNumber;
|
||||
qCDebug(dcSma()) << "Discovery: Software version:" << result.softwareVersion;
|
||||
qCDebug(dcSma()) << "Discovery:" << result.networkDeviceInfo;
|
||||
|
||||
// Done with this connection
|
||||
cleanupConnection(connection);
|
||||
@ -133,7 +117,7 @@ void SmaModbusSolarInverterDiscovery::checkNetworkDevice(const NetworkDeviceInfo
|
||||
|
||||
// Initializing...
|
||||
if (!connection->initialize()) {
|
||||
qCDebug(dcSma()) << "Discovery: Unable to initialize connection on" << networkDeviceInfo.address().toString() << "Continue...";;
|
||||
qCDebug(dcSma()) << "Discovery: Unable to initialize connection on" << address.toString() << "Continue...";;
|
||||
cleanupConnection(connection);
|
||||
}
|
||||
});
|
||||
@ -141,14 +125,14 @@ void SmaModbusSolarInverterDiscovery::checkNetworkDevice(const NetworkDeviceInfo
|
||||
// If we get any error...skip this host...
|
||||
connect(connection->modbusTcpMaster(), &ModbusTcpMaster::connectionErrorOccurred, this, [=](QModbusDevice::Error error){
|
||||
if (error != QModbusDevice::NoError) {
|
||||
qCDebug(dcSma()) << "Discovery: Connection error on" << networkDeviceInfo.address().toString() << "Continue...";;
|
||||
qCDebug(dcSma()) << "Discovery: Connection error on" << address.toString() << "Continue...";;
|
||||
cleanupConnection(connection);
|
||||
}
|
||||
});
|
||||
|
||||
// If check reachability failed...skip this host...
|
||||
connect(connection, &SmaSolarInverterModbusTcpConnection::checkReachabilityFailed, this, [=](){
|
||||
qCDebug(dcSma()) << "Discovery: Check reachability failed on" << networkDeviceInfo.address().toString() << "Continue...";;
|
||||
qCDebug(dcSma()) << "Discovery: Check reachability failed on" << address.toString() << "Continue...";;
|
||||
cleanupConnection(connection);
|
||||
});
|
||||
|
||||
@ -167,10 +151,15 @@ void SmaModbusSolarInverterDiscovery::finishDiscovery()
|
||||
{
|
||||
qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch();
|
||||
|
||||
// Fill in all network device infos we have
|
||||
for (int i = 0; i < m_discoveryResults.count(); i++)
|
||||
m_discoveryResults[i].networkDeviceInfo = m_networkDeviceInfos.get(m_discoveryResults.at(i).address);
|
||||
|
||||
// Cleanup any leftovers...we don't care any more
|
||||
foreach (SmaSolarInverterModbusTcpConnection *connection, m_connections)
|
||||
cleanupConnection(connection);
|
||||
|
||||
qCInfo(dcSma()) << "Discovery: Finished the discovery process. Found" << m_discoveryResults.count() << "SMA inverters in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
|
||||
qCInfo(dcSma()) << "Discovery: Finished the discovery process. Found" << m_discoveryResults.count()
|
||||
<< "SMA inverters in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
|
||||
emit discoveryFinished();
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2022, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -50,6 +50,7 @@ public:
|
||||
quint16 port;
|
||||
quint16 modbusAddress;
|
||||
QString softwareVersion;
|
||||
QHostAddress address;
|
||||
NetworkDeviceInfo networkDeviceInfo;
|
||||
} SmaModbusDiscoveryResult;
|
||||
|
||||
@ -64,15 +65,13 @@ private:
|
||||
NetworkDeviceDiscovery *m_networkDeviceDiscovery = nullptr;
|
||||
quint16 m_port;
|
||||
quint16 m_modbusAddress;
|
||||
|
||||
QDateTime m_startDateTime;
|
||||
NetworkDeviceInfos m_verifiedNetworkDeviceInfos;
|
||||
|
||||
NetworkDeviceInfos m_networkDeviceInfos;
|
||||
QList<SmaSolarInverterModbusTcpConnection *> m_connections;
|
||||
|
||||
QList<SmaModbusDiscoveryResult> m_discoveryResults;
|
||||
|
||||
void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo);
|
||||
void checkNetworkDevice(const QHostAddress &address);
|
||||
void cleanupConnection(SmaSolarInverterModbusTcpConnection *connection);
|
||||
|
||||
void finishDiscovery();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2022, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -96,7 +96,6 @@ void SpeedwireDiscovery::startMulticastDiscovery()
|
||||
sendDiscoveryRequest();
|
||||
}
|
||||
|
||||
|
||||
void SpeedwireDiscovery::startUnicastDiscovery()
|
||||
{
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Start discovering network...";
|
||||
@ -104,13 +103,12 @@ void SpeedwireDiscovery::startUnicastDiscovery()
|
||||
|
||||
NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, [this](const NetworkDeviceInfo &networkDeviceInfo){
|
||||
m_networkDeviceInfos.append(networkDeviceInfo);
|
||||
sendUnicastDiscoveryRequest(networkDeviceInfo.address());
|
||||
});
|
||||
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &SpeedwireDiscovery::sendUnicastDiscoveryRequest);
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [this, discoveryReply](){
|
||||
qCDebug(dcSma()) << "Discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices for unicast requests.";
|
||||
|
||||
m_networkDeviceInfos = discoveryReply->networkDeviceInfos();
|
||||
|
||||
// Wait some extra second in otder to give the last hosts joined some time to respond.
|
||||
QTimer::singleShot(3000, this, [this](){
|
||||
m_multicastSearchRequestTimer.stop();
|
||||
@ -178,10 +176,6 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin
|
||||
m_resultMeters.insert(senderAddress, result);
|
||||
}
|
||||
|
||||
if (m_networkDeviceInfos.hasHostAddress(senderAddress)) {
|
||||
m_resultMeters[senderAddress].networkDeviceInfo = m_networkDeviceInfos.get(senderAddress);
|
||||
}
|
||||
|
||||
m_resultMeters[senderAddress].modelId = modelId;
|
||||
m_resultMeters[senderAddress].serialNumber = serialNumber;
|
||||
} else if (header.protocolId == Speedwire::ProtocolIdInverter) {
|
||||
@ -196,10 +190,6 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin
|
||||
m_resultInverters.insert(senderAddress, result);
|
||||
}
|
||||
|
||||
if (m_networkDeviceInfos.hasHostAddress(senderAddress)) {
|
||||
m_resultInverters[senderAddress].networkDeviceInfo = m_networkDeviceInfos.get(senderAddress);
|
||||
}
|
||||
|
||||
m_resultInverters[senderAddress].modelId = inverterPacket.sourceModelId;
|
||||
m_resultInverters[senderAddress].serialNumber = inverterPacket.sourceSerialNumber;
|
||||
|
||||
@ -218,11 +208,11 @@ void SpeedwireDiscovery::processDatagram(const QHostAddress &senderAddress, quin
|
||||
connect(reply, &SpeedwireInverterReply::finished, this, [/*this, inverter,*/ senderAddress, reply](){
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Identify request finished from" << senderAddress.toString() << reply->error();
|
||||
|
||||
// SpeedwireInverterReply *loginReply = inverter->sendLoginRequest();
|
||||
// qCDebug(dcSma()) << "SpeedwireDiscovery: make login attempt using the default password.";
|
||||
// connect(loginReply, &SpeedwireInverterReply::finished, this, [loginReply, senderAddress](){
|
||||
// qCDebug(dcSma()) << "SpeedwireDiscovery: login attempt finished" << senderAddress.toString() << loginReply->error();
|
||||
// });
|
||||
// SpeedwireInverterReply *loginReply = inverter->sendLoginRequest();
|
||||
// qCDebug(dcSma()) << "SpeedwireDiscovery: make login attempt using the default password.";
|
||||
// connect(loginReply, &SpeedwireInverterReply::finished, this, [loginReply, senderAddress](){
|
||||
// qCDebug(dcSma()) << "SpeedwireDiscovery: login attempt finished" << senderAddress.toString() << loginReply->error();
|
||||
// });
|
||||
});
|
||||
|
||||
} else {
|
||||
@ -248,6 +238,10 @@ void SpeedwireDiscovery::finishDiscovery()
|
||||
{
|
||||
m_results = m_resultMeters.values() + m_resultInverters.values();
|
||||
|
||||
// Fill in all network device infos we have
|
||||
for (int i = 0; i < m_results.count(); i++)
|
||||
m_results[i].networkDeviceInfo = m_networkDeviceInfos.get(m_results.at(i).address);
|
||||
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Discovey finished. Found" << m_results.count() << "SMA devices in the network";
|
||||
m_multicastSearchRequestTimer.stop();
|
||||
|
||||
@ -255,13 +249,11 @@ void SpeedwireDiscovery::finishDiscovery()
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: ============================================";
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Device type:" << result.deviceType;
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Address:" << result.address.toString();
|
||||
if (result.networkDeviceInfo.isValid()) {
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Hostname:" << result.networkDeviceInfo.hostName();
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: MAC:" << result.networkDeviceInfo.macAddress();
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: MAC manufacturer:" << result.networkDeviceInfo.macAddressManufacturer();
|
||||
}
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Model ID:" << result.modelId;
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery: Serial number:" << result.serialNumber;
|
||||
if (result.networkDeviceInfo.isValid()) {
|
||||
qCDebug(dcSma()) << "SpeedwireDiscovery:" << result.networkDeviceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
emit discoveryFinished();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2022, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
|
||||
@ -33,17 +33,43 @@
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
SpeedwireInverter::SpeedwireInverter(SpeedwireInterface *speedwireInterface, const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_speedwireInterface(speedwireInterface),
|
||||
m_address(address),
|
||||
m_modelId(modelId),
|
||||
m_serialNumber(serialNumber)
|
||||
SpeedwireInverter::SpeedwireInverter(SpeedwireInterface *speedwireInterface, NetworkDeviceMonitor *monitor, quint16 modelId, quint32 serialNumber, QObject *parent)
|
||||
: QObject{parent},
|
||||
m_speedwireInterface{speedwireInterface},
|
||||
m_monitor{monitor},
|
||||
m_modelId{modelId},
|
||||
m_serialNumber{serialNumber}
|
||||
{
|
||||
if (!m_monitor->networkDeviceInfo().address().isNull())
|
||||
m_address = m_monitor->networkDeviceInfo().address();
|
||||
|
||||
qCDebug(dcSma()) << "Inverter: setup interface on" << m_monitor;
|
||||
connect(m_monitor, &NetworkDeviceMonitor::reachableChanged, this, [this](bool reachable){
|
||||
qCDebug(dcSma()) << "Inverter: reachable changed" << m_monitor;
|
||||
if (reachable) {
|
||||
m_address = m_monitor->networkDeviceInfo().address();
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_speedwireInterface, &SpeedwireInterface::dataReceived, this, &SpeedwireInverter::processData);
|
||||
}
|
||||
|
||||
SpeedwireInverter::SpeedwireInverter(SpeedwireInterface *speedwireInterface, const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent)
|
||||
: QObject{parent},
|
||||
m_speedwireInterface{speedwireInterface},
|
||||
m_address{address},
|
||||
m_modelId{modelId},
|
||||
m_serialNumber{serialNumber}
|
||||
{
|
||||
qCDebug(dcSma()) << "Inverter: setup interface on" << m_address.toString();
|
||||
connect(m_speedwireInterface, &SpeedwireInterface::dataReceived, this, &SpeedwireInverter::processData);
|
||||
}
|
||||
|
||||
NetworkDeviceMonitor *SpeedwireInverter::monitor() const
|
||||
{
|
||||
return m_monitor;
|
||||
}
|
||||
|
||||
SpeedwireInverter::State SpeedwireInverter::state() const
|
||||
{
|
||||
return m_state;
|
||||
|
||||
@ -34,12 +34,15 @@
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
|
||||
#include <network/networkdevicemonitor.h>
|
||||
|
||||
#include "sma.h"
|
||||
#include "speedwire.h"
|
||||
#include "speedwireinterface.h"
|
||||
#include "speedwireinverterreply.h"
|
||||
#include "speedwireinverterrequest.h"
|
||||
|
||||
|
||||
class SpeedwireInverter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -54,8 +57,11 @@ public:
|
||||
};
|
||||
Q_ENUM(State)
|
||||
|
||||
explicit SpeedwireInverter(SpeedwireInterface *speedwireInterface, NetworkDeviceMonitor *monitor, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr);
|
||||
explicit SpeedwireInverter(SpeedwireInterface *speedwireInterface, const QHostAddress &address, quint16 modelId, quint32 serialNumber, QObject *parent = nullptr);
|
||||
|
||||
NetworkDeviceMonitor *monitor() const;
|
||||
|
||||
State state() const;
|
||||
|
||||
bool reachable() const;
|
||||
@ -122,6 +128,7 @@ signals:
|
||||
|
||||
private:
|
||||
SpeedwireInterface *m_speedwireInterface = nullptr;
|
||||
NetworkDeviceMonitor *m_monitor = nullptr;
|
||||
QHostAddress m_address;
|
||||
QString m_password;
|
||||
|
||||
|
||||
@ -31,9 +31,9 @@
|
||||
#include "sunnywebbox.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include "QJsonDocument"
|
||||
#include "QJsonObject"
|
||||
#include "QJsonArray"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
SunnyWebBox::SunnyWebBox(NetworkAccessManager *networkAccessManager, const QHostAddress &hostAddress, QObject *parrent) :
|
||||
QObject(parrent),
|
||||
@ -142,16 +142,6 @@ void SunnyWebBox::setHostAddress(const QHostAddress &address)
|
||||
m_hostAddresss = address;
|
||||
}
|
||||
|
||||
QString SunnyWebBox::macAddress() const
|
||||
{
|
||||
return m_macAddress;
|
||||
}
|
||||
|
||||
void SunnyWebBox::setMacAddress(const QString &macAddress)
|
||||
{
|
||||
m_macAddress = macAddress;
|
||||
}
|
||||
|
||||
QNetworkReply *SunnyWebBox::sendRequest(const QHostAddress &address, const QString &procedure, const QJsonObject ¶ms, const QString &requestId)
|
||||
{
|
||||
qCDebug(dcSma()) << "SunnyWebBox: Send message to" << address.toString() << "Procedure:" << procedure << "Params:" << params;
|
||||
|
||||
@ -31,8 +31,8 @@
|
||||
#ifndef SUNNYWEBBOX_H
|
||||
#define SUNNYWEBBOX_H
|
||||
|
||||
#include "integrations/thing.h"
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include <integrations/thing.h>
|
||||
#include <network/networkaccessmanager.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonObject>
|
||||
@ -88,9 +88,6 @@ public:
|
||||
QHostAddress hostAddress() const;
|
||||
void setHostAddress(const QHostAddress &address);
|
||||
|
||||
QString macAddress() const;
|
||||
void setMacAddress(const QString &macAddress);
|
||||
|
||||
QNetworkReply *sendRequest(const QHostAddress &address, const QString &procedure, const QJsonObject ¶ms = QJsonObject(), const QString &requestId = QString());
|
||||
|
||||
static QString generateRequestId();
|
||||
@ -99,7 +96,6 @@ private:
|
||||
NetworkAccessManager *m_networkManager = nullptr;
|
||||
bool m_connected = false;
|
||||
QHostAddress m_hostAddresss;
|
||||
QString m_macAddress;
|
||||
QDateTime m_lastRequest;
|
||||
|
||||
QString sendMessage(const QHostAddress &address, const QString &procedure);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2022, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -46,8 +46,8 @@ SunnyWebBoxDiscovery::SunnyWebBoxDiscovery(NetworkAccessManager *networkAccessMa
|
||||
void SunnyWebBoxDiscovery::startDiscovery()
|
||||
{
|
||||
// Clean up
|
||||
m_discoveredHosts.clear();
|
||||
m_discoveryResults.clear();
|
||||
m_verifiedNetworkDeviceInfos.clear();
|
||||
|
||||
m_startDateTime = QDateTime::currentDateTime();
|
||||
|
||||
@ -55,23 +55,14 @@ void SunnyWebBoxDiscovery::startDiscovery()
|
||||
m_discoveryReply = m_networkDeviceDiscovery->discover();
|
||||
|
||||
// Test any network device beeing discovered
|
||||
connect(m_discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &SunnyWebBoxDiscovery::checkNetworkDevice);
|
||||
|
||||
// When the network discovery has finished, we process the rest and give some time to finish the pending replies
|
||||
connect(m_discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &SunnyWebBoxDiscovery::checkNetworkDevice);
|
||||
connect(m_discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
|
||||
// The network device discovery is done
|
||||
m_discoveredNetworkDeviceInfos = m_discoveryReply->networkDeviceInfos();
|
||||
m_networkDeviceInfos = m_discoveryReply->networkDeviceInfos();
|
||||
|
||||
m_discoveryReply->deleteLater();
|
||||
m_discoveryReply = nullptr;
|
||||
|
||||
// Check if all network device infos have been verified
|
||||
foreach (const NetworkDeviceInfo &networkDeviceInfo, m_discoveredNetworkDeviceInfos) {
|
||||
if (m_verifiedNetworkDeviceInfos.contains(networkDeviceInfo))
|
||||
continue;
|
||||
|
||||
checkNetworkDevice(networkDeviceInfo);
|
||||
}
|
||||
|
||||
// If there might be some response after the grace period time,
|
||||
// we don't care any more since there might just waiting for some timeouts...
|
||||
// If there would be a device, if would have responded.
|
||||
@ -87,16 +78,11 @@ NetworkDeviceInfos SunnyWebBoxDiscovery::discoveryResults() const
|
||||
return m_discoveryResults;
|
||||
}
|
||||
|
||||
void SunnyWebBoxDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo)
|
||||
void SunnyWebBoxDiscovery::checkNetworkDevice(const QHostAddress &address)
|
||||
{
|
||||
if (m_verifiedNetworkDeviceInfos.contains(networkDeviceInfo))
|
||||
return;
|
||||
|
||||
m_verifiedNetworkDeviceInfos.append(networkDeviceInfo);
|
||||
|
||||
// Make a simple request and verify if it worked and the expected data gets returned.
|
||||
SunnyWebBox webBox(m_networkAccessManager, networkDeviceInfo.address(), this);
|
||||
QNetworkReply *reply = webBox.sendRequest(networkDeviceInfo.address(), "GetPlantOverview");
|
||||
SunnyWebBox webBox(m_networkAccessManager, address, this);
|
||||
QNetworkReply *reply = webBox.sendRequest(address, "GetPlantOverview");
|
||||
m_pendingReplies.append(reply);
|
||||
connect(reply, &QNetworkReply::finished, this, [=](){
|
||||
m_pendingReplies.removeAll(reply);
|
||||
@ -104,7 +90,7 @@ void SunnyWebBoxDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDe
|
||||
|
||||
// Check HTTP reply
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Checked" << networkDeviceInfo.address().toString()
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Checked" << address.toString()
|
||||
<< "and a HTTP error occurred:" << reply->errorString() << "Continue...";
|
||||
return;
|
||||
}
|
||||
@ -115,28 +101,28 @@ void SunnyWebBoxDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDe
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Checked" << networkDeviceInfo.address().toString()
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Checked" << address.toString()
|
||||
<< "and received invalid JSON data:" << error.errorString() << "Continue...";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jsonDoc.isObject()) {
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Response JSON is not an Object" << networkDeviceInfo.address().toString() << "Continue...";
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Response JSON is not an Object" << address.toString() << "Continue...";
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap map = jsonDoc.toVariant().toMap();
|
||||
if (map["version"] != "1.0") {
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: API version not supported on" << networkDeviceInfo.address().toString() << "Continue...";;
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: API version not supported on" << address.toString() << "Continue...";;
|
||||
return;
|
||||
}
|
||||
|
||||
if (map.contains("proc") && map.contains("result")) {
|
||||
// Ok, seems to be a Sunny WebBox we are talking to...add to the discovery results...
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: --> Found Sunny WebBox on" << networkDeviceInfo;
|
||||
m_discoveryResults.append(networkDeviceInfo);
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: --> Found Sunny WebBox on" << address;
|
||||
m_discoveredHosts.append(address);
|
||||
} else {
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Missing proc or result value in response from" << networkDeviceInfo.address().toString() << "Continue...";
|
||||
qCDebug(dcSma()) << "Discovery: SunnyWebBox: Missing proc or result value in response from" << address.toString() << "Continue...";
|
||||
return;
|
||||
}
|
||||
});
|
||||
@ -152,6 +138,10 @@ void SunnyWebBoxDiscovery::cleanupPendingReplies()
|
||||
void SunnyWebBoxDiscovery::finishDiscovery()
|
||||
{
|
||||
qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch();
|
||||
|
||||
foreach (const QHostAddress &address, m_discoveredHosts)
|
||||
m_discoveryResults.append(m_networkDeviceInfos.get(address));
|
||||
|
||||
qCInfo(dcSma()) << "Discovery: SunnyWebBox: Finished the discovery process. Found" << m_discoveryResults.count()
|
||||
<< "Sunny WebBoxes in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2022, nymea GmbH
|
||||
* Copyright 2013 - 2024, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -50,7 +50,7 @@ signals:
|
||||
void discoveryFinished();
|
||||
|
||||
private slots:
|
||||
void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo);
|
||||
void checkNetworkDevice(const QHostAddress &address);
|
||||
void cleanupPendingReplies();
|
||||
void finishDiscovery();
|
||||
|
||||
@ -59,9 +59,9 @@ private:
|
||||
NetworkDeviceDiscovery *m_networkDeviceDiscovery = nullptr;
|
||||
NetworkDeviceDiscoveryReply *m_discoveryReply = nullptr;
|
||||
|
||||
QList<QHostAddress> m_discoveredHosts;
|
||||
NetworkDeviceInfos m_discoveryResults;
|
||||
NetworkDeviceInfos m_discoveredNetworkDeviceInfos;
|
||||
NetworkDeviceInfos m_verifiedNetworkDeviceInfos;
|
||||
NetworkDeviceInfos m_networkDeviceInfos;
|
||||
|
||||
QDateTime m_startDateTime;
|
||||
QList<QNetworkReply *> m_pendingReplies;
|
||||
|
||||
Reference in New Issue
Block a user