Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge PR #756: Keba: Update to networkdevice interface
Browse files Browse the repository at this point in the history
jenkins committed Jan 14, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 8ebf94e + 0473671 commit c3dd46f
Showing 5 changed files with 90 additions and 62 deletions.
24 changes: 16 additions & 8 deletions keba/integrationpluginkeba.cpp
Original file line number Diff line number Diff line change
@@ -50,6 +50,12 @@ void IntegrationPluginKeba::init()
m_macAddressParamTypeIds.insert(kebaThingClassId, kebaThingMacAddressParamTypeId);
m_macAddressParamTypeIds.insert(kebaSimpleThingClassId, kebaSimpleThingMacAddressParamTypeId);

m_hostNameParamTypeIds.insert(kebaThingClassId, kebaThingHostNameParamTypeId);
m_hostNameParamTypeIds.insert(kebaSimpleThingClassId, kebaSimpleThingHostNameParamTypeId);

m_addressParamTypeIds.insert(kebaThingClassId, kebaThingAddressParamTypeId);
m_addressParamTypeIds.insert(kebaSimpleThingClassId, kebaSimpleThingAddressParamTypeId);

m_modelParamTypeIds.insert(kebaThingClassId, kebaThingModelParamTypeId);
m_modelParamTypeIds.insert(kebaSimpleThingClassId, kebaSimpleThingModelParamTypeId);

@@ -104,14 +110,16 @@ void IntegrationPluginKeba::discoverThings(ThingDiscoveryInfo *info)
qCDebug(dcKeba()) << "Discovered:" << descriptor.title() << descriptor.description();

// Check if we already have set up this device
Things existingThings = myThings().filterByParam(m_macAddressParamTypeIds.value(discoveredThingClassId), result.networkDeviceInfo.macAddress());
Things existingThings = myThings().filterByParam(m_serialNumberParamTypeIds.value(discoveredThingClassId), result.serialNumber);
if (existingThings.count() == 1) {
qCDebug(dcKeba()) << "This keba already exists in the system!" << result.networkDeviceInfo;
descriptor.setThingId(existingThings.first()->id());
}

ParamList params;
params << Param(m_macAddressParamTypeIds.value(discoveredThingClassId), result.networkDeviceInfo.macAddress());
params << Param(m_macAddressParamTypeIds.value(discoveredThingClassId), result.networkDeviceInfo.thingParamValueMacAddress());
params << Param(m_hostNameParamTypeIds.value(discoveredThingClassId), result.networkDeviceInfo.thingParamValueHostName());
params << Param(m_addressParamTypeIds.value(discoveredThingClassId), result.networkDeviceInfo.thingParamValueAddress());
params << Param(m_modelParamTypeIds.value(discoveredThingClassId), result.product);
params << Param(m_serialNumberParamTypeIds.value(discoveredThingClassId), result.serialNumber);
descriptor.setParams(params);
@@ -156,16 +164,16 @@ void IntegrationPluginKeba::setupThing(ThingSetupInfo *info)
}
}


// Create a monitor so we always get the correct IP in the network and see if the device is reachable without polling on our own
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(thing);
// Make sure we have a valid mac address, otherwise no monitor and not auto searching is possible
MacAddress macAddress = MacAddress(thing->paramValue(m_macAddressParamTypeIds.value(thing->thingClassId())).toString());
if (macAddress.isNull()) {
qCWarning(dcKeba()) << "Failed to set up keba because the MAC address is not valid:" << thing->paramValue(m_macAddressParamTypeIds.value(thing->thingClassId())).toString() << macAddress.toString();
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The MAC address is not vaild. Please reconfigure the device to fix this."));
if (!monitor) {
qCWarning(dcKeba()) << "Can not set up connection monitor with the given parameters:" << thing->params();
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("Unable to set up the connection with this configuration. Please reconfigure the connection."));
return;
}

