Merge PR #49: Packaging: Split translations and consolidate package descriptions

This commit is contained in:
Jenkins nymea 2022-03-23 13:25:34 +01:00
commit a3dc920a30
27 changed files with 2696 additions and 129 deletions

1
debian/changelog vendored
View File

@ -1,3 +1,4 @@
nymea-plugins-modbus (0.30.0) xenial; urgency=medium
[ Michael Zanetti ]

167
debian/control vendored
View File

@ -1,7 +1,7 @@
Source: nymea-plugins-modbus
Section: utils
Priority: options
Maintainer: Bernhard Trinnes <bernhard.trinnes@nymea.io>
Maintainer: nymea GmbH <developer@nymea.io>
Build-depends: debhelper (>= 9.0.0),
libnymea-dev (>= 0.17),
libnymea-gpio-dev,
@ -20,13 +20,7 @@ Section: libs
Depends: ${shlibs:Depends},
${misc:Depends}
Description: nymea.io sunspec library
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io sunspec library
This package contains the nymea sunspec library.
Package: libnymea-sunspec-dev
Section: libdevel
@ -38,28 +32,15 @@ Depends: ${shlibs:Depends},
pkg-config,
qtbase5-dev,
Description: The main libraries and header files for developing with nymea sunspec.
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the development files for nymea sunspec.
This package contains the nymea sunspec library - development files.
Package: nymea-plugin-alphainnotec
Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for alpha innotec heat pumps
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for alpha innotec heat pumps
Description: nymea integration plugin for alpha innotec heat pumps
This package contains the nymea integration plugin for alpha innotec head pumps.
Package: nymea-plugin-drexelundweiss
@ -67,15 +48,8 @@ Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for Drexel & Weiss heat pumps
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for Drexel & Weiss heat pumps
Description: nymea integration plugin for Drexel & Weiss heat pumps
This package contains the nymea integration plugin for Drexel & Weiss heat pumps.
Package: nymea-plugin-idm
@ -83,15 +57,8 @@ Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations,
Description: nymea.io plugin for iDM heat pumps
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for iDM heat pumps
Description: nymea integration plugin for iDM heat pumps
This package contains the nymea integration plugin for iDM heat pumps.
Package: nymea-plugin-energymeters
@ -100,15 +67,19 @@ Multi-Arch: same
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for Modbus based energy meters
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for energy meters
Description: nymea integration plugin for Modbus based energy meters
This package contains a collection of energy meters.
Package: nymea-plugin-huawei
Architecture: any
Multi-Arch: same
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends}
Description: nymea integration plugin for Huawei FusionSolar energy devices
This package contains the nymea integration plugin for Huawei FusionSolar devices
based on Modbus TCP.
Package: nymea-plugin-modbuscommander
@ -116,15 +87,9 @@ Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin to send and receive generic modbus commands
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io modbus commander plug-in
Description: nymea integration plugin to send and receive generic modbus commands
This package contains a nymea integration plugin which allows to send and receive
generic Modbus commands to/from a Modbus device.
Package: nymea-plugin-mypv
@ -132,15 +97,8 @@ Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for my-pv heating rods
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for my-pv
Description: nymea integration plugin for my-pv heating rods
This package contains the nymea integration plugin for my-pv solar inverters.
Package: nymea-plugin-mtec
@ -148,30 +106,16 @@ Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for M-TEC heat pumps
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for M-TEC heat pumps
Description: nymea integration plugin for M-TEC heat pumps
This package contains the nymea integration plugin for M-TEC heat pumps.
Package: nymea-plugin-sunspec
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for SunSpec Modbus devices.
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for SunSpec.
Description: nymea integration plugin for SunSpec Modbus devices
This package contains the nymea integration plugin for SunSpec compatible solar inverters.
Package: nymea-plugin-unipi2
@ -181,16 +125,9 @@ Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
wiringpi,
nymea-plugins-modbus-translations
Replaces: nymea-plugin-unipi
Description: nymea.io plugin for UniPi devices
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for unipi devices
Description: nymea integration plugin for UniPi devices
This package contains the nymea integration plugin for UniPi devices.
Package: nymea-plugin-wallbe
@ -198,41 +135,15 @@ Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for wallbe ev charging stations
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for wallbe
Description: nymea integration plugin for Wallbe wallboxes
This package contains the nymea integration plugin for wallboxes made
by wallbe.
Package: nymea-plugin-webasto
Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
nymea-plugins-modbus-translations
Description: nymea.io plugin for Webasto Live EV charging stations
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the nymea.io plugin for webasto
Package: nymea-plugins-modbus-translations
Section: misc
Architecture: all
Depends: ${misc:Depends}
Description: Translation files for nymea modbus plugins - translations
The nymea daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package provides the translation files for all nymea modbus plugins.
Description: nymea integration plugin for Webasto Live wallboxes
This package contains the nymea integration plugin for wallboxes made
by Webasto.

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginalphainnotec.so
alphainnotec/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationplugindrexelundweiss.so
drexelundweiss/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginenergymeters.so
energymeters/translations/*qm usr/share/nymea/translations/

2
debian/nymea-plugin-huawei.install.in vendored Normal file
View File

@ -0,0 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginhuawei.so
huawei/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginidm.so
idm/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginmodbuscommander.so
modbuscommander/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginmypv.so
mypv/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginsunspec.so
sunspec/translations/*qm usr/share/nymea/translations/

View File

@ -1,2 +1,3 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginunipi.so
unipi/modbus_maps/* usr/share/nymea/modbus
unipi/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginwallbe.so
wallbe/translations/*qm usr/share/nymea/translations/

View File

@ -1 +1,2 @@
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginwebasto.so
webasto/translations/*qm usr/share/nymea/translations/

13
huawei/README.md Normal file
View File

@ -0,0 +1,13 @@
# Huawei FusionSolar
Connects to a Huawei FusionSolar using Modbus TCP.
## Supported things
* Inverter
* Meter (only current power)
* Battery (on Unit 1 and 2)
## More
https://solar.huawei.com/eu/

View File

@ -0,0 +1,277 @@
{
"protocol": "TCP",
"endianness": "BigEndian",
"enums": [
{
"name": "InverterDeviceStatus",
"values": [
{
"key": "StandbyInitializing",
"value": 0
},
{
"key": "StandbyDetectingInsulationResistance",
"value": 1
},
{
"key": "StandbyDetectingIrradiation",
"value": 2
},
{
"key": "StandbyDridDetecting",
"value": 3
},
{
"key": "Starting",
"value": 256
},
{
"key": "OnGrid",
"value": 512
},
{
"key": "PowerLimited",
"value": 513
},
{
"key": "SelfDerating",
"value": 514
},
{
"key": "ShutdownFault",
"value": 768
},
{
"key": "ShutdownCommand",
"value": 769
},
{
"key": "ShutdownOVGR",
"value": 770
},
{
"key": "ShutdownCommunicationDisconnected",
"value": 771
},
{
"key": "ShutdownPowerLimit",
"value": 772
},
{
"key": "ShutdownManualStartupRequired",
"value": 773
},
{
"key": "ShutdownInputUnderpower",
"value": 774
},
{
"key": "GridSchedulingPCurve",
"value": 1025
},
{
"key": "GridSchedulingQUCurve",
"value": 1026
},
{
"key": "GridSchedulingPFUCurve",
"value": 1027
},
{
"key": "GridSchedulingDryContact",
"value": 1028
},
{
"key": "GridSchedulingQPCurve",
"value": 1029
},
{
"key": "SpotCheckReady",
"value": 1280
},
{
"key": "SpotChecking",
"value": 1281
},
{
"key": "Inspecting",
"value": 1536
},
{
"key": "AfciSelfCheck",
"value": 1792
},
{
"key": "IVScanning",
"value": 2048
},
{
"key": "DCInputDetection",
"value": 2304
},
{
"key": "RunningOffGridCharging",
"value": 2560
},
{
"key": "StandbyNoIrradiation",
"value": 40960
}
]
},
{
"name": "BatteryDeviceStatus",
"values": [
{
"key": "Offline",
"value": 0
},
{
"key": "Standby",
"value": 1
},
{
"key": "Running",
"value": 1
},
{
"key": "Fault",
"value": 1
},
{
"key": "SleepMode",
"value": 1
}
]
}
],
"blocks": [
],
"registers": [
{
"id": "inverterActivePower",
"address": 32080,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Inverter active power",
"unit": "kW",
"staticScaleFactor": -3,
"defaultValue": "0",
"access": "RO"
},
{
"id": "inverterDeviceStatus",
"address": 32089,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Inverter device status",
"enum": "InverterDeviceStatus",
"defaultValue": "InverterDeviceStatusStandbyInitializing",
"access": "RO"
},
{
"id": "inverterEnergyProduced",
"address": 32106,
"size": 2,
"type": "uint32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Inverter energy produced",
"unit": "kWh",
"staticScaleFactor": -2,
"defaultValue": "0",
"access": "RO"
},
{
"id": "powerMeterActivePower",
"address": 37113,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Power meter active power",
"unit": "W",
"defaultValue": "0",
"access": "RO"
},
{
"id": "lunaBattery1Status",
"address": 37000,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Luna 2000 Battery 1 status",
"enum": "BatteryDeviceStatus",
"defaultValue": "BatteryDeviceStatusOffline",
"access": "RO"
},
{
"id": "lunaBattery1Power",
"address": 37001,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Luna 2000 Battery 1 power",
"unit": "W",
"defaultValue": "0",
"access": "RO"
},
{
"id": "lunaBattery1Soc",
"address": 37004,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Luna 2000 Battery 1 state of charge",
"staticScaleFactor": -1,
"unit": "%",
"defaultValue": "0",
"access": "RO"
},
{
"id": "lunaBattery2Status",
"address": 37741,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Luna 2000 Battery 2 status",
"enum": "BatteryDeviceStatus",
"defaultValue": "BatteryDeviceStatusOffline",
"access": "RO"
},
{
"id": "lunaBattery2Power",
"address": 37743,
"size": 2,
"type": "int32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Luna 2000 Battery 2 power",
"unit": "W",
"defaultValue": "0",
"access": "RO"
},
{
"id": "lunaBattery2Soc",
"address": 37738,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Luna 2000 Battery 2 state of charge",
"staticScaleFactor": -1,
"unit": "%",
"defaultValue": "0",
"access": "RO"
}
]
}

BIN
huawei/huawei.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

17
huawei/huawei.pro Normal file
View File

@ -0,0 +1,17 @@
include(../plugins.pri)
QT += network serialbus
HEADERS += \
huaweifusionsolar.h \
huaweimodbustcpconnection.h \
integrationpluginhuawei.h \
../modbus/modbustcpmaster.h \
../modbus/modbusdatautils.h
SOURCES += \
huaweifusionsolar.cpp \
huaweimodbustcpconnection.cpp \
integrationpluginhuawei.cpp \
../modbus/modbustcpmaster.cpp \
../modbus/modbusdatautils.cpp

View File

@ -0,0 +1,460 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This fileDescriptor 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 "huaweifusionsolar.h"
#include "extern-plugininfo.h"
#include "loggingcategories.h"
NYMEA_LOGGING_CATEGORY(dcHuaweiFusionSolar, "HuaweiFusionSolar")
HuaweiFusionSolar::HuaweiFusionSolar(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :
HuaweiModbusTcpConnection(hostAddress, port, slaveId, parent)
{
}
void HuaweiFusionSolar::initialize()
{
// No init registers defined. Nothing to be done and we are finished.
emit initializationFinished();
}
void HuaweiFusionSolar::update()
{
// Make sure there is not an update still running
if (!m_registersQueue.isEmpty())
return;
// Add the requests
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterInverterActivePower);
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterInverterDeviceStatus);
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterInverterEnergyProduced);
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterLunaBattery1Status);
if (m_battery1Available) {
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterLunaBattery1Power);
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterLunaBattery1Soc);
}
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterPowerMeterActivePower);
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterLunaBattery2Status);
if (m_battery2Available) {
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterLunaBattery2Power);
m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterLunaBattery2Soc);
}
// Note: since huawei can only process one request at the time, we need to queue the requests
m_currentRegisterRequest = -1;
readNextRegister();
}
void HuaweiFusionSolar::readNextRegister()
{
// Check if currently a reply is pending
if (m_currentRegisterRequest >= 0)
return;
// Check if there is still a register to read
if (m_registersQueue.isEmpty())
return;
m_currentRegisterRequest = m_registersQueue.dequeue();
switch (m_currentRegisterRequest) {
case HuaweiModbusTcpConnection::RegisterInverterActivePower: {
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Inverter active power\" register:" << 32080 << "size:" << 2;
QModbusReply *reply = readInverterActivePower();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter active power\" register" << 32080 << "size:" << 2 << values;
float receivedInverterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -3);
if (m_inverterActivePower != receivedInverterActivePower) {
m_inverterActivePower = receivedInverterActivePower;
emit inverterActivePowerChanged(m_inverterActivePower);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Inverter active power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Inverter active power\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterInverterDeviceStatus: {
// Update registers from Inverter device status
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Inverter device status\" register:" << 32089 << "size:" << 1;
QModbusReply *reply = readInverterDeviceStatus();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter device status\" register" << 32089 << "size:" << 1 << values;
InverterDeviceStatus receivedInverterDeviceStatus = static_cast<InverterDeviceStatus>(ModbusDataUtils::convertToUInt16(values));
qCDebug(dcHuaweiFusionSolar()) << "Inverter status" << receivedInverterDeviceStatus;
if (m_inverterDeviceStatus != receivedInverterDeviceStatus) {
m_inverterDeviceStatus = receivedInverterDeviceStatus;
emit inverterDeviceStatusChanged(m_inverterDeviceStatus);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Inverter device status\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Inverter device status\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterInverterEnergyProduced: {
// Update registers from Inverter energy produced
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Inverter energy produced\" register:" << 32106 << "size:" << 2;
QModbusReply *reply = readInverterEnergyProduced();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter energy produced\" register" << 32106 << "size:" << 2 << values;
float receivedInverterEnergyProduced = ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -2);
if (m_inverterEnergyProduced != receivedInverterEnergyProduced) {
m_inverterEnergyProduced = receivedInverterEnergyProduced;
emit inverterEnergyProducedChanged(m_inverterEnergyProduced);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Inverter energy produced\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Inverter energy produced\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterLunaBattery1Status: {
// Update registers from Luna 2000 Battery 1 status
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Luna 2000 Battery 1 status\" register:" << 37000 << "size:" << 1;
QModbusReply *reply = readLunaBattery1Status();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 status\" register" << 37000 << "size:" << 1 << values;
BatteryDeviceStatus receivedLunaBattery1Status = static_cast<BatteryDeviceStatus>(ModbusDataUtils::convertToUInt16(values));
qCDebug(dcHuaweiFusionSolar()) << "Battery 1 status" << receivedLunaBattery1Status;
if (receivedLunaBattery1Status == BatteryDeviceStatusOffline) {
m_battery1Available = false;
} else {
m_battery1Available = true;
}
if (m_lunaBattery1Status != receivedLunaBattery1Status) {
m_lunaBattery1Status = receivedLunaBattery1Status;
emit lunaBattery1StatusChanged(m_lunaBattery1Status);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 status\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Luna 2000 Battery 1 status\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterLunaBattery1Power: {
// Update registers from Luna 2000 Battery 1 power
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Luna 2000 Battery 1 power\" register:" << 37001 << "size:" << 2;
QModbusReply *reply = readLunaBattery1Power();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 power\" register" << 37001 << "size:" << 2 << values;
qint32 receivedLunaBattery1Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
if (m_lunaBattery1Power != receivedLunaBattery1Power) {
m_lunaBattery1Power = receivedLunaBattery1Power;
emit lunaBattery1PowerChanged(m_lunaBattery1Power);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Luna 2000 Battery 1 power\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterLunaBattery1Soc: {
// Update registers from Luna 2000 Battery 1 state of charge
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Luna 2000 Battery 1 state of charge\" register:" << 37004 << "size:" << 1;
QModbusReply *reply = readLunaBattery1Soc();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 state of charge\" register" << 37004 << "size:" << 1 << values;
float receivedLunaBattery1Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
if (m_lunaBattery1Soc != receivedLunaBattery1Soc) {
m_lunaBattery1Soc = receivedLunaBattery1Soc;
emit lunaBattery1SocChanged(m_lunaBattery1Soc);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 state of charge\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Luna 2000 Battery 1 state of charge\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterPowerMeterActivePower: {
// Update registers from Power meter active power
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Power meter active power\" register:" << 37113 << "size:" << 2;
QModbusReply *reply = readPowerMeterActivePower();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Power meter active power\" register" << 37113 << "size:" << 2 << values;
qint32 receivedPowerMeterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
if (m_powerMeterActivePower != receivedPowerMeterActivePower) {
m_powerMeterActivePower = receivedPowerMeterActivePower;
emit powerMeterActivePowerChanged(m_powerMeterActivePower);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Power meter active power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Power meter active power\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterLunaBattery2Status: {
// Update registers from Luna 2000 Battery 2 status
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Luna 2000 Battery 2 status\" register:" << 37741 << "size:" << 1;
QModbusReply *reply = readLunaBattery2Status();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 status\" register" << 37741 << "size:" << 1 << values;
BatteryDeviceStatus receivedLunaBattery2Status = static_cast<BatteryDeviceStatus>(ModbusDataUtils::convertToUInt16(values));
qCDebug(dcHuaweiFusionSolar()) << "Battery 2 status" << receivedLunaBattery2Status;
if (receivedLunaBattery2Status == BatteryDeviceStatusOffline) {
m_battery2Available = false;
} else {
m_battery2Available = true;
}
if (m_lunaBattery2Status != receivedLunaBattery2Status) {
m_lunaBattery2Status = receivedLunaBattery2Status;
emit lunaBattery2StatusChanged(m_lunaBattery2Status);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 status\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Luna 2000 Battery 2 status\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterLunaBattery2Power: {
// Update registers from Luna 2000 Battery 2 power
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Luna 2000 Battery 2 power\" register:" << 37743 << "size:" << 2;
QModbusReply *reply = readLunaBattery2Power();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 power\" register" << 37743 << "size:" << 2 << values;
qint32 receivedLunaBattery2Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
if (m_lunaBattery2Power != receivedLunaBattery2Power) {
m_lunaBattery2Power = receivedLunaBattery2Power;
emit lunaBattery2PowerChanged(m_lunaBattery2Power);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Luna 2000 Battery 2 power\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
case HuaweiModbusTcpConnection::RegisterLunaBattery2Soc: {
// Update registers from Luna 2000 Battery 2 state of charge
qCDebug(dcHuaweiFusionSolar()) << "--> Read \"Luna 2000 Battery 2 state of charge\" register:" << 37738 << "size:" << 1;
QModbusReply *reply = readLunaBattery2Soc();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 state of charge\" register" << 37738 << "size:" << 1 << values;
float receivedLunaBattery2Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
if (m_lunaBattery2Soc != receivedLunaBattery2Soc) {
m_lunaBattery2Soc = receivedLunaBattery2Soc;
emit lunaBattery2SocChanged(m_lunaBattery2Soc);
}
}
finishRequest();
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiFusionSolar()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 state of charge\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
finishRequest();
}
} else {
qCWarning(dcHuaweiFusionSolar()) << "Error occurred while reading \"Luna 2000 Battery 2 state of charge\" registers from" << hostAddress().toString() << errorString();
finishRequest();
}
break;
}
}
}
void HuaweiFusionSolar::finishRequest()
{
m_currentRegisterRequest = -1;
QTimer::singleShot(1000, this, &HuaweiFusionSolar::readNextRegister);
}

View File

@ -0,0 +1,63 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This fileDescriptor 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 HUAWEIFUSIONSOLAR_H
#define HUAWEIFUSIONSOLAR_H
#include <QObject>
#include <QQueue>
#include "huaweimodbustcpconnection.h"
class HuaweiFusionSolar : public HuaweiModbusTcpConnection
{
Q_OBJECT
public:
explicit HuaweiFusionSolar(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);
virtual void initialize() override;
virtual void update() override;
private:
QQueue<HuaweiModbusTcpConnection::Registers> m_registersQueue;
int m_currentRegisterRequest = -1;
void finishRequest();
bool m_battery1Available = true;
bool m_battery2Available = true;
private slots:
void readNextRegister();
};
#endif // HUAWEIFUSIONSOLAR_H

View File

@ -0,0 +1,523 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This fileDescriptor 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 "huaweimodbustcpconnection.h"
#include "loggingcategories.h"
NYMEA_LOGGING_CATEGORY(dcHuaweiModbusTcpConnection, "HuaweiModbusTcpConnection")
HuaweiModbusTcpConnection::HuaweiModbusTcpConnection(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :
ModbusTCPMaster(hostAddress, port, parent),
m_slaveId(slaveId)
{
}
float HuaweiModbusTcpConnection::inverterActivePower() const
{
return m_inverterActivePower;
}
HuaweiModbusTcpConnection::InverterDeviceStatus HuaweiModbusTcpConnection::inverterDeviceStatus() const
{
return m_inverterDeviceStatus;
}
float HuaweiModbusTcpConnection::inverterEnergyProduced() const
{
return m_inverterEnergyProduced;
}
qint32 HuaweiModbusTcpConnection::powerMeterActivePower() const
{
return m_powerMeterActivePower;
}
HuaweiModbusTcpConnection::BatteryDeviceStatus HuaweiModbusTcpConnection::lunaBattery1Status() const
{
return m_lunaBattery1Status;
}
qint32 HuaweiModbusTcpConnection::lunaBattery1Power() const
{
return m_lunaBattery1Power;
}
float HuaweiModbusTcpConnection::lunaBattery1Soc() const
{
return m_lunaBattery1Soc;
}
HuaweiModbusTcpConnection::BatteryDeviceStatus HuaweiModbusTcpConnection::lunaBattery2Status() const
{
return m_lunaBattery2Status;
}
qint32 HuaweiModbusTcpConnection::lunaBattery2Power() const
{
return m_lunaBattery2Power;
}
float HuaweiModbusTcpConnection::lunaBattery2Soc() const
{
return m_lunaBattery2Soc;
}
void HuaweiModbusTcpConnection::initialize()
{
// No init registers defined. Nothing to be done and we are finished.
emit initializationFinished();
}
void HuaweiModbusTcpConnection::update()
{
updateInverterActivePower();
updateInverterDeviceStatus();
updateInverterEnergyProduced();
updatePowerMeterActivePower();
updateLunaBattery1Status();
updateLunaBattery1Power();
updateLunaBattery1Soc();
updateLunaBattery2Status();
updateLunaBattery2Power();
updateLunaBattery2Soc();
}
void HuaweiModbusTcpConnection::updateInverterActivePower()
{
// Update registers from Inverter active power
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Inverter active power\" register:" << 32080 << "size:" << 2;
QModbusReply *reply = readInverterActivePower();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Inverter active power\" register" << 32080 << "size:" << 2 << values;
float receivedInverterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -3);
if (m_inverterActivePower != receivedInverterActivePower) {
m_inverterActivePower = receivedInverterActivePower;
emit inverterActivePowerChanged(m_inverterActivePower);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Inverter active power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Inverter active power\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateInverterDeviceStatus()
{
// Update registers from Inverter device status
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Inverter device status\" register:" << 32089 << "size:" << 1;
QModbusReply *reply = readInverterDeviceStatus();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Inverter device status\" register" << 32089 << "size:" << 1 << values;
InverterDeviceStatus receivedInverterDeviceStatus = static_cast<InverterDeviceStatus>(ModbusDataUtils::convertToUInt16(values));
if (m_inverterDeviceStatus != receivedInverterDeviceStatus) {
m_inverterDeviceStatus = receivedInverterDeviceStatus;
emit inverterDeviceStatusChanged(m_inverterDeviceStatus);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Inverter device status\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Inverter device status\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateInverterEnergyProduced()
{
// Update registers from Inverter energy produced
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Inverter energy produced\" register:" << 32106 << "size:" << 2;
QModbusReply *reply = readInverterEnergyProduced();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Inverter energy produced\" register" << 32106 << "size:" << 2 << values;
float receivedInverterEnergyProduced = ModbusDataUtils::convertToUInt32(values, ModbusDataUtils::ByteOrderBigEndian) * 1.0 * pow(10, -2);
if (m_inverterEnergyProduced != receivedInverterEnergyProduced) {
m_inverterEnergyProduced = receivedInverterEnergyProduced;
emit inverterEnergyProducedChanged(m_inverterEnergyProduced);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Inverter energy produced\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Inverter energy produced\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updatePowerMeterActivePower()
{
// Update registers from Power meter active power
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Power meter active power\" register:" << 37113 << "size:" << 2;
QModbusReply *reply = readPowerMeterActivePower();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Power meter active power\" register" << 37113 << "size:" << 2 << values;
qint32 receivedPowerMeterActivePower = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
if (m_powerMeterActivePower != receivedPowerMeterActivePower) {
m_powerMeterActivePower = receivedPowerMeterActivePower;
emit powerMeterActivePowerChanged(m_powerMeterActivePower);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Power meter active power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Power meter active power\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateLunaBattery1Status()
{
// Update registers from Luna 2000 Battery 1 status
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 1 status\" register:" << 37000 << "size:" << 1;
QModbusReply *reply = readLunaBattery1Status();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 1 status\" register" << 37000 << "size:" << 1 << values;
BatteryDeviceStatus receivedLunaBattery1Status = static_cast<BatteryDeviceStatus>(ModbusDataUtils::convertToUInt16(values));
m_lunaBattery1Status = receivedLunaBattery1Status;
emit lunaBattery1StatusChanged(m_lunaBattery1Status);
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 status\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 1 status\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateLunaBattery1Power()
{
// Update registers from Luna 2000 Battery 1 power
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 1 power\" register:" << 37001 << "size:" << 2;
QModbusReply *reply = readLunaBattery1Power();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 1 power\" register" << 37001 << "size:" << 2 << values;
qint32 receivedLunaBattery1Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
if (m_lunaBattery1Power != receivedLunaBattery1Power) {
m_lunaBattery1Power = receivedLunaBattery1Power;
emit lunaBattery1PowerChanged(m_lunaBattery1Power);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 1 power\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateLunaBattery1Soc()
{
// Update registers from Luna 2000 Battery 1 state of charge
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 1 state of charge\" register:" << 37004 << "size:" << 1;
QModbusReply *reply = readLunaBattery1Soc();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 1 state of charge\" register" << 37004 << "size:" << 1 << values;
float receivedLunaBattery1Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
if (m_lunaBattery1Soc != receivedLunaBattery1Soc) {
m_lunaBattery1Soc = receivedLunaBattery1Soc;
emit lunaBattery1SocChanged(m_lunaBattery1Soc);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 1 state of charge\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 1 state of charge\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateLunaBattery2Status()
{
// Update registers from Luna 2000 Battery 2 status
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 2 status\" register:" << 37741 << "size:" << 1;
QModbusReply *reply = readLunaBattery2Status();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 2 status\" register" << 37741 << "size:" << 1 << values;
BatteryDeviceStatus receivedLunaBattery2Status = static_cast<BatteryDeviceStatus>(ModbusDataUtils::convertToUInt16(values));
m_lunaBattery2Status = receivedLunaBattery2Status;
emit lunaBattery2StatusChanged(m_lunaBattery2Status);
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 status\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 2 status\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateLunaBattery2Power()
{
// Update registers from Luna 2000 Battery 2 power
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 2 power\" register:" << 37743 << "size:" << 2;
QModbusReply *reply = readLunaBattery2Power();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 2 power\" register" << 37743 << "size:" << 2 << values;
qint32 receivedLunaBattery2Power = ModbusDataUtils::convertToInt32(values, ModbusDataUtils::ByteOrderBigEndian);
if (m_lunaBattery2Power != receivedLunaBattery2Power) {
m_lunaBattery2Power = receivedLunaBattery2Power;
emit lunaBattery2PowerChanged(m_lunaBattery2Power);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 power\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 2 power\" registers from" << hostAddress().toString() << errorString();
}
}
void HuaweiModbusTcpConnection::updateLunaBattery2Soc()
{
// Update registers from Luna 2000 Battery 2 state of charge
qCDebug(dcHuaweiModbusTcpConnection()) << "--> Read \"Luna 2000 Battery 2 state of charge\" register:" << 37738 << "size:" << 1;
QModbusReply *reply = readLunaBattery2Soc();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
connect(reply, &QModbusReply::finished, this, [this, reply](){
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
const QVector<quint16> values = unit.values();
qCDebug(dcHuaweiModbusTcpConnection()) << "<-- Response from \"Luna 2000 Battery 2 state of charge\" register" << 37738 << "size:" << 1 << values;
float receivedLunaBattery2Soc = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -1);
if (m_lunaBattery2Soc != receivedLunaBattery2Soc) {
m_lunaBattery2Soc = receivedLunaBattery2Soc;
emit lunaBattery2SocChanged(m_lunaBattery2Soc);
}
}
});
connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){
qCWarning(dcHuaweiModbusTcpConnection()) << "Modbus reply error occurred while updating \"Luna 2000 Battery 2 state of charge\" registers from" << hostAddress().toString() << error << reply->errorString();
emit reply->finished(); // To make sure it will be deleted
});
} else {
delete reply; // Broadcast reply returns immediatly
}
} else {
qCWarning(dcHuaweiModbusTcpConnection()) << "Error occurred while reading \"Luna 2000 Battery 2 state of charge\" registers from" << hostAddress().toString() << errorString();
}
}
QModbusReply *HuaweiModbusTcpConnection::readInverterActivePower()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 32080, 2);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readInverterDeviceStatus()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 32089, 1);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readInverterEnergyProduced()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 32106, 2);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readPowerMeterActivePower()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37113, 2);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readLunaBattery1Status()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37000, 1);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readLunaBattery1Power()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37001, 2);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readLunaBattery1Soc()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37004, 1);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readLunaBattery2Status()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37741, 1);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readLunaBattery2Power()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37743, 2);
return sendReadRequest(request, m_slaveId);
}
QModbusReply *HuaweiModbusTcpConnection::readLunaBattery2Soc()
{
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, 37738, 1);
return sendReadRequest(request, m_slaveId);
}
void HuaweiModbusTcpConnection::verifyInitFinished()
{
if (m_pendingInitReplies.isEmpty()) {
qCDebug(dcHuaweiModbusTcpConnection()) << "Initialization finished of HuaweiModbusTcpConnection" << hostAddress().toString();
emit initializationFinished();
}
}
QDebug operator<<(QDebug debug, HuaweiModbusTcpConnection *huaweiModbusTcpConnection)
{
debug.nospace().noquote() << "HuaweiModbusTcpConnection(" << huaweiModbusTcpConnection->hostAddress().toString() << ":" << huaweiModbusTcpConnection->port() << ")" << "\n";
debug.nospace().noquote() << " - Inverter active power:" << huaweiModbusTcpConnection->inverterActivePower() << " [kW]" << "\n";
debug.nospace().noquote() << " - Inverter device status:" << huaweiModbusTcpConnection->inverterDeviceStatus() << "\n";
debug.nospace().noquote() << " - Inverter energy produced:" << huaweiModbusTcpConnection->inverterEnergyProduced() << " [kWh]" << "\n";
debug.nospace().noquote() << " - Power meter active power:" << huaweiModbusTcpConnection->powerMeterActivePower() << " [W]" << "\n";
debug.nospace().noquote() << " - Luna 2000 Battery 1 status:" << huaweiModbusTcpConnection->lunaBattery1Status() << "\n";
debug.nospace().noquote() << " - Luna 2000 Battery 1 power:" << huaweiModbusTcpConnection->lunaBattery1Power() << " [W]" << "\n";
debug.nospace().noquote() << " - Luna 2000 Battery 1 state of charge:" << huaweiModbusTcpConnection->lunaBattery1Soc() << " [%]" << "\n";
debug.nospace().noquote() << " - Luna 2000 Battery 2 status:" << huaweiModbusTcpConnection->lunaBattery2Status() << "\n";
debug.nospace().noquote() << " - Luna 2000 Battery 2 power:" << huaweiModbusTcpConnection->lunaBattery2Power() << " [W]" << "\n";
debug.nospace().noquote() << " - Luna 2000 Battery 2 state of charge:" << huaweiModbusTcpConnection->lunaBattery2Soc() << " [%]" << "\n";
return debug.quote().space();
}

View File

@ -0,0 +1,194 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This fileDescriptor 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 HUAWEIMODBUSTCPCONNECTION_H
#define HUAWEIMODBUSTCPCONNECTION_H
#include <QObject>
#include "../modbus/modbusdatautils.h"
#include "../modbus/modbustcpmaster.h"
class HuaweiModbusTcpConnection : public ModbusTCPMaster
{
Q_OBJECT
public:
enum Registers {
RegisterInverterActivePower = 32080,
RegisterInverterDeviceStatus = 32089,
RegisterInverterEnergyProduced = 32106,
RegisterLunaBattery1Status = 37000,
RegisterLunaBattery1Power = 37001,
RegisterLunaBattery1Soc = 37004,
RegisterPowerMeterActivePower = 37113,
RegisterLunaBattery2Soc = 37738,
RegisterLunaBattery2Status = 37741,
RegisterLunaBattery2Power = 37743
};
Q_ENUM(Registers)
enum InverterDeviceStatus {
InverterDeviceStatusStandbyInitializing = 0,
InverterDeviceStatusStandbyDetectingInsulationResistance = 1,
InverterDeviceStatusStandbyDetectingIrradiation = 2,
InverterDeviceStatusStandbyDridDetecting = 3,
InverterDeviceStatusStarting = 256,
InverterDeviceStatusOnGrid = 512,
InverterDeviceStatusPowerLimited = 513,
InverterDeviceStatusSelfDerating = 514,
InverterDeviceStatusShutdownFault = 768,
InverterDeviceStatusShutdownCommand = 769,
InverterDeviceStatusShutdownOVGR = 770,
InverterDeviceStatusShutdownCommunicationDisconnected = 771,
InverterDeviceStatusShutdownPowerLimit = 772,
InverterDeviceStatusShutdownManualStartupRequired = 773,
InverterDeviceStatusShutdownInputUnderpower = 774,
InverterDeviceStatusGridSchedulingPCurve = 1025,
InverterDeviceStatusGridSchedulingQUCurve = 1026,
InverterDeviceStatusGridSchedulingPFUCurve = 1027,
InverterDeviceStatusGridSchedulingDryContact = 1028,
InverterDeviceStatusGridSchedulingQPCurve = 1029,
InverterDeviceStatusSpotCheckReady = 1280,
InverterDeviceStatusSpotChecking = 1281,
InverterDeviceStatusInspecting = 1536,
InverterDeviceStatusAfciSelfCheck = 1792,
InverterDeviceStatusIVScanning = 2048,
InverterDeviceStatusDCInputDetection = 2304,
InverterDeviceStatusRunningOffGridCharging = 2560,
InverterDeviceStatusStandbyNoIrradiation = 40960
};
Q_ENUM(InverterDeviceStatus)
enum BatteryDeviceStatus {
BatteryDeviceStatusOffline = 0,
BatteryDeviceStatusStandby = 1,
BatteryDeviceStatusRunning = 1,
BatteryDeviceStatusFault = 1,
BatteryDeviceStatusSleepMode = 1
};
Q_ENUM(BatteryDeviceStatus)
explicit HuaweiModbusTcpConnection(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);
~HuaweiModbusTcpConnection() = default;
/* Inverter active power [kW] - Address: 32080, Size: 2 */
float inverterActivePower() const;
/* Inverter device status - Address: 32089, Size: 1 */
InverterDeviceStatus inverterDeviceStatus() const;
/* Inverter energy produced [kWh] - Address: 32106, Size: 2 */
float inverterEnergyProduced() const;
/* Power meter active power [W] - Address: 37113, Size: 2 */
qint32 powerMeterActivePower() const;
/* Luna 2000 Battery 1 status - Address: 37000, Size: 1 */
BatteryDeviceStatus lunaBattery1Status() const;
/* Luna 2000 Battery 1 power [W] - Address: 37001, Size: 2 */
qint32 lunaBattery1Power() const;
/* Luna 2000 Battery 1 state of charge [%] - Address: 37004, Size: 1 */
float lunaBattery1Soc() const;
/* Luna 2000 Battery 2 status - Address: 37741, Size: 1 */
BatteryDeviceStatus lunaBattery2Status() const;
/* Luna 2000 Battery 2 power [W] - Address: 37743, Size: 2 */
qint32 lunaBattery2Power() const;
/* Luna 2000 Battery 2 state of charge [%] - Address: 37738, Size: 1 */
float lunaBattery2Soc() const;
virtual void initialize();
virtual void update();
void updateInverterActivePower();
void updateInverterDeviceStatus();
void updateInverterEnergyProduced();
void updatePowerMeterActivePower();
void updateLunaBattery1Status();
void updateLunaBattery1Power();
void updateLunaBattery1Soc();
void updateLunaBattery2Status();
void updateLunaBattery2Power();
void updateLunaBattery2Soc();
signals:
void initializationFinished();
void inverterActivePowerChanged(float inverterActivePower);
void inverterDeviceStatusChanged(InverterDeviceStatus inverterDeviceStatus);
void inverterEnergyProducedChanged(float inverterEnergyProduced);
void powerMeterActivePowerChanged(qint32 powerMeterActivePower);
void lunaBattery1StatusChanged(BatteryDeviceStatus lunaBattery1Status);
void lunaBattery1PowerChanged(qint32 lunaBattery1Power);
void lunaBattery1SocChanged(float lunaBattery1Soc);
void lunaBattery2StatusChanged(BatteryDeviceStatus lunaBattery2Status);
void lunaBattery2PowerChanged(qint32 lunaBattery2Power);
void lunaBattery2SocChanged(float lunaBattery2Soc);
protected:
QModbusReply *readInverterActivePower();
QModbusReply *readInverterDeviceStatus();
QModbusReply *readInverterEnergyProduced();
QModbusReply *readPowerMeterActivePower();
QModbusReply *readLunaBattery1Status();
QModbusReply *readLunaBattery1Power();
QModbusReply *readLunaBattery1Soc();
QModbusReply *readLunaBattery2Status();
QModbusReply *readLunaBattery2Power();
QModbusReply *readLunaBattery2Soc();
float m_inverterActivePower = 0;
InverterDeviceStatus m_inverterDeviceStatus = InverterDeviceStatusStandbyInitializing;
float m_inverterEnergyProduced = 0;
qint32 m_powerMeterActivePower = 0;
BatteryDeviceStatus m_lunaBattery1Status = BatteryDeviceStatusOffline;
qint32 m_lunaBattery1Power = 0;
float m_lunaBattery1Soc = 0;
BatteryDeviceStatus m_lunaBattery2Status = BatteryDeviceStatusOffline;
qint32 m_lunaBattery2Power = 0;
float m_lunaBattery2Soc = 0;
private:
quint16 m_slaveId = 1;
QVector<QModbusReply *> m_pendingInitReplies;
void verifyInitFinished();
};
QDebug operator<<(QDebug debug, HuaweiModbusTcpConnection *huaweiModbusTcpConnection);
#endif // HUAWEIMODBUSTCPCONNECTION_H

