New plugin: Wattsonic
This commit is contained in:
parent
eae2cbe0ee
commit
2d9d4aea42
9
debian/control
vendored
9
debian/control
vendored
@ -258,6 +258,15 @@ Description: nymea integration plugin for PhoenixConnect wallboxes
|
||||
This package contains the nymea integration plugin for wallboxes made
|
||||
by PhonenixConnect and rebranded as Wallbe, Compleo and Scapo.
|
||||
|
||||
Package: nymea-plugin-wattsonic
|
||||
Architecture: any
|
||||
Section: libs
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
Description: nymea integration plugin for Wattsonic hybrid inverters
|
||||
This package contains the nymea integration plugin for hybrid inverters made
|
||||
by Wattsonic.
|
||||
|
||||
Package: nymea-plugin-webasto
|
||||
Architecture: any
|
||||
Section: libs
|
||||
|
||||
2
debian/nymea-plugin-wattsonic.install.in
vendored
Normal file
2
debian/nymea-plugin-wattsonic.install.in
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginwattsonic.so
|
||||
wattsonic/translations/*qm usr/share/nymea/translations/
|
||||
@ -25,6 +25,7 @@ PLUGIN_DIRS = \
|
||||
stiebeleltron \
|
||||
sunspec \
|
||||
unipi \
|
||||
wattsonic \
|
||||
webasto \
|
||||
|
||||
gcc {
|
||||
|
||||
4
wattsonic/README.md
Normal file
4
wattsonic/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Wattsonic
|
||||
|
||||
This plugin allows to connect wattsonic hybrid inverters to nymea
|
||||
|
||||
262
wattsonic/integrationpluginwattsonic.cpp
Normal file
262
wattsonic/integrationpluginwattsonic.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "integrationpluginwattsonic.h"
|
||||
#include "plugininfo.h"
|
||||
#include "wattsonicdiscovery.h"
|
||||
|
||||
#include <network/networkdevicediscovery.h>
|
||||
#include <hardwaremanager.h>
|
||||
|
||||
IntegrationPluginWattsonic::IntegrationPluginWattsonic()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginWattsonic::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
|
||||
if (info->thingClassId() == inverterThingClassId) {
|
||||
|
||||
WattsonicDiscovery *discovery = new WattsonicDiscovery(hardwareManager()->modbusRtuResource(), info);
|
||||
connect(discovery, &WattsonicDiscovery::discoveryFinished, info, [=](bool modbusRtuMasterAvailable){
|
||||
if (!modbusRtuMasterAvailable) {
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("No suitable Modbus RTU connection available. Please set up a Modbus RTU master with a baudrate of 9600, 8 data bits, 1 stop bit and no parity."));
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const WattsonicDiscovery::Result &result, discovery->discoveryResults()) {
|
||||
|
||||
QString name = "Wattsonic hybrid inverter";
|
||||
ThingDescriptor descriptor(inverterThingClassId, name, result.serialNumber);
|
||||
qCDebug(dcWattsonic()) << "Discovered:" << descriptor.title() << descriptor.description();
|
||||
|
||||
ParamList params {
|
||||
{inverterThingModbusMasterUuidParamTypeId, result.modbusRtuMasterId},
|
||||
{inverterThingSlaveAddressParamTypeId, result.slaveId}
|
||||
};
|
||||
descriptor.setParams(params);
|
||||
|
||||
// Check if we already have set up this device
|
||||
Thing *existingThing = myThings().findByParams(params);
|
||||
if (existingThing) {
|
||||
qCDebug(dcWattsonic()) << "This inverter already exists in the system:" << result.serialNumber;
|
||||
descriptor.setThingId(existingThing->id());
|
||||
}
|
||||
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
discovery->startDiscovery();
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginWattsonic::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
qCDebug(dcWattsonic()) << "Setup" << thing << thing->params();
|
||||
|
||||
if (info->thing()->thingClassId() == inverterThingClassId) {
|
||||
if (m_connections.contains(thing)) {
|
||||
qCDebug(dcWattsonic()) << "Reconfiguring existing thing" << thing->name();
|
||||
m_connections.take(thing)->deleteLater();
|
||||
}
|
||||
|
||||
setupWattsonicConnection(info);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->thing()->thingClassId() == meterThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->thing()->thingClassId() == batteryThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginWattsonic::postSetupThing(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == inverterThingClassId) {
|
||||
Things meters = myThings().filterByParentId(thing->id()).filterByThingClassId(meterThingClassId);
|
||||
if (meters.isEmpty()) {
|
||||
qCInfo(dcWattsonic()) << "No energy meter set up yet. Creating thing...";
|
||||
ThingDescriptor descriptor(meterThingClassId, "Wattsonic energy meter", QString(), thing->id());
|
||||
emit autoThingsAppeared({descriptor});
|
||||
}
|
||||
Things batteries = myThings().filterByParentId(thing->id()).filterByThingClassId(batteryThingClassId);
|
||||
if (batteries.isEmpty()) {
|
||||
qCInfo(dcWattsonic()) << "No battery set up yet. Creating thing...";
|
||||
ThingDescriptor descriptor(batteryThingClassId, "Wattsonic energy storage", QString(), thing->id());
|
||||
emit autoThingsAppeared({descriptor});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!m_pluginTimer) {
|
||||
qCDebug(dcWattsonic()) << "Starting plugin timer...";
|
||||
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(2);
|
||||
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
|
||||
foreach(WattsonicModbusRtuConnection *connection, m_connections) {
|
||||
qCDebug(dcWattsonic()) << "Updating connection" << connection->modbusRtuMaster()->serialPort() << connection->slaveId();
|
||||
connection->update();
|
||||
}
|
||||
});
|
||||
|
||||
m_pluginTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginWattsonic::thingRemoved(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == inverterThingClassId && m_connections.contains(thing)) {
|
||||
delete m_connections.take(thing);
|
||||
}
|
||||
|
||||
if (myThings().isEmpty() && m_pluginTimer) {
|
||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
|
||||
m_pluginTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginWattsonic::setupWattsonicConnection(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
|
||||
uint slaveId = thing->paramValue(inverterThingSlaveAddressParamTypeId).toUInt();
|
||||
if (slaveId > 247 || slaveId == 0) {
|
||||
qCWarning(dcWattsonic()) << "Setup failed, slave ID is not valid" << slaveId;
|
||||
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus address not valid. It must be a value between 1 and 247."));
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid uuid = thing->paramValue(inverterThingModbusMasterUuidParamTypeId).toUuid();
|
||||
if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(uuid)) {
|
||||
qCWarning(dcWattsonic()) << "Setup failed, hardware manager not available";
|
||||
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus RTU resource is not available."));
|
||||
return;
|
||||
}
|
||||
|
||||
WattsonicModbusRtuConnection *connection = new WattsonicModbusRtuConnection(hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), slaveId, this);
|
||||
connect(info, &ThingSetupInfo::aborted, connection, &ModbusRtuMaster::deleteLater);
|
||||
|
||||
m_connections.insert(thing, connection);
|
||||
connect(info, &ThingSetupInfo::aborted, this, [=](){
|
||||
m_connections.take(info->thing())->deleteLater();
|
||||
});
|
||||
|
||||
connect(connection, &WattsonicModbusRtuConnection::reachableChanged, thing, [connection, thing, this](bool reachable){
|
||||
qCDebug(dcWattsonic()) << "Reachable state changed" << reachable;
|
||||
if (reachable) {
|
||||
connection->initialize();
|
||||
} else {
|
||||
thing->setStateValue("connected", false);
|
||||
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
child->setStateValue("connected", true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(connection, &WattsonicModbusRtuConnection::initializationFinished, info, [=](bool success){
|
||||
qCDebug(dcWattsonic()) << "Initialisation finished" << success;
|
||||
if (info->isInitialSetup() && !success) {
|
||||
m_connections.take(info->thing())->deleteLater();
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
if (success) {
|
||||
qCDebug(dcWattsonic) << "Firmware version:" << connection->firmwareVersion();
|
||||
// info->thing()->setStateValue(inverterCurrentVersionStateTypeId, compact20Connection->firmwareVersion());
|
||||
}
|
||||
});
|
||||
|
||||
connect(connection, &WattsonicModbusRtuConnection::reachableChanged, thing, [=](bool reachable){
|
||||
thing->setStateValue(inverterConnectedStateTypeId, reachable);
|
||||
foreach (Thing *child, myThings().filterByParentId(thing->id())) {
|
||||
child->setStateValue("connected", reachable);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
connect(connection, &WattsonicModbusRtuConnection::updateFinished, thing, [this, connection, thing](){
|
||||
qCDebug(dcWattsonic()) << "Update finished:" << thing->name() << connection;
|
||||
|
||||
Thing *inverter = thing;
|
||||
|
||||
inverter->setStateValue(inverterCurrentPowerStateTypeId, connection->pAC() * -1.0);
|
||||
inverter->setStateValue(inverterTotalEnergyProducedStateTypeId, connection->totalPVGenerationFromInstallation() * 0.1);
|
||||
qCInfo(dcWattsonic()) << "Updating inverter:" << inverter->stateValue(inverterCurrentPowerStateTypeId).toDouble() << "W" << inverter->stateValue(inverterTotalEnergyProducedStateTypeId).toDouble() << "kWh";
|
||||
|
||||
Things meters = myThings().filterByParentId(thing->id()).filterByThingClassId(meterThingClassId);
|
||||
if (!meters.isEmpty()) {
|
||||
Thing *meter = meters.first();
|
||||
meter->setStateValue(meterCurrentPowerStateTypeId, connection->totalPowerOnMeter() * -1.0);
|
||||
meter->setStateValue(meterTotalEnergyConsumedStateTypeId, connection->totalEnergyPurchasedFromGrid() / 10.0);
|
||||
meter->setStateValue(meterTotalEnergyProducedStateTypeId, connection->totalEnergyInjectedToGrid() / 10.0);
|
||||
meter->setStateValue(meterCurrentPowerPhaseAStateTypeId, connection->phaseAPower() * -1.0);
|
||||
meter->setStateValue(meterCurrentPowerPhaseBStateTypeId, connection->phaseBPower() * -1.0);
|
||||
meter->setStateValue(meterCurrentPowerPhaseCStateTypeId, connection->phaseCPower() * -1.0);
|
||||
meter->setStateValue(meterVoltagePhaseAStateTypeId, connection->gridPhaseAVoltage() / 10.0);
|
||||
meter->setStateValue(meterVoltagePhaseBStateTypeId, connection->gridPhaseBVoltage() / 10.0);
|
||||
meter->setStateValue(meterVoltagePhaseCStateTypeId, connection->gridPhaseCVoltage() / 10.0);
|
||||
// The phase current registers don't seem to contain proper values. Calculating ourselves instead
|
||||
// meter->setStateValue(meterCurrentPhaseAStateTypeId, connection->gridPhaseACurrent() / 10.0);
|
||||
// meter->setStateValue(meterCurrentPhaseBStateTypeId, connection->gridPhaseBCurrent() / 10.0);
|
||||
// meter->setStateValue(meterCurrentPhaseCStateTypeId, connection->gridPhaseCCurrent() / 10.0);
|
||||
meter->setStateValue(meterCurrentPhaseAStateTypeId, (connection->phaseAPower() * -1.0) / (connection->gridPhaseAVoltage() / 10.0));
|
||||
meter->setStateValue(meterCurrentPhaseBStateTypeId, (connection->phaseBPower() * -1.0) / (connection->gridPhaseBVoltage() / 10.0));
|
||||
meter->setStateValue(meterCurrentPhaseCStateTypeId, (connection->phaseCPower() * -1.0) / (connection->gridPhaseCVoltage() / 10.0));
|
||||
qCInfo(dcWattsonic()) << "Updating meter:" << meter->stateValue(meterCurrentPowerStateTypeId).toDouble() << "W" << meter->stateValue(meterTotalEnergyProducedStateTypeId).toDouble() << "kWh";
|
||||
}
|
||||
Things batteries = myThings().filterByParentId(thing->id()).filterByThingClassId(batteryThingClassId);
|
||||
if (!batteries.isEmpty() && connection->SOC() > 0) {
|
||||
Thing *battery = batteries.first();
|
||||
QHash<WattsonicModbusRtuConnection::BatteryMode, QString> map {
|
||||
{WattsonicModbusRtuConnection::BatteryModeDischarge, "discharging"},
|
||||
{WattsonicModbusRtuConnection::BatteryModeCharge, "charging"}
|
||||
};
|
||||
battery->setStateValue(batteryChargingStateStateTypeId, map.value(connection->batteryMode()));
|
||||
battery->setStateValue(batteryCurrentPowerStateTypeId, connection->batteryPower() * -1.0);
|
||||
battery->setStateValue(batteryBatteryLevelStateTypeId, connection->SOC() / 100.0);
|
||||
battery->setStateValue(batteryBatteryCriticalStateTypeId, connection->SOC() < 500);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
66
wattsonic/integrationpluginwattsonic.h
Normal file
66
wattsonic/integrationpluginwattsonic.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef INTEGRATIONPLUGINWATTSONIC_H
|
||||
#define INTEGRATIONPLUGINWATTSONIC_H
|
||||
|
||||
#include <plugintimer.h>
|
||||
#include <integrations/integrationplugin.h>
|
||||
#include <network/networkdevicemonitor.h>
|
||||
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include "wattsonicmodbusrtuconnection.h"
|
||||
|
||||
class IntegrationPluginWattsonic: public IntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginwattsonic.json")
|
||||
Q_INTERFACES(IntegrationPlugin)
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginWattsonic();
|
||||
|
||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
|
||||
private:
|
||||
void setupWattsonicConnection(ThingSetupInfo *info);
|
||||
|
||||
PluginTimer *m_pluginTimer = nullptr;
|
||||
QHash<Thing *, WattsonicModbusRtuConnection *> m_connections;
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINWATTSONIC_H
|
||||
|
||||
|
||||
246
wattsonic/integrationpluginwattsonic.json
Normal file
246
wattsonic/integrationpluginwattsonic.json
Normal file
@ -0,0 +1,246 @@
|
||||
{
|
||||
"name": "Wattsonic",
|
||||
"displayName": "Wattsonic",
|
||||
"id": "d0eaf684-001e-4b1c-9e37-122955958de3",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "wattsonic",
|
||||
"displayName": "Wattsonic",
|
||||
"id": "c335f9bc-3bc9-46bf-8c50-800cd93e827a",
|
||||
"thingClasses": [
|
||||
{
|
||||
"name": "inverter",
|
||||
"displayName": "Wattsonic hybrid inverter",
|
||||
"id": "688bef8d-2ba8-4eb3-b30e-16193eba02fb",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"interfaces": ["solarinverter", "connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "55a7d9ed-5f4f-41a2-8dc1-c6a5a79512d2",
|
||||
"name": "slaveAddress",
|
||||
"displayName": "Modbus slave address",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
},
|
||||
{
|
||||
"id": "4f1238b5-07e0-4516-b84a-71670141ef81",
|
||||
"name": "modbusMasterUuid",
|
||||
"displayName": "Modbus RTU master",
|
||||
"type": "QUuid",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "c0f77c00-b82a-478e-826b-bc3204d66100",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "2cbb25e6-c1bd-4216-b354-6ad6fa957e29",
|
||||
"name": "totalEnergyProduced",
|
||||
"displayName": "Total energy produced",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "3107958e-07a2-4ebd-83a1-96fb5998cfb9",
|
||||
"name": "currentPower",
|
||||
"displayName": "Current power consumption",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "e27a9590-0d13-4d7f-b66b-946dad86b8c8",
|
||||
"name": "meter",
|
||||
"displayName": "Wattsonic energy meter",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": ["energymeter", "connectable"],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "d3bf44be-00d0-4119-ad16-45648bc1532a",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "d5ce5ba0-bc1d-4af3-9afa-cbfb6c0d01ec",
|
||||
"name": "currentPower",
|
||||
"displayName": "Current power consumption",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"cached": false,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "60d486a6-337d-4977-9624-78d99657aea9",
|
||||
"name": "totalEnergyConsumed",
|
||||
"displayName": "Total consumed energy",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "3fd2e110-8851-4530-bb53-e8e5b20cd4cb",
|
||||
"name": "totalEnergyProduced",
|
||||
"displayName": "Total returned energy",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "1def2f00-8d1c-4d22-b662-a31a552c8a82",
|
||||
"name": "currentPowerPhaseA",
|
||||
"displayName": "Power consumption phase A",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "404549a1-de1e-42e2-8d5d-f581b8674b7d",
|
||||
"name": "currentPowerPhaseB",
|
||||
"displayName": "Power consumption phase B",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "6fccc09c-7c89-45b7-908e-9cbe5bda1c2c",
|
||||
"name": "currentPowerPhaseC",
|
||||
"displayName": "Power consumption phase C",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "12798e83-3093-411e-ab8e-5955956717da",
|
||||
"name": "voltagePhaseA",
|
||||
"displayName": "Voltage phase A",
|
||||
"type": "double",
|
||||
"unit": "Volt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "eef67976-2c39-4d79-8b6d-053e369346a8",
|
||||
"name": "voltagePhaseB",
|
||||
"displayName": "Voltage phase B",
|
||||
"type": "double",
|
||||
"unit": "Volt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "1e237634-d23c-4c20-b710-b3586bbb988f",
|
||||
"name": "voltagePhaseC",
|
||||
"displayName": "Voltage phase C",
|
||||
"type": "double",
|
||||
"unit": "Volt",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "80c12358-c2d9-4c1b-9150-b7dc3da8a7ae",
|
||||
"name": "currentPhaseA",
|
||||
"displayName": "Current phase A",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "d0914688-59ae-4bd9-97ee-1668e7948ab0",
|
||||
"name": "currentPhaseB",
|
||||
"displayName": "Current phase B",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "ecb8072f-dcb0-4e5e-8cc9-95947d3b7185",
|
||||
"name": "currentPhaseC",
|
||||
"displayName": "Current phase C",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0,
|
||||
"cached": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "04c4e5fd-7b64-444f-8905-75651833224e",
|
||||
"name": "battery",
|
||||
"displayName": "Wattsonic energy storage",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": ["energystorage", "connectable"],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "a8673429-043e-4149-8775-c89cab0b63ca",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "76c70da1-484d-4bb2-8070-22e5e141cadd",
|
||||
"name": "batteryCritical",
|
||||
"displayName": "Battery critical",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "113cac91-24cf-45eb-93bf-e81145ba6c4e",
|
||||
"name": "batteryLevel",
|
||||
"displayName": "Battery level",
|
||||
"type": "int",
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "dfaa3890-e3d2-4262-be3d-ece18b520ed9",
|
||||
"name": "chargingState",
|
||||
"displayName": "Charging state",
|
||||
"type": "QString",
|
||||
"possibleValues": ["idle", "charging", "discharging"],
|
||||
"defaultValue": "idle"
|
||||
},
|
||||
{
|
||||
"id": "608da87c-e45f-471d-975d-936807a94c9a",
|
||||
"name": "currentPower",
|
||||
"displayName": "Current power consumption",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"cached": false,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "5c652ecd-1302-4796-92fa-672a3d9442c8",
|
||||
"name": "capacity",
|
||||
"displayName": "Capacity",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
13
wattsonic/meta.json
Normal file
13
wattsonic/meta.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"title": "Wattsonic",
|
||||
"tagline": "Connect Wattsonic devices to nymea.",
|
||||
"icon": "wattsonic.svg",
|
||||
"stability": "consumer",
|
||||
"offline": true,
|
||||
"technologies": [
|
||||
"network"
|
||||
],
|
||||
"categories": [
|
||||
"energy"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>IntegrationPluginWattsonic</name>
|
||||
<message>
|
||||
<location filename="../integrationpluginwattsonic.cpp" line="140"/>
|
||||
<source>The Modbus address not valid. It must be a value between 1 and 247.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginwattsonic.cpp" line="147"/>
|
||||
<source>The Modbus RTU resource is not available.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Wattsonic</name>
|
||||
<message>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="33"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the StateType ({c0f77c00-b82a-478e-826b-bc3204d66100}) of ThingClass inverter</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="36"/>
|
||||
<source>Current power consumption</source>
|
||||
<extracomment>The name of the StateType ({3107958e-07a2-4ebd-83a1-96fb5998cfb9}) of ThingClass inverter</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="39"/>
|
||||
<source>Modbus RTU master</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: inverter, Type: thing, ID: {4f1238b5-07e0-4516-b84a-71670141ef81})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="42"/>
|
||||
<source>Modbus slave address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: inverter, Type: thing, ID: {55a7d9ed-5f4f-41a2-8dc1-c6a5a79512d2})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="45"/>
|
||||
<source>Total energy produced</source>
|
||||
<extracomment>The name of the StateType ({2cbb25e6-c1bd-4216-b354-6ad6fa957e29}) of ThingClass inverter</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="48"/>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="51"/>
|
||||
<source>Wattsonic</source>
|
||||
<extracomment>The name of the vendor ({c335f9bc-3bc9-46bf-8c50-800cd93e827a})
|
||||
----------
|
||||
The name of the plugin Wattsonic ({d0eaf684-001e-4b1c-9e37-122955958de3})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/wattsonic/plugininfo.h" line="54"/>
|
||||
<source>Wattsonic hybrid inverter</source>
|
||||
<extracomment>The name of the ThingClass ({688bef8d-2ba8-4eb3-b30e-16193eba02fb})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
362
wattsonic/wattsonic-registers.json
Normal file
362
wattsonic/wattsonic-registers.json
Normal file
@ -0,0 +1,362 @@
|
||||
{
|
||||
"className": "Wattsonic",
|
||||
"protocol": "RTU",
|
||||
"endianness": "BigEndian",
|
||||
"errorLimitUntilNotReachable": 20,
|
||||
"checkReachableRegister": "serialNumber",
|
||||
"enums": [
|
||||
{
|
||||
"name": "InverterStatus",
|
||||
"values": [
|
||||
{
|
||||
"key": "Wait",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"key": "Check",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"key": "OnGrid",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"key": "Fault",
|
||||
"value": 3
|
||||
},
|
||||
{
|
||||
"key": "Flash",
|
||||
"value": 4
|
||||
},
|
||||
{
|
||||
"key": "OffGrid",
|
||||
"value": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "BatteryMode",
|
||||
"values": [
|
||||
{
|
||||
"key": "Discharge",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"key": "Charge",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"blocks": [
|
||||
],
|
||||
"registers": [
|
||||
{
|
||||
"id": "serialNumber",
|
||||
"address": 10000,
|
||||
"size": 8,
|
||||
"type": "string",
|
||||
"readSchedule": "init",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Serial number",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "firmwareVersion",
|
||||
"address": 10011,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"readSchedule": "init",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Firmware version",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "inverterStatus",
|
||||
"address": 10105,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Inverter status",
|
||||
"enum": "InverterStatus",
|
||||
"defaultValue": "InverterStatusWait",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "phaseAPower",
|
||||
"address": 10994,
|
||||
"size": 2,
|
||||
"type": "int32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Phase A power",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/1000 kW",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "phaseBPower",
|
||||
"address": 10996,
|
||||
"size": 2,
|
||||
"type": "int32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Phase B power",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/1000 kW",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "phaseCPower",
|
||||
"address": 10998,
|
||||
"size": 2,
|
||||
"type": "int32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Phase C power",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/1000 kW",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalPowerOnMeter",
|
||||
"address": 11000,
|
||||
"size": 2,
|
||||
"type": "int32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Total power on meter",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/1000 kW",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalGridInjectionEnergy",
|
||||
"address": 11002,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Total grid injection energy on meter",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/100 kWh",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalPurchasingEnergyFromGrid",
|
||||
"address": 11004,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Total purchasing energy from grid on meter",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/100 kWh",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "gridPhaseAVoltage",
|
||||
"address": 11009,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Grid Phase A Voltage",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 V",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "gridPhaseACurrent",
|
||||
"address": 11010,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Grid Phase A Current",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 A",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "gridPhaseBVoltage",
|
||||
"address": 11011,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Grid Phase B Voltage",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 V",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "gridPhaseBCurrent",
|
||||
"address": 11012,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Grid Phase B Current",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 A",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "gridPhaseCVoltage",
|
||||
"address": 11013,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Grid Phase C Voltage",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 V",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "gridPhaseCCurrent",
|
||||
"address": 11014,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Grid Phase C Current",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 A",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "pAC",
|
||||
"address": 11016,
|
||||
"size": 2,
|
||||
"type": "int32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "P_AC",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/1000 kW",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalPVGenerationFromInstallation",
|
||||
"address": 11020,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Total PV Generation from installation",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 kWh",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "pvInputTotalPower",
|
||||
"address": 11028,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "PV Total Input Power",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/1000 kW",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalBackupP",
|
||||
"address": 30230,
|
||||
"size": 2,
|
||||
"type": "int32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Total_Backup_P/AC Active Power",
|
||||
"unit": "1/1000 kW",
|
||||
"defaultValue": 0,
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "batteryMode",
|
||||
"address": 30256,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Battery mode",
|
||||
"enum": "BatteryMode",
|
||||
"defaultValue": "BatteryModeDischarge",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "batteryPower",
|
||||
"address": 30258,
|
||||
"size": 2,
|
||||
"type": "int32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Battery power",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/1000 kW",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalEnergyInjectedToGrid",
|
||||
"address": 31102,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Total energy injected to grid",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 kWh",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalEnergyPurchasedFromGrid",
|
||||
"address": 31104,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Total energy purchased from grid",
|
||||
"defaultValue": 0,
|
||||
"unit": "1/10 kWh",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "batteryStrings",
|
||||
"address": 32001,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "Battery strings",
|
||||
"defaultValue": 0,
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "SOC",
|
||||
"address": 33000,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "SOC",
|
||||
"defaultValue": 0,
|
||||
"unit": "% * 100",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "SOH",
|
||||
"address": 33001,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"registerType": "holdingRegister",
|
||||
"description": "SOH",
|
||||
"defaultValue": 0,
|
||||
"unit": "% * 100",
|
||||
"access": "RO"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
wattsonic/wattsonic.pro
Normal file
15
wattsonic/wattsonic.pro
Normal file
@ -0,0 +1,15 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
# Generate modbus connection
|
||||
MODBUS_CONNECTIONS += wattsonic-registers.json
|
||||
|
||||
#MODBUS_TOOLS_CONFIG += VERBOSE
|
||||
include(../modbus.pri)
|
||||
|
||||
HEADERS += \
|
||||
wattsonicdiscovery.h \
|
||||
integrationpluginwattsonic.h
|
||||
|
||||
SOURCES += \
|
||||
wattsonicdiscovery.cpp \
|
||||
integrationpluginwattsonic.cpp
|
||||
100
wattsonic/wattsonicdiscovery.cpp
Normal file
100
wattsonic/wattsonicdiscovery.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "wattsonicdiscovery.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <modbusdatautils.h>
|
||||
|
||||
QList<int> slaveIdCandidates = {247};
|
||||
|
||||
WattsonicDiscovery::WattsonicDiscovery(ModbusRtuHardwareResource *modbusRtuResource, QObject *parent):
|
||||
QObject{parent},
|
||||
m_modbusRtuResource(modbusRtuResource)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void WattsonicDiscovery::startDiscovery()
|
||||
{
|
||||
qCInfo(dcWattsonic()) << "Discovery: Searching for Wattsonic device on modbus RTU...";
|
||||
|
||||
QList<ModbusRtuMaster*> candidateMasters;
|
||||
foreach (ModbusRtuMaster *master, m_modbusRtuResource->modbusRtuMasters()) {
|
||||
if (master->baudrate() == 9600 && master->dataBits() == 8 && master->stopBits() == 1 && master->parity() == QSerialPort::NoParity) {
|
||||
candidateMasters.append(master);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidateMasters.isEmpty()) {
|
||||
qCWarning(dcWattsonic()) << "No usable modbus RTU master found.";
|
||||
emit discoveryFinished(false);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ModbusRtuMaster *master, candidateMasters) {
|
||||
if (master->connected()) {
|
||||
tryConnect(master, 0);
|
||||
} else {
|
||||
qCWarning(dcWattsonic()) << "Modbus RTU master" << master->modbusUuid().toString() << "is not connected.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<WattsonicDiscovery::Result> WattsonicDiscovery::discoveryResults() const
|
||||
{
|
||||
return m_discoveryResults;
|
||||
}
|
||||
|
||||
void WattsonicDiscovery::tryConnect(ModbusRtuMaster *master, quint16 slaveIdIndex)
|
||||
{
|
||||
quint8 slaveId = slaveIdCandidates.at(slaveIdIndex);
|
||||
qCDebug(dcWattsonic()) << "Scanning modbus RTU master" << master->modbusUuid() << "Slave ID:" << slaveId;
|
||||
|
||||
ModbusRtuReply *reply = master->readHoldingRegister(slaveId, 10000, 8);
|
||||
connect(reply, &ModbusRtuReply::finished, this, [=](){
|
||||
|
||||
if (reply->error() == ModbusRtuReply::NoError) {
|
||||
|
||||
QString serialNumber = ModbusDataUtils::convertToString(reply->result(), ModbusDataUtils::ByteOrderBigEndian);
|
||||
qCDebug(dcWattsonic()) << "Test reply finished!" << reply->error() << reply->result() << serialNumber;
|
||||
|
||||
Result result {master->modbusUuid(), serialNumber, slaveId};
|
||||
m_discoveryResults.append(result);
|
||||
|
||||
}
|
||||
|
||||
if (slaveIdIndex < slaveIdCandidates.count() - 1) {
|
||||
tryConnect(master, slaveIdIndex+1);
|
||||
} else {
|
||||
emit discoveryFinished(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
65
wattsonic/wattsonicdiscovery.h
Normal file
65
wattsonic/wattsonicdiscovery.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef WATTSONICDISCOVERY_H
|
||||
#define WATTSONICDISCOVERY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <hardware/modbus/modbusrtuhardwareresource.h>
|
||||
|
||||
class WattsonicDiscovery : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WattsonicDiscovery(ModbusRtuHardwareResource *modbusRtuResource, QObject *parent = nullptr);
|
||||
|
||||
struct Result {
|
||||
QUuid modbusRtuMasterId;
|
||||
QString serialNumber;
|
||||
quint16 slaveId;
|
||||
};
|
||||
|
||||
void startDiscovery();
|
||||
|
||||
QList<Result> discoveryResults() const;
|
||||
|
||||
signals:
|
||||
void discoveryFinished(bool modbusRtuMasterAvailable);
|
||||
|
||||
private slots:
|
||||
void tryConnect(ModbusRtuMaster *master, quint16 slaveIdIndex);
|
||||
|
||||
private:
|
||||
ModbusRtuHardwareResource *m_modbusRtuResource = nullptr;
|
||||
|
||||
QList<Result> m_discoveryResults;
|
||||
};
|
||||
|
||||
#endif // WATTSONICDISCOVERY_H
|
||||
Reference in New Issue
Block a user