// Create a monitor so we always get the correct IP in the network and see if the device is reachable without polling on our own
NetworkDeviceMonitor *monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(macAddress);
connect(monitor, &NetworkDeviceMonitor::reachableChanged, thing, [=](bool reachable){
// Only if the setup has been finished
KeContact *keba = m_kebaDevices.value(thing->id());
2 changes: 2 additions & 0 deletions keba/integrationpluginkeba.h
Original file line number Diff line number Diff line change
@@ -77,6 +77,8 @@ class IntegrationPluginKeba : public IntegrationPlugin
KebaDiscovery *m_runningDiscovery = nullptr;

QHash<ThingClassId, ParamTypeId> m_macAddressParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_hostNameParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_addressParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_modelParamTypeIds;
QHash<ThingClassId, ParamTypeId> m_serialNumberParamTypeIds;

42 changes: 37 additions & 5 deletions keba/integrationpluginkeba.json
Original file line number Diff line number Diff line change
@@ -13,24 +13,40 @@
"name": "keba",
"displayName": "Keba KeContact",
"createMethods": ["discovery", "user"],
"interfaces": ["evcharger", "smartmeterconsumer", "connectable"],
"interfaces": ["evcharger", "smartmeterconsumer", "connectable", "networkdevice"],
"paramTypes":[
{
"id": "c2df921d-ff8b-411c-9b1d-04a437d7dfa6",
"name": "macAddress",
"displayName": "MAC address",
"type": "QString",
"inputType": "TextLine",
"defaultValue":"",
"inputType": "MacAddress",
"defaultValue": "",
"readOnly": true
},
{
"id": "0cc79bb7-3162-432c-a7bc-45f9b5542fbd",
"name": "hostName",
"displayName": "Host name",
"type": "QString",
"inputType": "TextLine",
"defaultValue": ""
},
{
"id": "22f70789-33c2-4183-8bca-0d3108b1c80b",
"name": "address",
"displayName": "IP address",
"type": "QString",
"inputType": "IPv4Address",
"defaultValue": ""
},
{
"id": "45255155-318b-4204-8ce6-2c106a56286d",
"name": "serialNumber",
"displayName": "Serial number",
"type": "QString",
"inputType": "TextLine",
"defaultValue":"",
"defaultValue": "",
"readOnly": true
},
{
@@ -39,7 +55,7 @@
"displayName": "Product name",
"type": "QString",
"inputType": "TextLine",
"defaultValue":"",
"defaultValue": "",
"readOnly": true
}
],
@@ -410,6 +426,22 @@
"defaultValue":"",
"readOnly": true
},
{
"id": "96104d2b-2fd3-4f20-bc8c-7b873d0b0f9e",
"name": "hostName",
"displayName": "Host name",
"type": "QString",
"inputType": "TextLine",
"defaultValue": ""
},
{
"id": "a0c60511-4082-4109-9a9f-383076680c4f",
"name": "address",
"displayName": "IP address",
"type": "QString",
"inputType": "IPv4Address",
"defaultValue": ""
},
{
"id": "6f732eb9-1711-4da0-a9a4-abcfa19f5e34",
"name": "serialNumber",
70 changes: 29 additions & 41 deletions keba/kebadiscovery.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Copyright 2013 - 2024, nymea GmbH
* Contact: [email protected]
*
* This file is part of nymea.
@@ -44,19 +44,19 @@ KebaDiscovery::KebaDiscovery(KeContactDataLayer *kebaDataLayer, NetworkDeviceDis
m_responseTimer.setInterval(2000);
m_responseTimer.setSingleShot(true);
connect(&m_responseTimer, &QTimer::timeout, this, [=](){

// 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);
}

qCInfo(dcKeba()) << "Discovery: Finished successfully. Found" << m_results.count() << "Keba Wallbox";
emit discoveryFinished();
});

// Read data from the keba data layer and verify if it is a keba report
connect (m_kebaDataLayer, &KeContactDataLayer::datagramReceived, this, [=](const QHostAddress &address, const QByteArray &datagram){

// Just continue if this is a new address we have no result for
if (alreadyDiscovered(address)) {
qCDebug(dcKeba()) << "Discovery: Skipping datagram from already discovered Keba on" << address.toString();
return;
}

// Try to convert the received data to a json document
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(datagram, &error);
@@ -78,15 +78,23 @@ KebaDiscovery::KebaDiscovery(KeContactDataLayer *kebaDataLayer, NetworkDeviceDis
}

// We have received a report 1 datagram, let's add it to the result
NetworkDeviceInfo networkDeviceInfo = m_verifiedNetworkDeviceInfos.get(address);
if (networkDeviceInfo.isValid()) {
KebaDiscoveryResult result;
result.networkDeviceInfo = networkDeviceInfo;
result.product = dataMap.value("Product").toString();
result.serialNumber = dataMap.value("Serial").toString();
result.firmwareVersion = dataMap.value("Firmware").toString();
KebaDiscoveryResult result;
result.address = address;
result.product = dataMap.value("Product").toString();
result.serialNumber = dataMap.value("Serial").toString();
result.firmwareVersion = dataMap.value("Firmware").toString();

bool alreadyDiscovered = false;
foreach (const KebaDiscoveryResult &r, m_results) {
if (r.serialNumber == result.serialNumber) {
alreadyDiscovered = true;
break;
}
}

if (!alreadyDiscovered) {
m_results.append(result);
qCDebug(dcKeba()) << "Discovery: -->" << networkDeviceInfo << networkDeviceInfo.macAddress() << result.product << result.serialNumber << result.firmwareVersion;
qCDebug(dcKeba()) << "Discovery: -->" << address.toString() << result.product << result.serialNumber << result.firmwareVersion;
}
});
}
@@ -104,26 +112,16 @@ void KebaDiscovery::startDiscovery()
qCInfo(dcKeba()) << "Discovery: Start searching for Keba wallboxes in the network...";
NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();

// Check any already discovered infos..
foreach (const NetworkDeviceInfo &networkDeviceInfo, discoveryReply->networkDeviceInfos()) {
sendReportRequest(networkDeviceInfo);
}

// Imedialty check any new device gets discovered
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &KebaDiscovery::sendReportRequest);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::hostAddressDiscovered, this, &KebaDiscovery::sendReportRequest);