View File

@ -0,0 +1,322 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This fileDescriptor 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 "integrationpluginhuawei.h"
#include "network/networkdevicediscovery.h"
#include "hardwaremanager.h"
#include "plugininfo.h"
IntegrationPluginHuawei::IntegrationPluginHuawei()
{
}
void IntegrationPluginHuawei::discoverThings(ThingDiscoveryInfo *info)
{
if (!hardwareManager()->networkDeviceDiscovery()->available()) {
qCWarning(dcHuawei()) << "The network discovery is not available on this platform.";
info->finish(Thing::ThingErrorUnsupportedFeature, QT_TR_NOOP("The network device discovery is not available."));
return;
}
NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
foreach (const NetworkDeviceInfo &networkDeviceInfo, discoveryReply->networkDeviceInfos()) {
qCDebug(dcHuawei()) << "Found" << networkDeviceInfo;
// Filter for mac manufacturer
if (!networkDeviceInfo.macAddressManufacturer().contains("Huawei"))
continue;
QString title;
if (networkDeviceInfo.hostName().isEmpty()) {
title = "Huawei FusionSolar";
} else {
title = networkDeviceInfo.hostName() + " (" + networkDeviceInfo.address().toString() + ")";
}
QString description;
if (networkDeviceInfo.macAddressManufacturer().isEmpty()) {
description = networkDeviceInfo.macAddress();
} else {
description = networkDeviceInfo.macAddress() + " (" + networkDeviceInfo.macAddressManufacturer() + ")";
}
ThingDescriptor descriptor(huaweiInverterThingClassId, title, description);
ParamList params;
params << Param(huaweiInverterThingIpAddressParamTypeId, networkDeviceInfo.address().toString());
params << Param(huaweiInverterThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
descriptor.setParams(params);
// Check if we already have set up this device
Things existingThings = myThings().filterByParam(huaweiInverterThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
if (existingThings.count() == 1) {
qCDebug(dcHuawei()) << "This connection already exists in the system:" << networkDeviceInfo;
descriptor.setThingId(existingThings.first()->id());
}
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
});
}
void IntegrationPluginHuawei::startMonitoringAutoThings()
{
}
void IntegrationPluginHuawei::setupThing(ThingSetupInfo *info)
{
Thing *thing = info->thing();
qCDebug(dcHuawei()) << "Setup" << thing << thing->params();
if (thing->thingClassId() == huaweiInverterThingClassId) {
QHostAddress hostAddress = QHostAddress(thing->paramValue(huaweiInverterThingIpAddressParamTypeId).toString());
if (hostAddress.isNull()) {
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("No IP address given"));
return;
}
uint port = thing->paramValue(huaweiInverterThingPortParamTypeId).toUInt();
quint16 slaveId = thing->paramValue(huaweiInverterThingSlaveIdParamTypeId).toUInt();
HuaweiFusionSolar *connection = new HuaweiFusionSolar(hostAddress, port, slaveId, this);
connect(connection, &HuaweiFusionSolar::connectionStateChanged, this, [this, thing, connection](bool status){
qCDebug(dcHuawei()) << "Connected changed to" << status << "for" << thing;
if (status) {
// Connected true will be set after successfull init
connection->initialize();
thing->setStateValue(huaweiInverterConnectedStateTypeId, true);
} else {
thing->setStateValue(huaweiInverterConnectedStateTypeId, false);
}
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
childThing->setStateValue("connected", status);
}
});
connect(connection, &HuaweiFusionSolar::inverterActivePowerChanged, this, [thing](float inverterActivePower){
qCDebug(dcHuawei()) << "Inverter power changed" << inverterActivePower * -1000.0 << "W";
thing->setStateValue(huaweiInverterCurrentPowerStateTypeId, inverterActivePower * -1000.0);
});
connect(connection, &HuaweiFusionSolar::inverterDeviceStatusChanged, this, [thing](HuaweiFusionSolar::InverterDeviceStatus inverterDeviceStatus){
qCDebug(dcHuawei()) << "Inverter device status changed" << inverterDeviceStatus;
Q_UNUSED(thing)
});
connect(connection, &HuaweiFusionSolar::inverterEnergyProducedChanged, this, [thing](float inverterEnergyProduced){
qCDebug(dcHuawei()) << "Inverter total energy produced changed" << inverterEnergyProduced << "kWh";
thing->setStateValue(huaweiInverterTotalEnergyProducedStateTypeId, inverterEnergyProduced);
});
// Meter
connect(connection, &HuaweiFusionSolar::powerMeterActivePowerChanged, this, [this, thing](qint32 powerMeterActivePower){
Things meterThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiMeterThingClassId);
if (!meterThings.isEmpty()) {
qCDebug(dcHuawei()) << "Meter power changed" << powerMeterActivePower << "W";
// Note: > 0 -> return, < 0 consume
meterThings.first()->setStateValue(huaweiMeterCurrentPowerStateTypeId, -powerMeterActivePower);
}
});
// Battery 1
connect(connection, &HuaweiFusionSolar::lunaBattery1StatusChanged, this, [this, thing](HuaweiFusionSolar::BatteryDeviceStatus lunaBattery1Status){
qCDebug(dcHuawei()) << "Battery 1 status changed" << lunaBattery1Status;
if (lunaBattery1Status != HuaweiFusionSolar::BatteryDeviceStatusOffline) {
// Check if w have to create the energy storage
Things batteryThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiBatteryThingClassId);
bool alreadySetUp = false;
foreach (Thing *batteryThing, batteryThings) {
if (batteryThing->paramValue(huaweiBatteryThingUnitParamTypeId).toUInt() == 1) {
alreadySetUp = true;
}
}
if (!alreadySetUp) {
qCDebug(dcHuawei()) << "Set up huawei energy storage 1 for" << thing;
ThingDescriptor descriptor(huaweiBatteryThingClassId, "Luna 2000 Battery", QString(), thing->id());
ParamList params;
params.append(Param(huaweiBatteryThingUnitParamTypeId, 1));
descriptor.setParams(params);
emit autoThingsAppeared(ThingDescriptors() << descriptor);
}
}
});
connect(connection, &HuaweiFusionSolar::lunaBattery1PowerChanged, this, [this, thing](qint32 lunaBattery1Power){
qCDebug(dcHuawei()) << "Battery 1 power changed" << lunaBattery1Power << "W";
Things batteryThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiBatteryThingClassId).filterByParam(huaweiBatteryThingUnitParamTypeId, 1);
if (!batteryThings.isEmpty()) {
batteryThings.first()->setStateValue(huaweiBatteryCurrentPowerStateTypeId, lunaBattery1Power);
if (lunaBattery1Power < 0) {
batteryThings.first()->setStateValue(huaweiBatteryChargingStateStateTypeId, "discharging");
} else if (lunaBattery1Power > 0) {
batteryThings.first()->setStateValue(huaweiBatteryChargingStateStateTypeId, "charging");
} else {
batteryThings.first()->setStateValue(huaweiBatteryChargingStateStateTypeId, "idle");
}
}
});
connect(connection, &HuaweiFusionSolar::lunaBattery1SocChanged, this, [this, thing](float lunaBattery1Soc){
qCDebug(dcHuawei()) << "Battery 1 SOC changed" << lunaBattery1Soc << "%";
Things batteryThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiBatteryThingClassId).filterByParam(huaweiBatteryThingUnitParamTypeId, 1);
if (!batteryThings.isEmpty()) {
batteryThings.first()->setStateValue(huaweiBatteryBatteryLevelStateTypeId, lunaBattery1Soc);
batteryThings.first()->setStateValue(huaweiBatteryBatteryCriticalStateTypeId, lunaBattery1Soc < 10);
}
});
// Battery 2
connect(connection, &HuaweiFusionSolar::lunaBattery2StatusChanged, this, [this, thing](HuaweiFusionSolar::BatteryDeviceStatus lunaBattery1Status){
qCDebug(dcHuawei()) << "Battery 2 status changed" << lunaBattery1Status;
if (lunaBattery1Status != HuaweiFusionSolar::BatteryDeviceStatusOffline) {
// Check if w have to create the energy storage
Things batteryThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiBatteryThingClassId);
bool alreadySetUp = false;
foreach (Thing *batteryThing, batteryThings) {
if (batteryThing->paramValue(huaweiBatteryThingUnitParamTypeId).toUInt() == 2) {
alreadySetUp = true;
}
}
if (!alreadySetUp) {
qCDebug(dcHuawei()) << "Set up huawei energy storage 2 for" << thing;
ThingDescriptor descriptor(huaweiBatteryThingClassId, "Luna 2000 Battery", QString(), thing->id());
ParamList params;
params.append(Param(huaweiBatteryThingUnitParamTypeId, 2));
descriptor.setParams(params);
emit autoThingsAppeared(ThingDescriptors() << descriptor);
}
}
});
connect(connection, &HuaweiFusionSolar::lunaBattery2PowerChanged, this, [this, thing](qint32 lunaBattery2Power){
qCDebug(dcHuawei()) << "Battery 2 power changed" << lunaBattery2Power << "W";
Things batteryThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiBatteryThingClassId).filterByParam(huaweiBatteryThingUnitParamTypeId, 2);
if (!batteryThings.isEmpty()) {
batteryThings.first()->setStateValue(huaweiBatteryCurrentPowerStateTypeId, lunaBattery2Power);
if (lunaBattery2Power < 0) {
batteryThings.first()->setStateValue(huaweiBatteryChargingStateStateTypeId, "discharging");
} else if (lunaBattery2Power > 0) {
batteryThings.first()->setStateValue(huaweiBatteryChargingStateStateTypeId, "charging");
} else {
batteryThings.first()->setStateValue(huaweiBatteryChargingStateStateTypeId, "idle");
}
}
});
connect(connection, &HuaweiFusionSolar::lunaBattery2SocChanged, this, [this, thing](float lunaBattery2Soc){
qCDebug(dcHuawei()) << "Battery 2 SOC changed" << lunaBattery2Soc << "%";
Things batteryThings = myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiBatteryThingClassId).filterByParam(huaweiBatteryThingUnitParamTypeId, 2);
if (!batteryThings.isEmpty()) {
batteryThings.first()->setStateValue(huaweiBatteryBatteryLevelStateTypeId, lunaBattery2Soc);
batteryThings.first()->setStateValue(huaweiBatteryBatteryCriticalStateTypeId, lunaBattery2Soc < 10);
}
});
m_connections.insert(thing, connection);
connection->connectDevice();
// FIXME: make async and check if this is really a huawei
info->finish(Thing::ThingErrorNoError);
}
if (thing->thingClassId() == huaweiMeterThingClassId) {
// Nothing to do here, we get all information from the inverter connection
info->finish(Thing::ThingErrorNoError);
Thing *parentThing = myThings().findById(thing->parentId());
if (parentThing) {
thing->setStateValue("connected", parentThing->stateValue("connected").toBool());
}
}
if (thing->thingClassId() == huaweiBatteryThingClassId) {
// Nothing to do here, we get all information from the inverter connection
info->finish(Thing::ThingErrorNoError);
Thing *parentThing = myThings().findById(thing->parentId());
if (parentThing) {
thing->setStateValue("connected", parentThing->stateValue("connected").toBool());
}
}
}
void IntegrationPluginHuawei::postSetupThing(Thing *thing)
{
if (thing->thingClassId() == huaweiInverterThingClassId) {
if (!m_pluginTimer) {
qCDebug(dcHuawei()) << "Starting plugin timer...";
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
foreach(HuaweiFusionSolar *connection, m_connections) {
if (connection->connected()) {
connection->update();
}
}
});
m_pluginTimer->start();
}
// Check if w have to set up a child meter for this inverter connection
if (myThings().filterByParentId(thing->id()).filterByThingClassId(huaweiMeterThingClassId).isEmpty()) {
qCDebug(dcHuawei()) << "Set up huawei meter for" << thing;
emit autoThingsAppeared(ThingDescriptors() << ThingDescriptor(huaweiMeterThingClassId, "Huawei Power Meter", QString(), thing->id()));
}
}
}
void IntegrationPluginHuawei::thingRemoved(Thing *thing)
{
if (thing->thingClassId() == huaweiInverterThingClassId && m_connections.contains(thing)) {
m_connections.take(thing)->deleteLater();
}
if (myThings().isEmpty() && m_pluginTimer) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
m_pluginTimer = nullptr;
}
}
void IntegrationPluginHuawei::executeAction(ThingActionInfo *info)
{
info->finish(Thing::ThingErrorNoError);
}

