Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sungrow: Update to networkdevice interface #201

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions sungrow/integrationpluginsungrow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,29 @@ void IntegrationPluginSungrow::discoverThings(ThingDiscoveryInfo *info)

// Create a discovery with the info as parent for auto deleting the object once the discovery info is done
SungrowDiscovery *discovery = new SungrowDiscovery(hardwareManager()->networkDeviceDiscovery(), m_modbusTcpPort, m_modbusSlaveAddress, info);
connect(discovery, &SungrowDiscovery::discoveryFinished, discovery, &SungrowDiscovery::deleteLater);
connect(discovery, &SungrowDiscovery::discoveryFinished, info, [=](){
foreach (const SungrowDiscovery::SungrowDiscoveryResult &result, discovery->discoveryResults()) {
QString title = "Sungrow " + QString::number(result.nominalOutputPower) + "kW Inverter";

if (!result.serialNumber.isEmpty())
title.append(" " + result.serialNumber);

ThingDescriptor descriptor(sungrowInverterTcpThingClassId, title, result.networkDeviceInfo.address().toString() + " " + result.networkDeviceInfo.macAddress());
ThingDescriptor descriptor(sungrowInverterTcpThingClassId, title, result.networkDeviceInfo.address().toString());
qCInfo(dcSungrow()) << "Discovered:" << descriptor.title() << descriptor.description();

ParamList params;
params << Param(sungrowInverterTcpThingMacAddressParamTypeId, result.networkDeviceInfo.thingParamValueMacAddress());
params << Param(sungrowInverterTcpThingHostNameParamTypeId, result.networkDeviceInfo.thingParamValueHostName());
params << Param(sungrowInverterTcpThingAddressParamTypeId, result.networkDeviceInfo.thingParamValueAddress());
descriptor.setParams(params);

// Check if we already have set up this device
Things existingThings = myThings().filterByParam(sungrowInverterTcpThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress());
if (existingThings.count() == 1) {
qCDebug(dcSungrow()) << "This Sungrow inverter already exists in the system:" << result.networkDeviceInfo;
descriptor.setThingId(existingThings.first()->id());
Thing *existingThing = myThings().findByParams(params);
if (existingThing) {
qCDebug(dcSungrow()) << "This thing already exists in the system:" << result.networkDeviceInfo;
descriptor.setThingId(existingThing->id());
}

ParamList params;
params << Param(sungrowInverterTcpThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress());
descriptor.setParams(params);
info->addThingDescriptor(descriptor);
}

Expand All @@ -97,16 +99,16 @@ void IntegrationPluginSungrow::setupThing(ThingSetupInfo *info)
}
}

MacAddress macAddress = MacAddress(thing->paramValue(sungrowInverterTcpThingMacAddressParamTypeId).toString());
if (!macAddress.isValid()) {
qCWarning(dcSungrow()) << "The configured MAC address is not valid" << thing->params();
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The MAC address is not known. Please reconfigure this inverter."));
// Create the monitor
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
if (!monitor) {
qCWarning(dcSungrow()) << "Unable to register monitor with the given params" << 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);

connect(info, &ThingSetupInfo::aborted, monitor, [=](){
// Clean up in case the setup gets aborted
if (m_monitors.contains(thing)) {
Expand Down
18 changes: 17 additions & 1 deletion sungrow/integrationpluginsungrow.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,25 @@
"id": "59cb2da4-da07-11ee-adea-7397f8a9afe9",
"createMethods": ["discovery"],
"discoveryType": "weak",
"interfaces": ["solarinverter", "connectable"],
"interfaces": ["solarinverter", "connectable", "networkdevice"],
"providedInterfaces": [ "energymeter", "energystorage"],
"paramTypes": [
{
"id": "311c0038-0134-4d91-878d-57526c3eec11",
"name": "address",
"displayName": "Host address",
"type": "QString",
"inputType": "IPv4Address",
"defaultValue": ""
},
{
"id": "6676fcea-1f3a-4241-ae03-18dae96c5d8d",
"name": "hostName",
"displayName": "Host name",
"type": "QString",
"inputType": "TextLine",
"defaultValue": ""
},
{
"id": "62137142-da07-11ee-9522-2f74f3b1fc5d",
"name":"macAddress",
Expand Down
29 changes: 17 additions & 12 deletions sungrow/sungrowdiscovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ void SungrowDiscovery::startDiscovery()
m_startDateTime = QDateTime::currentDateTime();

NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &SungrowDiscovery::checkNetworkDevice);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &SungrowDiscovery::checkNetworkDevice);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=] () {
qCDebug(dcSungrow()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices";
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] () {
Expand All @@ -64,15 +65,15 @@ QList<SungrowDiscovery::SungrowDiscoveryResult> SungrowDiscovery::discoveryResul
return m_discoveryResults;
}

void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo)
void SungrowDiscovery::checkNetworkDevice(const QHostAddress &address)
{
/* Create a Sungrow 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).
*/

qCDebug(dcSungrow()) << "Creating Sungrow Modbus TCP connection for" << networkDeviceInfo.address() << "Port:" << m_port << "Slave Address" << m_modbusAddress;
SungrowModbusTcpConnection *connection = new SungrowModbusTcpConnection(networkDeviceInfo.address(), m_port, m_modbusAddress, this);
qCDebug(dcSungrow()) << "Creating Sungrow Modbus TCP connection for" << address << "Port:" << m_port << "Slave Address" << m_modbusAddress;
SungrowModbusTcpConnection *connection = new SungrowModbusTcpConnection(address, m_port, m_modbusAddress, this);
connection->modbusTcpMaster()->setTimeout(5000);
connection->modbusTcpMaster()->setNumberOfRetries(0);
m_connections.append(connection);
Expand All @@ -87,20 +88,20 @@ void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice

connect(connection, &SungrowModbusTcpConnection::initializationFinished, this, [=](bool success){
if (!success) {
qCDebug(dcSungrow()) << "Discovery: Initialization failed on" << networkDeviceInfo.address().toString() << "Continue...";
qCDebug(dcSungrow()) << "Discovery: Initialization failed on" << address.toString() << "Continue...";
cleanupConnection(connection);
return;
}

qCDebug(dcSungrow()) << "Discovery: Initialized successfully" << networkDeviceInfo << connection->serialNumber();
qCDebug(dcSungrow()) << "Discovery: Initialized successfully" << address.toString() << connection->serialNumber();
qCDebug(dcSungrow()) << " - Protocol number:" << connection->protocolNumber();
qCDebug(dcSungrow()) << " - Protocol version:" << connection->protocolVersion();
qCDebug(dcSungrow()) << " - ARM software version:" << connection->armSoftwareVersion();
qCDebug(dcSungrow()) << " - DSP software version:" << connection->dspSoftwareVersion();

if (connection->deviceTypeCode() >= 0xd00 && connection->deviceTypeCode() <= 0xeff) {
SungrowDiscoveryResult result;
result.networkDeviceInfo = networkDeviceInfo;
result.address = address;
result.serialNumber = connection->serialNumber();
result.nominalOutputPower = connection->nominalOutputPower();
result.deviceType = connection->deviceTypeCode();
Expand All @@ -110,31 +111,31 @@ void SungrowDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDevice
connection->disconnectDevice();
});

qCDebug(dcSungrow()) << "Discovery: The host" << networkDeviceInfo << "is reachable. Starting with initialization.";
qCDebug(dcSungrow()) << "Discovery: The host" << address << "is reachable. Starting with initialization.";
if (!connection->initialize()) {
qCDebug(dcSungrow()) << "Discovery: Unable to initialize connection on" << networkDeviceInfo.address().toString() << "Continue...";
qCDebug(dcSungrow()) << "Discovery: Unable to initialize connection on" << address.toString() << "Continue...";
cleanupConnection(connection);
}
});

// In case of an error skip the host
connect(connection->modbusTcpMaster(), &ModbusTcpMaster::connectionStateChanged, this, [=](bool connected){
if (connected) {
qCDebug(dcSungrow()) << "Discovery: Connected with" << networkDeviceInfo.address().toString() << m_port;
qCDebug(dcSungrow()) << "Discovery: Connected with" << address.toString() << m_port;
}
});

// In case of an error skip the host
connect(connection->modbusTcpMaster(), &ModbusTcpMaster::connectionErrorOccurred, this, [=](QModbusDevice::Error error){
if (error != QModbusDevice::NoError) {
qCDebug(dcSungrow()) << "Discovery: Connection error on" << networkDeviceInfo.address().toString() << "Continue...";
qCDebug(dcSungrow()) << "Discovery: Connection error on" << address.toString() << "Continue...";
cleanupConnection(connection);
}
});

// If the reachability check failed skip the host
connect(connection, &SungrowModbusTcpConnection::checkReachabilityFailed, this, [=](){
qCDebug(dcSungrow()) << "Discovery: Check reachability failed on" << networkDeviceInfo.address().toString() << "Continue...";
qCDebug(dcSungrow()) << "Discovery: Check reachability failed on" << address.toString() << "Continue...";
cleanupConnection(connection);
});

Expand All @@ -153,6 +154,10 @@ void SungrowDiscovery::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);

foreach (SungrowModbusTcpConnection *connection, m_connections)
cleanupConnection(connection);

Expand Down
4 changes: 3 additions & 1 deletion sungrow/sungrowdiscovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class SungrowDiscovery : public QObject
explicit SungrowDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, quint16 port = 502, quint16 modbusAddress = 1, QObject *parent = nullptr);
typedef struct SungrowDiscoveryResult {
QString serialNumber;
QHostAddress address;
NetworkDeviceInfo networkDeviceInfo;
float nominalOutputPower;
int deviceType;
Expand All @@ -64,10 +65,11 @@ class SungrowDiscovery : public QObject

QDateTime m_startDateTime;

NetworkDeviceInfos m_networkDeviceInfos;
QList<SungrowModbusTcpConnection *> m_connections;
QList<SungrowDiscoveryResult> m_discoveryResults;

void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo);
void checkNetworkDevice(const QHostAddress &address);
void cleanupConnection(SungrowModbusTcpConnection *connection);

void finishDiscovery();
Expand Down