// Check what might be left on finished
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, discoveryReply, &NetworkDeviceDiscoveryReply::deleteLater);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
qCDebug(dcKeba()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices";
m_networkDeviceInfos = discoveryReply->networkDeviceInfos();

qCDebug(dcKeba()) << "Discovery: Network discovery finished. Start finishing discovery...";
// Send a report request to nework device info not sent already...
foreach (const NetworkDeviceInfo &networkDeviceInfo, m_networkDeviceInfos) {
if (!m_verifiedNetworkDeviceInfos.contains(networkDeviceInfo)) {
sendReportRequest(networkDeviceInfo);
}
}
m_responseTimer.start();
});
}
@@ -133,27 +131,17 @@ QList<KebaDiscovery::KebaDiscoveryResult> KebaDiscovery::discoveryResults() cons
return m_results;
}

bool KebaDiscovery::alreadyDiscovered(const QHostAddress &address)
void KebaDiscovery::sendReportRequest(const QHostAddress &address)
{
foreach (const KebaDiscoveryResult &result, m_results) {
if (result.networkDeviceInfo.address() == address) {
return true;
}
}

return false;
m_verifiedAddresses.append(address);
m_kebaDataLayer->write(address, QByteArray("report 1\n"));
}

void KebaDiscovery::cleanup()
{
m_networkDeviceInfos.clear();
m_verifiedNetworkDeviceInfos.clear();
m_verifiedAddresses.clear();
m_results.clear();
}

void KebaDiscovery::sendReportRequest(const NetworkDeviceInfo &networkDeviceInfo)
{
m_verifiedNetworkDeviceInfos.append(networkDeviceInfo);
m_kebaDataLayer->write(networkDeviceInfo.address(), QByteArray("report 1\n"));
}

14 changes: 6 additions & 8 deletions keba/kebadiscovery.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, nymea GmbH
* Copyright 2013 - 2024, nymea GmbH
* Contact: [email protected]
*
* This file is part of nymea.
@@ -47,6 +47,7 @@ class KebaDiscovery : public QObject
QString product;
QString serialNumber;
QString firmwareVersion;
QHostAddress address;
NetworkDeviceInfo networkDeviceInfo;
} KebaDiscoveryResult;

@@ -60,22 +61,19 @@ class KebaDiscovery : public QObject
signals:
void discoveryFinished();

private slots:
void sendReportRequest(const QHostAddress &address);

private:
KeContactDataLayer *m_kebaDataLayer = nullptr;
NetworkDeviceDiscovery *m_networkDeviceDiscovery = nullptr;
QTimer m_responseTimer;

NetworkDeviceInfos m_networkDeviceInfos;
NetworkDeviceInfos m_verifiedNetworkDeviceInfos;
QList<QHostAddress> m_verifiedAddresses;
QList<KebaDiscoveryResult> m_results;

bool alreadyDiscovered(const QHostAddress &address);

void cleanup();

private slots:
void sendReportRequest(const NetworkDeviceInfo &networkDeviceInfo);

};

#endif // KEBADISCOVERY_H

0 comments on commit c3dd46f

Please sign in to comment.