View File

@ -0,0 +1,62 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This fileDescriptor 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 INTEGRATIONPLUGINHUAWEI_H
#define INTEGRATIONPLUGINHUAWEI_H
#include "plugintimer.h"
#include "integrations/integrationplugin.h"
#include "huaweifusionsolar.h"
class IntegrationPluginHuawei: public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginhuawei.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginHuawei();
void discoverThings(ThingDiscoveryInfo *info) override;
void startMonitoringAutoThings() override;
void setupThing(ThingSetupInfo *info) override;
void postSetupThing(Thing *thing) override;
void thingRemoved(Thing *thing) override;
void executeAction(ThingActionInfo *info) override;
private:
PluginTimer *m_pluginTimer = nullptr;
QHash<Thing *, HuaweiFusionSolar *> m_connections;
};
#endif // INTEGRATIONPLUGINHUAWEI_H

View File

@ -0,0 +1,297 @@
{
"name": "Huawei",
"displayName": "Huawei FusionSolar",
"id": "fc3e4509-47f3-4622-9bc4-0a90fe2b6262",
"vendors": [
{
"name": "huawei",
"displayName": "Huawei",
"id": "f654c99d-a286-4abb-b33e-1a71843d8da0",
"thingClasses": [
{
"name": "huaweiInverter",
"displayName": "Huawei FusionSolar Inverter",
"id": "87e75ee0-d544-457b-add3-bd4e58160fcd",
"createMethods": ["discovery", "user"],
"interfaces": ["solarinverter", "connectable"],
"providedInterfaces": [ "solarinverter", "energymeter", "energystorage"],
"paramTypes": [
{
"id": "d93371db-0954-4dcd-a1a5-6881b78cb0ea",
"name": "ipAddress",
"displayName": "IP address",
"type": "QString",
"inputType": "IPv4Address",
"defaultValue": "127.0.0.1"
},
{
"id": "93517bff-1928-4c4a-8207-5fe596c86eba",
"name":"macAddress",
"displayName": "MAC address",
"type": "QString",
"inputType": "MacAddress",
"defaultValue": ""
},
{
"id": "55c4ec99-6342-4309-84a8-d1615f19b2e8",
"name":"port",
"displayName": "Port",
"type": "int",
"defaultValue": 502
},
{
"id": "aa6e978e-a16b-4722-8330-e706f3c7c21e",
"name":"slaveId",
"displayName": "Slave ID",
"type": "int",
"defaultValue": 1
}
],
"stateTypes": [
{
"id": "a51f0ceb-bd2c-444f-8b39-77cf8a4e1bc6",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "f463f36e-69f9-4614-b690-664ce22d76e0",
"name": "currentPower",
"displayName": "Active power",
"displayNameEvent": "Active power changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "e97fe328-6ca4-4fe4-86f7-fee6e9e406a5",
"name": "totalEnergyProduced",
"displayName": "AC energy",
"displayNameEvent": "AC energy changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
}
],
"actionTypes": [ ]
},
{
"name": "huaweiMeter",
"displayName": "Huawei Meter",
"id": "529c2a19-ca6a-4df2-b56e-3fb2673fa95f",
"createMethods": ["auto"],
"interfaces": [ "energymeter", "connectable"],
"paramTypes": [
],
"stateTypes": [
{
"id": "720ece7a-b0b3-4fa3-9f52-6f23042624a5",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "f480dc82-68e2-44e2-839c-df38b9c10310",
"name": "currentPower",
"displayName": "Total real power",
"displayNameEvent": "Total real power changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00
},
{
"id": "759554dd-74c5-4836-9792-96e02eb816f0",
"name": "totalEnergyProduced",
"displayName": "AC energy",
"displayNameEvent": "AC energy changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "2cf8d885-37f7-478f-819e-c4e20f2dbe01",
"name": "totalEnergyConsumed",
"displayName": "Total real energy imported",
"displayNameEvent": "Total real energy imported changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "af48ff45-11ba-401e-a812-bb1db0896449",
"name": "currentPhaseA",
"displayName": "Phase A current",
"displayNameEvent": "Phase A current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0.00
},
{
"id": "fb5082e4-a2d8-4958-a47d-e80928795ece",
"name": "currentPhaseB",
"displayName": "Phase B current",
"displayNameEvent": "Phase B current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0.00
},
{
"id": "bdd9aa8b-93fe-4b6b-8a31-08e99d85a06c",
"name": "currentPhaseC",
"displayName": "Phase C current",
"displayNameEvent": "Phase C current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0.00
},
{
"id": "ecc03e9b-88b1-424f-a179-66bbdebaaea9",
"name": "currentPowerPhaseA",
"displayName": "Current power phase A",
"displayNameEvent": "Current power phase A changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00
},
{
"id": "7971cbde-b2ea-4474-b68a-71e040ed3b1d",
"name": "currentPowerPhaseB",
"displayName": "Current power phase B",
"displayNameEvent": "Current power phase B changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00
},
{
"id": "7ca21c4d-6763-49e4-a056-4c9c76923971",
"name": "currentPowerPhaseC",
"displayName": "Current power phase C",
"displayNameEvent": "Current power phase C changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00
},
{
"id": "ea5d7924-19a8-415c-aeeb-e04ce08bed33",
"name": "voltagePhaseA",
"displayName": "Voltage phase A",
"displayNameEvent": "Voltage phase A changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0.00
},
{
"id": "f15856d1-645f-4d34-89a7-c1585ca329cc",
"name": "voltagePhaseB",
"displayName": "Voltage phase B",
"displayNameEvent": "Voltage phase B changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0.00
},
{
"id": "aafb5de4-caa1-4a90-8149-cdf85ae5dc2b",
"name": "voltagePhaseC",
"displayName": "Voltage phase C",
"displayNameEvent": "Voltage phase C changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0.00
},
{
"id": "1e2252be-80b3-4e9a-97f7-105d6d1c50f9",
"name": "frequency",
"displayName": "Frequency",
"displayNameEvent": "Frequency changed",
"type": "double",
"unit": "Hertz",
"defaultValue": 0.00
}
],
"actionTypes": [ ]
},
{
"name": "huaweiBattery",
"displayName": "Huawei Battery",
"id": "40104aac-0456-475d-8bd6-18f946597d96",
"createMethods": ["auto"],
"interfaces": [ "energystorage", "connectable"],
"paramTypes": [
{
"id": "019287a6-c593-45a8-9695-2e1ad8e81c32",
"name":"unit",
"displayName": "Unit",
"type": "uint",
"defaultValue": 0
}
],
"stateTypes": [
{
"id": "917bc284-9d43-430c-a8c3-642d302448e6",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "223ddf60-ff73-4acf-b8ab-6337aeb972e8",
"name": "batteryCritical",
"displayName": "Battery critical",
"displayNameEvent": "Battery critical changed",
"type": "bool",
"defaultValue": false
},
{
"id": "94d609bf-1f67-47c4-a23d-2fd14e7c0b21",
"name": "batteryLevel",
"displayName": "Battery level",
"displayNameEvent": "Battery level changed",
"type": "int",
"unit": "Percentage",
"minValue": 0,
"maxValue": 100,
"defaultValue": 0
},
{
"id": "53ca1f8a-0267-40aa-b563-762a943c8f55",
"name": "currentPower",
"displayName": "Total real power",
"displayNameEvent": "Total real power changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00
},
{
"id": "3eed974a-0acb-4e38-bcb8-0e3f6fbfd51a",
"name": "capacity",
"displayName": "Capacity",
"displayNameEvent": "Capacity changed",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.00
},
{
"id": "d9604513-d5a9-463a-ad18-d2f259a7a99d",
"name": "chargingState",
"displayName": "Charging state",
"displayNameEvent": "Charging state changed",
"type": "QString",
"possibleValues": ["idle", "charging", "discharging"],
"defaultValue": "idle"
}
],
"actionTypes": [ ]
}
]
}
]
}

13
huawei/meta.json Normal file
View File

@ -0,0 +1,13 @@
{
"title": "Huawei FusionSolar",
"tagline": "Connect to Huawei FusionSolar devices.",
"icon": "huawei.png",
"stability": "consumer",
"offline": true,
"technologies": [
"network"
],
"categories": [
"energy"
]
}

View File

@ -0,0 +1,401 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>Huawei</name>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="104"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="107"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="110"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="113"/>
<source>AC energy</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: totalEnergyProduced, ID: {759554dd-74c5-4836-9792-96e02eb816f0})
----------
The name of the StateType ({759554dd-74c5-4836-9792-96e02eb816f0}) of ThingClass huaweiMeter
----------
The name of the ParamType (ThingClass: huaweiInverter, EventType: totalEnergyProduced, ID: {e97fe328-6ca4-4fe4-86f7-fee6e9e406a5})
----------
The name of the StateType ({e97fe328-6ca4-4fe4-86f7-fee6e9e406a5}) of ThingClass huaweiInverter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="116"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="119"/>
<source>AC energy changed</source>
<extracomment>The name of the EventType ({759554dd-74c5-4836-9792-96e02eb816f0}) of ThingClass huaweiMeter
----------
The name of the EventType ({e97fe328-6ca4-4fe4-86f7-fee6e9e406a5}) of ThingClass huaweiInverter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="122"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="125"/>
<source>Active power</source>
<extracomment>The name of the ParamType (ThingClass: huaweiInverter, EventType: currentPower, ID: {f463f36e-69f9-4614-b690-664ce22d76e0})
----------
The name of the StateType ({f463f36e-69f9-4614-b690-664ce22d76e0}) of ThingClass huaweiInverter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="128"/>
<source>Active power changed</source>
<extracomment>The name of the EventType ({f463f36e-69f9-4614-b690-664ce22d76e0}) of ThingClass huaweiInverter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="131"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="134"/>
<source>Battery critical</source>
<extracomment>The name of the ParamType (ThingClass: huaweiBattery, EventType: batteryCritical, ID: {223ddf60-ff73-4acf-b8ab-6337aeb972e8})
----------
The name of the StateType ({223ddf60-ff73-4acf-b8ab-6337aeb972e8}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="137"/>
<source>Battery critical changed</source>
<extracomment>The name of the EventType ({223ddf60-ff73-4acf-b8ab-6337aeb972e8}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="140"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="143"/>
<source>Battery level</source>
<extracomment>The name of the ParamType (ThingClass: huaweiBattery, EventType: batteryLevel, ID: {94d609bf-1f67-47c4-a23d-2fd14e7c0b21})
----------
The name of the StateType ({94d609bf-1f67-47c4-a23d-2fd14e7c0b21}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="146"/>
<source>Battery level changed</source>
<extracomment>The name of the EventType ({94d609bf-1f67-47c4-a23d-2fd14e7c0b21}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="149"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="152"/>
<source>Capacity</source>
<extracomment>The name of the ParamType (ThingClass: huaweiBattery, EventType: capacity, ID: {3eed974a-0acb-4e38-bcb8-0e3f6fbfd51a})
----------
The name of the StateType ({3eed974a-0acb-4e38-bcb8-0e3f6fbfd51a}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="155"/>
<source>Capacity changed</source>
<extracomment>The name of the EventType ({3eed974a-0acb-4e38-bcb8-0e3f6fbfd51a}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="158"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="161"/>
<source>Charging state</source>
<extracomment>The name of the ParamType (ThingClass: huaweiBattery, EventType: chargingState, ID: {d9604513-d5a9-463a-ad18-d2f259a7a99d})
----------
The name of the StateType ({d9604513-d5a9-463a-ad18-d2f259a7a99d}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="164"/>
<source>Charging state changed</source>
<extracomment>The name of the EventType ({d9604513-d5a9-463a-ad18-d2f259a7a99d}) of ThingClass huaweiBattery</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="167"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="170"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="173"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="176"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="179"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="182"/>
<source>Connected</source>
<extracomment>The name of the ParamType (ThingClass: huaweiBattery, EventType: connected, ID: {917bc284-9d43-430c-a8c3-642d302448e6})
----------
The name of the StateType ({917bc284-9d43-430c-a8c3-642d302448e6}) of ThingClass huaweiBattery
----------
The name of the ParamType (ThingClass: huaweiMeter, EventType: connected, ID: {720ece7a-b0b3-4fa3-9f52-6f23042624a5})
----------
The name of the StateType ({720ece7a-b0b3-4fa3-9f52-6f23042624a5}) of ThingClass huaweiMeter
----------
The name of the ParamType (ThingClass: huaweiInverter, EventType: connected, ID: {a51f0ceb-bd2c-444f-8b39-77cf8a4e1bc6})
----------
The name of the StateType ({a51f0ceb-bd2c-444f-8b39-77cf8a4e1bc6}) of ThingClass huaweiInverter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="185"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="188"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="191"/>
<source>Connected changed</source>
<extracomment>The name of the EventType ({917bc284-9d43-430c-a8c3-642d302448e6}) of ThingClass huaweiBattery
----------
The name of the EventType ({720ece7a-b0b3-4fa3-9f52-6f23042624a5}) of ThingClass huaweiMeter
----------
The name of the EventType ({a51f0ceb-bd2c-444f-8b39-77cf8a4e1bc6}) of ThingClass huaweiInverter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="194"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="197"/>
<source>Current power phase A</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: currentPowerPhaseA, ID: {ecc03e9b-88b1-424f-a179-66bbdebaaea9})
----------
The name of the StateType ({ecc03e9b-88b1-424f-a179-66bbdebaaea9}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="200"/>
<source>Current power phase A changed</source>
<extracomment>The name of the EventType ({ecc03e9b-88b1-424f-a179-66bbdebaaea9}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="203"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="206"/>
<source>Current power phase B</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: currentPowerPhaseB, ID: {7971cbde-b2ea-4474-b68a-71e040ed3b1d})
----------
The name of the StateType ({7971cbde-b2ea-4474-b68a-71e040ed3b1d}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="209"/>
<source>Current power phase B changed</source>
<extracomment>The name of the EventType ({7971cbde-b2ea-4474-b68a-71e040ed3b1d}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="212"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="215"/>
<source>Current power phase C</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: currentPowerPhaseC, ID: {7ca21c4d-6763-49e4-a056-4c9c76923971})
----------
The name of the StateType ({7ca21c4d-6763-49e4-a056-4c9c76923971}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="218"/>
<source>Current power phase C changed</source>
<extracomment>The name of the EventType ({7ca21c4d-6763-49e4-a056-4c9c76923971}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="221"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="224"/>
<source>Frequency</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: frequency, ID: {1e2252be-80b3-4e9a-97f7-105d6d1c50f9})
----------
The name of the StateType ({1e2252be-80b3-4e9a-97f7-105d6d1c50f9}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="227"/>
<source>Frequency changed</source>
<extracomment>The name of the EventType ({1e2252be-80b3-4e9a-97f7-105d6d1c50f9}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="230"/>
<source>Huawei</source>
<extracomment>The name of the vendor ({f654c99d-a286-4abb-b33e-1a71843d8da0})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="233"/>
<source>Huawei Battery</source>
<extracomment>The name of the ThingClass ({40104aac-0456-475d-8bd6-18f946597d96})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="236"/>
<source>Huawei FusionSolar</source>
<extracomment>The name of the plugin Huawei ({fc3e4509-47f3-4622-9bc4-0a90fe2b6262})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="239"/>
<source>Huawei FusionSolar Inverter</source>
<extracomment>The name of the ThingClass ({87e75ee0-d544-457b-add3-bd4e58160fcd})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="242"/>
<source>Huawei Meter</source>
<extracomment>The name of the ThingClass ({529c2a19-ca6a-4df2-b56e-3fb2673fa95f})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="245"/>
<source>IP address</source>
<extracomment>The name of the ParamType (ThingClass: huaweiInverter, Type: thing, ID: {d93371db-0954-4dcd-a1a5-6881b78cb0ea})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="248"/>
<source>MAC address</source>
<extracomment>The name of the ParamType (ThingClass: huaweiInverter, Type: thing, ID: {93517bff-1928-4c4a-8207-5fe596c86eba})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="251"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="254"/>
<source>Phase A current</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: currentPhaseA, ID: {af48ff45-11ba-401e-a812-bb1db0896449})
----------
The name of the StateType ({af48ff45-11ba-401e-a812-bb1db0896449}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="257"/>
<source>Phase A current changed</source>
<extracomment>The name of the EventType ({af48ff45-11ba-401e-a812-bb1db0896449}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="260"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="263"/>
<source>Phase B current</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: currentPhaseB, ID: {fb5082e4-a2d8-4958-a47d-e80928795ece})
----------
The name of the StateType ({fb5082e4-a2d8-4958-a47d-e80928795ece}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="266"/>
<source>Phase B current changed</source>
<extracomment>The name of the EventType ({fb5082e4-a2d8-4958-a47d-e80928795ece}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="269"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="272"/>
<source>Phase C current</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: currentPhaseC, ID: {bdd9aa8b-93fe-4b6b-8a31-08e99d85a06c})
----------
The name of the StateType ({bdd9aa8b-93fe-4b6b-8a31-08e99d85a06c}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="275"/>
<source>Phase C current changed</source>
<extracomment>The name of the EventType ({bdd9aa8b-93fe-4b6b-8a31-08e99d85a06c}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="278"/>
<source>Port</source>
<extracomment>The name of the ParamType (ThingClass: huaweiInverter, Type: thing, ID: {55c4ec99-6342-4309-84a8-d1615f19b2e8})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="281"/>
<source>Slave ID</source>
<extracomment>The name of the ParamType (ThingClass: huaweiInverter, Type: thing, ID: {aa6e978e-a16b-4722-8330-e706f3c7c21e})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="284"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="287"/>
<source>Total real energy imported</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: totalEnergyConsumed, ID: {2cf8d885-37f7-478f-819e-c4e20f2dbe01})
----------
The name of the StateType ({2cf8d885-37f7-478f-819e-c4e20f2dbe01}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="290"/>
<source>Total real energy imported changed</source>
<extracomment>The name of the EventType ({2cf8d885-37f7-478f-819e-c4e20f2dbe01}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="293"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="296"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="299"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="302"/>
<source>Total real power</source>
<extracomment>The name of the ParamType (ThingClass: huaweiBattery, EventType: currentPower, ID: {53ca1f8a-0267-40aa-b563-762a943c8f55})
----------
The name of the StateType ({53ca1f8a-0267-40aa-b563-762a943c8f55}) of ThingClass huaweiBattery
----------
The name of the ParamType (ThingClass: huaweiMeter, EventType: currentPower, ID: {f480dc82-68e2-44e2-839c-df38b9c10310})
----------
The name of the StateType ({f480dc82-68e2-44e2-839c-df38b9c10310}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="305"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="308"/>
<source>Total real power changed</source>
<extracomment>The name of the EventType ({53ca1f8a-0267-40aa-b563-762a943c8f55}) of ThingClass huaweiBattery
----------
The name of the EventType ({f480dc82-68e2-44e2-839c-df38b9c10310}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="311"/>
<source>Unit</source>
<extracomment>The name of the ParamType (ThingClass: huaweiBattery, Type: thing, ID: {019287a6-c593-45a8-9695-2e1ad8e81c32})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="314"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="317"/>
<source>Voltage phase A</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: voltagePhaseA, ID: {ea5d7924-19a8-415c-aeeb-e04ce08bed33})
----------
The name of the StateType ({ea5d7924-19a8-415c-aeeb-e04ce08bed33}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="320"/>
<source>Voltage phase A changed</source>
<extracomment>The name of the EventType ({ea5d7924-19a8-415c-aeeb-e04ce08bed33}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="323"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="326"/>
<source>Voltage phase B</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: voltagePhaseB, ID: {f15856d1-645f-4d34-89a7-c1585ca329cc})
----------
The name of the StateType ({f15856d1-645f-4d34-89a7-c1585ca329cc}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="329"/>
<source>Voltage phase B changed</source>
<extracomment>The name of the EventType ({f15856d1-645f-4d34-89a7-c1585ca329cc}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="332"/>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="335"/>
<source>Voltage phase C</source>
<extracomment>The name of the ParamType (ThingClass: huaweiMeter, EventType: voltagePhaseC, ID: {aafb5de4-caa1-4a90-8149-cdf85ae5dc2b})
----------
The name of the StateType ({aafb5de4-caa1-4a90-8149-cdf85ae5dc2b}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/huawei/plugininfo.h" line="338"/>
<source>Voltage phase C changed</source>
<extracomment>The name of the EventType ({aafb5de4-caa1-4a90-8149-cdf85ae5dc2b}) of ThingClass huaweiMeter</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IntegrationPluginHuawei</name>
<message>
<location filename="../integrationpluginhuawei.cpp" line="46"/>
<source>The network device discovery is not available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginhuawei.cpp" line="107"/>
<source>No IP address given</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -7,7 +7,8 @@ SUBDIRS += libnymea-sunspec
PLUGIN_DIRS = \
alphainnotec \
drexelundweiss \
energymeters \
energymeters \
huawei \
modbuscommander \
mtec \
mypv \