Merge PR #111: New plugin: Amperfied/Heidelberg

This commit is contained in:
jenkins 2023-03-07 17:25:32 +01:00
commit d93cc3d499
17 changed files with 1597 additions and 0 deletions

19
amperfied/README.md Normal file
View File

@ -0,0 +1,19 @@
# Amperfied - Heidelberg
Connects nymea to a Amperfied/Heidelberg wallboxes. Currently supported models are:
* Amperfeid Energy Control
* Amperfeid connect.home
# Requirements
nymea requires the use of a firmware greator or equal version 1.0.7 on the wallbox.
## Amperfeid Energy Control
The Amperfeid Energy Control is a Modbus RTU device. This means it must be connected to the nymea system using an RS485 port.
In order to allow nymea to automatically discover the wallbox on the bus, the Modbus slave ID must be in the range of 1 - 20.
If a higher slave ID number is required, the manual setup is to be used.
## Amperfied connect.home
The Amperfeid connect.home is a Modbus TCP device. This means it must be connected to the same network the nymea system is in.

View File

@ -0,0 +1,250 @@
{
"className": "Amperfied",
"protocol": "BOTH",
"endianness": "BigEndian",
"errorLimitUntilNotReachable": 2,
"checkReachableRegister": "chargingCurrent",
"enums": [
{
"name": "ChargingState",
"values": [
{
"key": "Undefined",
"value": 1
},
{
"key": "A1",
"value": 2
},
{
"key": "A2",
"value": 3
},
{
"key": "B1",
"value": 4
},
{
"key": "B2",
"value": 5
},
{
"key": "C1",
"value": 6
},
{
"key": "C2",
"value": 7
},
{
"key": "Derating",
"value": 8
},
{
"key": "E",
"value": 9
},
{
"key": "F",
"value": 10
},
{
"key": "Error",
"value": 11
}
]
}
],
"blocks": [
{
"id": "consumptions",
"readSchedule": "update",
"registers": [
{
"id": "chargingState",
"address": 5,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "ChargingState",
"enum": "ChargingState",
"defaultValue": "ChargingStateUndefined",
"access": "RO"
},
{
"id": "currentL1",
"address": 6,
"size": 1,
"type": "uint16",
"unit": "A",
"registerType": "inputRegister",
"description": "Current L1",
"defaultValue": "0",
"access": "RO"
},
{
"id": "currentL2",
"address": 7,
"size": 1,
"type": "uint16",
"unit": "A",
"registerType": "inputRegister",
"description": "Current L2",
"defaultValue": "0",
"access": "RO"
},
{
"id": "currentL3",
"address": 8,
"size": 1,
"type": "uint16",
"unit": "A",
"registerType": "inputRegister",
"description": "Current L3",
"defaultValue": "0",
"access": "RO"
},
{
"id": "pcbTemperature",
"address": 9,
"size": 1,
"type": "uint16",
"unit": "1/10°C",
"registerType": "inputRegister",
"description": "PCB temperature",
"defaultValue": "0",
"access": "RO"
},
{
"id": "voltageL1",
"address": 10,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "Voltage L1",
"unit": "V",
"defaultValue": 0,
"access": "RO"
},
{
"id": "voltageL2",
"address": 11,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "Voltage L2",
"unit": "V",
"defaultValue": 0,
"access": "RO"
},
{
"id": "voltageL3",
"address": 12,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "Voltage L3",
"unit": "V",
"defaultValue": 0,
"access": "RO"
},
{
"id": "externalLock",
"address": 13,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "External lock",
"defaultValue": 0,
"access": "RO"
},
{
"id": "currentPower",
"address": 14,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "Power (L1+L2+L3)",
"unit": "VA",
"defaultValue": 0,
"access": "RO"
},
{
"id": "sessionEnergy",
"address": 15,
"size": 2,
"type": "uint32",
"registerType": "inputRegister",
"description": "Energy since PowerOn",
"unit": "Wh",
"defaultValue": 0,
"access": "RO"
},
{
"id": "totalEnergy",
"address": 17,
"size": 2,
"type": "uint32",
"registerType": "inputRegister",
"description": "Energy since installation",
"unit": "Wh",
"defaultValue": 0,
"access": "RO"
}
]
},
{
"id": "minMaxValues",
"readSchedule": "update",
"registers": [
{
"id": "maxChargingCurrent",
"address": 100,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "Absolute maximum charging current",
"unit": "A",
"defaultValue": 0,
"access": "RO"
},
{
"id": "minChargingCurrent",
"address": 101,
"size": 1,
"type": "uint16",
"registerType": "inputRegister",
"description": "Absolute minimum charging current",
"unit": "A",
"defaultValue": 0,
"access": "RO"
}
]
}
],
"registers": [
{
"id": "version",
"address": 4,
"size": 1,
"type": "uint16",
"readSchedule": "init",
"registerType": "inputRegister",
"description": "Version",
"defaultValue": 0,
"access": "RO"
},
{
"id": "chargingCurrent",
"address": 261,
"size": 1,
"type": "uint16",
"readSchedule": "update",
"registerType": "holdingRegister",
"description": "Charging current",
"unit": "A",
"defaultValue": "0",
"access": "RW"
}
]
}

BIN
amperfied/amperfied.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

17
amperfied/amperfied.pro Normal file
View File

@ -0,0 +1,17 @@
include(../plugins.pri)
MODBUS_CONNECTIONS += amperfied-registers.json
MODBUS_TOOLS_CONFIG += VERBOSE
include(../modbus.pri)
HEADERS += \
energycontroldiscovery.h \
connecthomediscovery.h \
integrationpluginamperfied.h
SOURCES += \
energycontroldiscovery.cpp \
connecthomediscovery.cpp \
integrationpluginamperfied.cpp

View File

@ -0,0 +1,138 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2023, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "connecthomediscovery.h"
#include "extern-plugininfo.h"
ConnectHomeDiscovery::ConnectHomeDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, QObject *parent) :
QObject{parent},
m_networkDeviceDiscovery{networkDeviceDiscovery}
{
m_gracePeriodTimer.setSingleShot(true);
m_gracePeriodTimer.setInterval(3000);
connect(&m_gracePeriodTimer, &QTimer::timeout, this, [this](){
qCDebug(dcAmperfied()) << "Discovery: Grace period timer triggered.";
finishDiscovery();
});
}
void ConnectHomeDiscovery::startDiscovery()
{
qCInfo(dcAmperfied()) << "Discovery: Searching for Amperfied wallboxes in the network...";
NetworkDeviceDiscoveryReply *discoveryReply = m_networkDeviceDiscovery->discover();
connect(discoveryReply, &NetworkDeviceDiscoveryReply::networkDeviceInfoAdded, this, &ConnectHomeDiscovery::checkNetworkDevice);
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
qCDebug(dcAmperfied()) << "Discovery: Network discovery finished. Found" << discoveryReply->networkDeviceInfos().count() << "network devices";
m_gracePeriodTimer.start();
discoveryReply->deleteLater();
});
}
QList<ConnectHomeDiscovery::Result> ConnectHomeDiscovery::discoveryResults() const
{
return m_discoveryResults;
}
void ConnectHomeDiscovery::checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo)
{
int port = 502;
int slaveId = 1;
qCDebug(dcAmperfied()) << "Checking network device:" << networkDeviceInfo << "Port:" << port << "Slave ID:" << slaveId;
AmperfiedModbusTcpConnection *connection = new AmperfiedModbusTcpConnection(networkDeviceInfo.address(), port, slaveId, this);
m_connections.append(connection);
connect(connection, &AmperfiedModbusTcpConnection::reachableChanged, this, [=](bool reachable){
if (!reachable) {
// Disconnected ... done with this connection
cleanupConnection(connection);
return;
}
// Modbus TCP connected...ok, let's try to initialize it!
connect(connection, &AmperfiedModbusTcpConnection::initializationFinished, this, [=](bool success){
if (!success) {
qCDebug(dcAmperfied()) << "Discovery: Initialization failed on" << networkDeviceInfo.address().toString();
cleanupConnection(connection);
return;
}
Result result;
result.firmwareVersion = connection->version();
result.networkDeviceInfo = networkDeviceInfo;
m_discoveryResults.append(result);
qCDebug(dcAmperfied()) << "Discovery: --> Found"
<< "Version:" << result.firmwareVersion
<< result.networkDeviceInfo;
// Done with this connection
cleanupConnection(connection);
});
if (!connection->initialize()) {
qCDebug(dcAmperfied()) << "Discovery: Unable to initialize connection on" << networkDeviceInfo.address().toString();
cleanupConnection(connection);
}
});
// If check reachability failed...skip this host...
connect(connection, &AmperfiedModbusTcpConnection::checkReachabilityFailed, this, [=](){
qCDebug(dcAmperfied()) << "Discovery: Checking reachability failed on" << networkDeviceInfo.address().toString();
cleanupConnection(connection);
});
// Try to connect, maybe it works, maybe not...
connection->connectDevice();
}
void ConnectHomeDiscovery::cleanupConnection(AmperfiedModbusTcpConnection *connection)
{
m_connections.removeAll(connection);
connection->disconnectDevice();
connection->deleteLater();
}
void ConnectHomeDiscovery::finishDiscovery()
{
qint64 durationMilliSeconds = QDateTime::currentMSecsSinceEpoch() - m_startDateTime.toMSecsSinceEpoch();
// Cleanup any leftovers...we don't care any more
foreach (AmperfiedModbusTcpConnection *connection, m_connections)
cleanupConnection(connection);
qCInfo(dcAmperfied()) << "Discovery: Finished the discovery process. Found" << m_discoveryResults.count()
<< "Amperfied wallboxes in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
m_gracePeriodTimer.stop();
emit discoveryFinished();
}

View File

@ -0,0 +1,75 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2023, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef CONNECTHOMEDISCOVERY_H
#define CONNECTHOMEDISCOVERY_H
#include <QObject>
#include <QTimer>
#include <network/networkdevicediscovery.h>
#include "amperfiedmodbustcpconnection.h"
class ConnectHomeDiscovery : public QObject
{
Q_OBJECT
public:
explicit ConnectHomeDiscovery(NetworkDeviceDiscovery *networkDeviceDiscovery, QObject *parent = nullptr);
struct Result {
quint16 firmwareVersion;
quint16 slaveId;
NetworkDeviceInfo networkDeviceInfo;
};
void startDiscovery();
QList<Result> discoveryResults() const;
signals:
void discoveryFinished();
private:
NetworkDeviceDiscovery *m_networkDeviceDiscovery = nullptr;
QTimer m_gracePeriodTimer;
QDateTime m_startDateTime;
QList<AmperfiedModbusTcpConnection *> m_connections;
QList<Result> m_discoveryResults;
void checkNetworkDevice(const NetworkDeviceInfo &networkDeviceInfo);
void cleanupConnection(AmperfiedModbusTcpConnection *connection);
void finishDiscovery();
};
#endif // CONNECTHOMEDISCOVERY_H

View File

@ -0,0 +1,95 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2023, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "energycontroldiscovery.h"
#include "extern-plugininfo.h"
EnergyControlDiscovery::EnergyControlDiscovery(ModbusRtuHardwareResource *modbusRtuResource, QObject *parent) :
QObject{parent},
m_modbusRtuResource{modbusRtuResource}
{
}
void EnergyControlDiscovery::startDiscovery()
{
qCInfo(dcAmperfied()) << "Discovery: Searching for Amperfied EnergyControl wallboxes on modbus RTU...";
QList<ModbusRtuMaster*> candidateMasters;
foreach (ModbusRtuMaster *master, m_modbusRtuResource->modbusRtuMasters()) {
if (master->baudrate() == 19200 && master->dataBits() == 8 && master->stopBits() == 1 && master->parity() == QSerialPort::EvenParity) {
candidateMasters.append(master);
}
}
if (candidateMasters.isEmpty()) {
qCWarning(dcAmperfied()) << "No usable modbus RTU master found.";
emit discoveryFinished(false);
return;
}
foreach (ModbusRtuMaster *master, candidateMasters) {
if (master->connected()) {
tryConnect(master, 1);
} else {
qCWarning(dcAmperfied()) << "Modbus RTU master" << master->modbusUuid().toString() << "is not connected.";
}
}
}
QList<EnergyControlDiscovery::Result> EnergyControlDiscovery::discoveryResults() const
{
return m_discoveryResults;
}
void EnergyControlDiscovery::tryConnect(ModbusRtuMaster *master, quint16 slaveId)
{
qCDebug(dcAmperfied()) << "Scanning modbus RTU master" << master->modbusUuid() << "Slave ID:" << slaveId;
ModbusRtuReply *reply = master->readInputRegister(slaveId, 4);
connect(reply, &ModbusRtuReply::finished, this, [=](){
qCDebug(dcAmperfied()) << "Test reply finished!" << reply->error() << reply->result();
if (reply->error() == ModbusRtuReply::NoError && reply->result().length() > 0) {
quint16 version = reply->result().first();
if (version >= 0x0100) {
qCDebug(dcAmperfied()) << QString("Version is 0x%1").arg(version, 0, 16);
Result result {master->modbusUuid(), version, slaveId};
m_discoveryResults.append(result);
} else {
qCDebug(dcAmperfied()) << "Version must be at least 1.0.0 (0x0100)";
}
}
if (slaveId < 20) {
tryConnect(master, slaveId+1);
} else {
emit discoveryFinished(true);
}
});
}

View File

@ -0,0 +1,66 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2023, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ENERGYCONTROLDISCOVERY_H
#define ENERGYCONTROLDISCOVERY_H
#include <QObject>
#include <QTimer>
#include <hardware/modbus/modbusrtuhardwareresource.h>
class EnergyControlDiscovery : public QObject
{
Q_OBJECT
public:
explicit EnergyControlDiscovery(ModbusRtuHardwareResource *modbusRtuResource, QObject *parent = nullptr);
struct Result {
QUuid modbusRtuMasterId;
quint16 firmwareVersion;
quint16 slaveId;
};
void startDiscovery();
QList<Result> discoveryResults() const;
signals:
void discoveryFinished(bool modbusRtuMasterAvailable);
private slots:
void tryConnect(ModbusRtuMaster *master, quint16 slaveId);
private:
ModbusRtuHardwareResource *m_modbusRtuResource = nullptr;
QList<Result> m_discoveryResults;
};
#endif // ENERGYCONTROLDISCOVERY_H

Binary file not shown.

View File

@ -0,0 +1,443 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "integrationpluginamperfied.h"
#include "plugininfo.h"
#include "energycontroldiscovery.h"
#include "connecthomediscovery.h"
#include <network/networkdevicediscovery.h>
#include <hardwaremanager.h>
#include <hardware/modbus/modbusrtuhardwareresource.h>
IntegrationPluginAmperfied::IntegrationPluginAmperfied()
{
}
void IntegrationPluginAmperfied::discoverThings(ThingDiscoveryInfo *info)
{
hardwareManager()->modbusRtuResource();
if (info->thingClassId() == energyControlThingClassId) {
EnergyControlDiscovery *discovery = new EnergyControlDiscovery(hardwareManager()->modbusRtuResource(), info);
connect(discovery, &EnergyControlDiscovery::discoveryFinished, info, [this, info, discovery](bool modbusMasterAvailable){
if (!modbusMasterAvailable) {
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("No modbus RTU master with appropriate settings found. Please set up a modbus RTU master with a baudrate of 19200, 8 data bis, 1 stop bit and even parity first."));
return;
}
qCInfo(dcAmperfied()) << "Discovery results:" << discovery->discoveryResults().count();
foreach (const EnergyControlDiscovery::Result &result, discovery->discoveryResults()) {
ThingDescriptor descriptor(energyControlThingClassId, "Amperfied Energy Control", QString("Slave ID: %1").arg(result.slaveId));
ParamList params{
{energyControlThingRtuMasterParamTypeId, result.modbusRtuMasterId},
{energyControlThingSlaveIdParamTypeId, result.slaveId}
};
descriptor.setParams(params);
Thing *existingThing = myThings().findByParams(params);
if (existingThing) {
descriptor.setThingId(existingThing->id());
}
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
});
discovery->startDiscovery();
return;
}
if (info->thingClassId() == connectHomeThingClassId) {
ConnectHomeDiscovery *discovery = new ConnectHomeDiscovery(hardwareManager()->networkDeviceDiscovery(), info);
connect(discovery, &ConnectHomeDiscovery::discoveryFinished, info, [this, info, discovery](){
qCInfo(dcAmperfied()) << "Discovery results:" << discovery->discoveryResults().count();
foreach (const ConnectHomeDiscovery::Result &result, discovery->discoveryResults()) {
ThingDescriptor descriptor(connectHomeThingClassId, "Amperfied connect.home", QString("MAC: %1").arg(result.networkDeviceInfo.macAddress()));
ParamList params{
{connectHomeThingMacAddressParamTypeId, result.networkDeviceInfo.macAddress()}
};
descriptor.setParams(params);
Thing *existingThing = myThings().findByParams(params);
if (existingThing) {
descriptor.setThingId(existingThing->id());
}
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
});
discovery->startDiscovery();
}
}
void IntegrationPluginAmperfied::setupThing(ThingSetupInfo *info)
{
Thing *thing = info->thing();
qCDebug(dcAmperfied()) << "Setup" << thing << thing->params();
if (thing->thingClassId() == energyControlThingClassId) {
if (m_rtuConnections.contains(thing)) {
qCDebug(dcAmperfied()) << "Reconfiguring existing thing" << thing->name();
m_rtuConnections.take(thing)->deleteLater();
}
setupRtuConnection(info);
return;
}
if (info->thing()->thingClassId() == connectHomeThingClassId) {
if (m_tcpConnections.contains(info->thing())) {
delete m_tcpConnections.take(info->thing());
}
NetworkDeviceMonitor *monitor = m_monitors.value(info->thing());
if (!monitor) {
monitor = hardwareManager()->networkDeviceDiscovery()->registerMonitor(MacAddress(thing->paramValue(connectHomeThingMacAddressParamTypeId).toString()));
m_monitors.insert(thing, monitor);
}
connect(info, &ThingSetupInfo::aborted, monitor, [=](){
if (m_monitors.contains(thing)) {
qCDebug(dcAmperfied()) << "Unregistering monitor because setup has been aborted.";
hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(m_monitors.take(thing));
}
});
qCDebug(dcAmperfied()) << "Monitor reachable" << monitor->reachable() << thing->paramValue(connectHomeThingMacAddressParamTypeId).toString();
if (monitor->reachable()) {
setupTcpConnection(info);
} else {
connect(monitor, &NetworkDeviceMonitor::reachableChanged, info, [this, info](bool reachable){
qCDebug(dcAmperfied()) << "Monitor reachable changed!" << reachable;
if (reachable) {
setupTcpConnection(info);
}
});
}
}
}
void IntegrationPluginAmperfied::postSetupThing(Thing *thing)
{
Q_UNUSED(thing)
if (!m_pluginTimer) {
qCDebug(dcAmperfied()) << "Starting plugin timer...";
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(2);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
foreach(AmperfiedModbusRtuConnection *connection, m_rtuConnections) {
qCDebug(dcAmperfied()) << "Updating connection" << connection->modbusRtuMaster() << connection->slaveId();
connection->update();
}
foreach(AmperfiedModbusTcpConnection *connection, m_tcpConnections) {
qCDebug(dcAmperfied()) << "Updating connection" << connection->hostAddress();
connection->update();
}
});
m_pluginTimer->start();
}
}
void IntegrationPluginAmperfied::executeAction(ThingActionInfo *info)
{
if (info->thing()->thingClassId() == energyControlThingClassId) {
AmperfiedModbusRtuConnection *connection = m_rtuConnections.value(info->thing());
if (info->action().actionTypeId() == energyControlPowerActionTypeId) {
bool power = info->action().paramValue(energyControlPowerActionPowerParamTypeId).toBool();
ModbusRtuReply *reply = connection->setChargingCurrent(power ? info->thing()->stateValue(energyControlMaxChargingCurrentStateTypeId).toUInt() * 10 : 0);
connect(reply, &ModbusRtuReply::finished, info, [info, reply, power](){
if (reply->error() == ModbusRtuReply::NoError) {
info->thing()->setStateValue(energyControlPowerStateTypeId, power);
info->finish(Thing::ThingErrorNoError);
} else {
qCWarning(dcAmperfied()) << "Error setting power:" << reply->error() << reply->errorString();
info->finish(Thing::ThingErrorHardwareFailure);
}
});
return;
}
if (info->action().actionTypeId() == energyControlMaxChargingCurrentActionTypeId) {
bool power = info->thing()->stateValue(energyControlPowerStateTypeId).toBool();
uint max = info->action().paramValue(energyControlMaxChargingCurrentActionMaxChargingCurrentParamTypeId).toUInt() * 10;
ModbusRtuReply *reply = connection->setChargingCurrent(power ? max : 0);
connect(reply, &ModbusRtuReply::finished, info, [info, reply, max](){
if (reply->error() == ModbusRtuReply::NoError) {
info->thing()->setStateValue(energyControlMaxChargingCurrentStateTypeId, max);
info->finish(Thing::ThingErrorNoError);
} else {
qCWarning(dcAmperfied()) << "Error setting power:" << reply->error() << reply->errorString();
info->finish(Thing::ThingErrorHardwareFailure);
}
});
}
}
if (info->thing()->thingClassId() == connectHomeThingClassId) {
AmperfiedModbusTcpConnection *connection = m_tcpConnections.value(info->thing());
if (info->action().actionTypeId() == connectHomePowerActionTypeId) {
bool power = info->action().paramValue(connectHomePowerActionPowerParamTypeId).toBool();
QModbusReply *reply = connection->setChargingCurrent(power ? info->thing()->stateValue(connectHomeMaxChargingCurrentStateTypeId).toUInt() * 10 : 0);
connect(reply, &QModbusReply::finished, info, [info, reply, power](){
if (reply->error() == QModbusDevice::NoError) {
info->thing()->setStateValue(connectHomePowerStateTypeId, power);
info->finish(Thing::ThingErrorNoError);
} else {
qCWarning(dcAmperfied()) << "Error setting power:" << reply->error() << reply->errorString();
info->finish(Thing::ThingErrorHardwareFailure);
}
});
}
if (info->action().actionTypeId() == connectHomeMaxChargingCurrentActionTypeId) {
bool power = info->thing()->stateValue(connectHomePowerStateTypeId).toBool();
uint max = info->action().paramValue(connectHomeMaxChargingCurrentActionMaxChargingCurrentParamTypeId).toUInt() * 10;
QModbusReply *reply = connection->setChargingCurrent(power ? max : 0);
connect(reply, &QModbusReply::finished, info, [info, reply, max](){
if (reply->error() == QModbusDevice::NoError) {
info->thing()->setStateValue(connectHomeMaxChargingCurrentStateTypeId, max);
info->finish(Thing::ThingErrorNoError);
} else {
qCWarning(dcAmperfied()) << "Error setting power:" << reply->error() << reply->errorString();
info->finish(Thing::ThingErrorHardwareFailure);
}
});
}
}
}
void IntegrationPluginAmperfied::thingRemoved(Thing *thing)
{
if (thing->thingClassId() == energyControlThingClassId) {
delete m_rtuConnections.take(thing);
}
if (thing->thingClassId() == connectHomeThingClassId) {
delete m_tcpConnections.take(thing);
}
if (myThings().isEmpty() && m_pluginTimer) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
m_pluginTimer = nullptr;
}
}
void IntegrationPluginAmperfied::setupRtuConnection(ThingSetupInfo *info)
{
Thing *thing = info->thing();
ModbusRtuMaster *master = hardwareManager()->modbusRtuResource()->getModbusRtuMaster(thing->paramValue(energyControlThingRtuMasterParamTypeId).toUuid());
quint16 slaveId = thing->paramValue(energyControlThingSlaveIdParamTypeId).toUInt();
AmperfiedModbusRtuConnection *connection = new AmperfiedModbusRtuConnection(master, slaveId, thing);
connect(connection, &AmperfiedModbusRtuConnection::reachableChanged, thing, [connection, thing](bool reachable){
if (reachable) {
connection->initialize();
} else {
thing->setStateValue(energyControlCurrentPowerStateTypeId, 0);
thing->setStateValue(energyControlConnectedStateTypeId, false);
}
});
connect(connection, &AmperfiedModbusRtuConnection::initializationFinished, thing, [thing](bool success){
if (success) {
thing->setStateValue(energyControlConnectedStateTypeId, true);
}
});
connect(connection, &AmperfiedModbusRtuConnection::initializationFinished, info, [this, info, connection](bool success){
if (success) {
if (connection->version() < 0x0107) {
qCWarning(dcAmperfied()) << "We require at least version 1.0.8.";
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The firmware of this wallbox is too old. Please update the wallbox to at least firmware 1.0.7."));
delete connection;
return;
}
m_rtuConnections.insert(info->thing(), connection);
info->finish(Thing::ThingErrorNoError);
} else {
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("The wallbox is not responding"));
}
});
connect(connection, &AmperfiedModbusRtuConnection::updateFinished, thing, [connection, thing](){
qCDebug(dcAmperfied()) << "Updated:" << connection;
if (connection->chargingCurrent() == 0) {
thing->setStateValue(energyControlPowerStateTypeId, false);
} else {
thing->setStateValue(energyControlPowerStateTypeId, true);
thing->setStateValue(energyControlMaxChargingCurrentStateTypeId, connection->chargingCurrent() / 10);
}
thing->setStateMinMaxValues(energyControlMaxChargingCurrentStateTypeId, connection->minChargingCurrent(), connection->maxChargingCurrent());
thing->setStateValue(energyControlCurrentPowerStateTypeId, connection->currentPower());
thing->setStateValue(energyControlTotalEnergyConsumedStateTypeId, connection->totalEnergy() / 1000.0);
thing->setStateValue(energyControlSessionEnergyStateTypeId, connection->sessionEnergy() / 1000.0);
switch (connection->chargingState()) {
case AmperfiedModbusRtuConnection::ChargingStateUndefined:
case AmperfiedModbusRtuConnection::ChargingStateA1:
case AmperfiedModbusRtuConnection::ChargingStateA2:
thing->setStateValue(energyControlPluggedInStateTypeId, false);
break;
case AmperfiedModbusRtuConnection::ChargingStateB1:
case AmperfiedModbusRtuConnection::ChargingStateB2:
case AmperfiedModbusRtuConnection::ChargingStateC1:
case AmperfiedModbusRtuConnection::ChargingStateC2:
thing->setStateValue(energyControlPluggedInStateTypeId, true);
break;
case AmperfiedModbusRtuConnection::ChargingStateDerating:
case AmperfiedModbusRtuConnection::ChargingStateE:
case AmperfiedModbusRtuConnection::ChargingStateError:
case AmperfiedModbusRtuConnection::ChargingStateF:
qCWarning(dcAmperfied()) << "Unhandled charging state:" << connection->chargingState();
}
int phaseCount = 0;
if (connection->currentL1() > 1) {
phaseCount++;
}
if (connection->currentL2() > 1) {
phaseCount++;
}
if (connection->currentL3() > 1) {
phaseCount++;
}
if (phaseCount > 0) {
thing->setStateValue(energyControlPhaseCountStateTypeId, phaseCount);
}
thing->setStateValue(energyControlChargingStateTypeId, phaseCount > 0);
});
connection->update();
}
void IntegrationPluginAmperfied::setupTcpConnection(ThingSetupInfo *info)
{
qCDebug(dcAmperfied()) << "setting up TCP connection";
Thing *thing = info->thing();
NetworkDeviceMonitor *monitor = m_monitors.value(info->thing());
AmperfiedModbusTcpConnection *connection = new AmperfiedModbusTcpConnection(monitor->networkDeviceInfo().address(), 502, 1, info->thing());
connect(connection, &AmperfiedModbusTcpConnection::reachableChanged, thing, [connection, thing](bool reachable){
if (reachable) {
connection->initialize();
} else {
thing->setStateValue(connectHomeCurrentPowerStateTypeId, 0);
thing->setStateValue(connectHomeConnectedStateTypeId, false);
}
});
connect(connection, &AmperfiedModbusTcpConnection::initializationFinished, info, [this, info, connection](bool success){
if (success) {
if (connection->version() < 0x0107) {
qCWarning(dcAmperfied()) << "We require at least version 1.0.8.";
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The firmware of this wallbox is too old. Please update the wallbox to at least firmware 1.0.7."));
delete connection;
return;
}
m_tcpConnections.insert(info->thing(), connection);
info->finish(Thing::ThingErrorNoError);
connection->update();
} else {
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("The wallbox is not responding"));
}
});
connect(connection, &AmperfiedModbusTcpConnection::updateFinished, thing, [connection, thing](){
qCDebug(dcAmperfied()) << "Updated:" << connection;
thing->setStateValue(connectHomeConnectedStateTypeId, true);
if (connection->chargingCurrent() == 0) {
thing->setStateValue(connectHomePowerStateTypeId, false);
} else {
thing->setStateValue(connectHomePowerStateTypeId, true);
thing->setStateValue(connectHomeMaxChargingCurrentStateTypeId, connection->chargingCurrent() / 10);
}
thing->setStateMinMaxValues(connectHomeMaxChargingCurrentStateTypeId, connection->minChargingCurrent(), connection->maxChargingCurrent());
thing->setStateValue(connectHomeCurrentPowerStateTypeId, connection->currentPower());
thing->setStateValue(connectHomeTotalEnergyConsumedStateTypeId, connection->totalEnergy() / 1000.0);
thing->setStateValue(connectHomeSessionEnergyStateTypeId, connection->sessionEnergy() / 1000.0);
switch (connection->chargingState()) {
case AmperfiedModbusTcpConnection::ChargingStateUndefined:
case AmperfiedModbusTcpConnection::ChargingStateA1:
case AmperfiedModbusTcpConnection::ChargingStateA2:
thing->setStateValue(connectHomePluggedInStateTypeId, false);
break;
case AmperfiedModbusTcpConnection::ChargingStateB1:
case AmperfiedModbusTcpConnection::ChargingStateB2:
case AmperfiedModbusTcpConnection::ChargingStateC1:
case AmperfiedModbusTcpConnection::ChargingStateC2:
thing->setStateValue(connectHomePluggedInStateTypeId, true);
break;
case AmperfiedModbusTcpConnection::ChargingStateDerating:
case AmperfiedModbusTcpConnection::ChargingStateE:
case AmperfiedModbusTcpConnection::ChargingStateError:
case AmperfiedModbusTcpConnection::ChargingStateF:
qCWarning(dcAmperfied()) << "Unhandled charging state:" << connection->chargingState();
}
int phaseCount = 0;
if (connection->currentL1() > 1) {
phaseCount++;
}
if (connection->currentL2() > 1) {
phaseCount++;
}
if (connection->currentL3() > 1) {
phaseCount++;
}
if (phaseCount > 0) {
thing->setStateValue(connectHomePhaseCountStateTypeId, phaseCount);
}
thing->setStateValue(connectHomeChargingStateTypeId, phaseCount > 0);
});
connection->connectDevice();
}

View File

@ -0,0 +1,73 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2023, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef INTEGRATIONPLUGINHEIDELBERG_H
#define INTEGRATIONPLUGINHEIDELBERG_H
#include <plugintimer.h>
#include <integrations/integrationplugin.h>
#include <network/networkdevicemonitor.h>
#include "extern-plugininfo.h"
#include "amperfiedmodbusrtuconnection.h"
#include "amperfiedmodbustcpconnection.h"
class IntegrationPluginAmperfied: public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginamperfied.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginAmperfied();
void discoverThings(ThingDiscoveryInfo *info) override;
void setupThing(ThingSetupInfo *info) override;
void postSetupThing(Thing *thing) override;
void executeAction(ThingActionInfo *info) override;
void thingRemoved(Thing *thing) override;
private:
void setupRtuConnection(ThingSetupInfo *info);
void setupTcpConnection(ThingSetupInfo *info);
private:
PluginTimer *m_pluginTimer = nullptr;
QHash<Thing *, AmperfiedModbusRtuConnection*> m_rtuConnections;
QHash<Thing *, AmperfiedModbusTcpConnection*> m_tcpConnections;
QHash<Thing *, NetworkDeviceMonitor *> m_monitors;
};
#endif // INTEGRATIONPLUGINHEIDELBERG_H

View File

@ -0,0 +1,219 @@
{
"name": "amperfied",
"displayName": "Amperfied",
"id": "2c463ff6-eea8-4977-a0b7-28b70399925b",
"vendors": [
{
"name": "amperfied",
"displayName": "Amperfied",
"id": "0f1d4317-fd3d-4f1e-b92a-d48df03d94e9",
"thingClasses": [
{
"name": "energyControl",
"displayName": "Energy Control",
"id": "5b87b9ab-c78b-48c2-9f5f-5a4efebd2c58",
"createMethods": ["discovery", "user"],
"interfaces": ["evcharger", "smartmeterconsumer", "connectable"],
"paramTypes": [
{
"id": "22aa91ef-d6bc-4ea3-b4c5-c2f773d86510",
"name":"rtuMaster",
"displayName": "Modbus RTU master",
"type": "QString",
"defaultValue": ""
},
{
"id": "fb3a1559-2fb8-4cc5-9b88-bde1714c746d",
"name":"slaveId",
"displayName": "Modbus slave ID",
"type": "uint",
"minValue": 1,
"maxValue": 248,
"defaultValue": 1
}
],
"stateTypes": [
{
"id": "ed520673-4474-4301-8665-47125e20b5c0",
"name": "connected",
"displayName": "Connected",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "22c107c6-a23b-40e4-918c-701bb0a9616e",
"name": "pluggedIn",
"displayName": "Plugged in",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "452e726a-256d-4e69-ac40-20f62c34e531",
"name": "charging",
"displayName": "Charging",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "a5254891-a60d-45b7-beee-a49688a09ca8",
"name": "phaseCount",
"displayName": "Connected phases",
"type": "uint",
"minValue": 1,
"maxValue": 3,
"defaultValue": 1
},
{
"id": "b7ea8449-c76f-4d42-8433-505f542abfd4",
"name": "currentPower",
"displayName": "Active power",
"type": "double",
"unit": "Watt",
"defaultValue": 0,
"cached": false
},
{
"id": "87269ace-fa6b-44a1-83d3-b2e834982407",
"name": "totalEnergyConsumed",
"displayName": "Total consumed energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.0,
"cached": true
},
{
"id": "bb119584-dec6-4bef-8b49-772feb8ca4dd",
"name": "power",
"displayName": "Charging enabled",
"displayNameAction": "Set charging enabled",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "7f7d729e-91e8-45c6-af40-442a47f63c23",
"name": "maxChargingCurrent",
"displayName": "Maximum charging current",
"displayNameAction": "Set maximum charging current",
"type": "uint",
"unit": "Ampere",
"minValue": 6,
"maxValue": 32,
"defaultValue": 6,
"writable": true
},
{
"id": "6fa264a2-96f4-43d1-b89f-06494830f225",
"name": "sessionEnergy",
"displayName": "Session energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0
}
]
},
{
"name": "connectHome",
"displayName": "connect.home",
"id": "f8805308-1ddd-496c-bea3-ef9163357bfa",
"createMethods": ["discovery", "user"],
"interfaces": ["evcharger", "smartmeterconsumer", "connectable"],
"paramTypes": [
{
"id": "b4b0556e-0d5d-4951-b5cd-e0c7986b8dcf",
"name":"macAddress",
"displayName": "MAC address",
"type": "QString",
"defaultValue": ""
}
],
"stateTypes": [
{
"id": "5ef1f3b5-d477-4458-a711-d3fa12a5fb75",
"name": "connected",
"displayName": "Connected",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "0ecb5575-2d6e-45e7-983d-af195aa1227f",
"name": "pluggedIn",
"displayName": "Plugged in",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "88605046-9a5f-4553-82dc-f5ba15be05d4",
"name": "charging",
"displayName": "Charging",
"type": "bool",
"defaultValue": false,
"cached": false
},
{
"id": "50b3df7c-a633-42d6-a690-9063b0c244f0",
"name": "phaseCount",
"displayName": "Connected phases",
"type": "uint",
"minValue": 1,
"maxValue": 3,
"defaultValue": 1
},
{
"id": "6221212e-e21d-4006-bfdc-90a8a50b2587",
"name": "currentPower",
"displayName": "Active power",
"type": "double",
"unit": "Watt",
"defaultValue": 0,
"cached": false
},
{
"id": "11531bb0-82e6-4d07-8d30-7682d538db68",
"name": "totalEnergyConsumed",
"displayName": "Total consumed energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0.0,
"cached": true
},
{
"id": "a109e222-86bd-4699-8ade-3da5a6304fa7",
"name": "power",
"displayName": "Charging enabled",
"displayNameAction": "Set charging enabled",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "9e114f85-6f66-4b78-8b03-5d6f191337ab",
"name": "maxChargingCurrent",
"displayName": "Maximum charging current",
"displayNameAction": "Set maximum charging current",
"type": "uint",
"unit": "Ampere",
"minValue": 6,
"maxValue": 32,
"defaultValue": 6,
"writable": true
},
{
"id": "0a3fd1a6-b952-4dd1-95d1-25dfe3b0ce2f",
"name": "sessionEnergy",
"displayName": "Session energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0
}
]
}
]
}
]
}

13
amperfied/meta.json Normal file
View File

@ -0,0 +1,13 @@
{
"title": "Amperfied",
"tagline": "Connect Amperfied/Heidelberg wallboxes to nymea.",
"icon": "amperfeid.jpg",
"stability": "consumer",
"offline": true,
"technologies": [
"network"
],
"categories": [
"energy"
]
}

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>IntegrationPluginAmperfied</name>
<message>
<location filename="../integrationpluginamperfied.cpp" line="54"/>
<source>No modbus RTU master with appropriate settings found. Please set up a modbus RTU master with a baudrate of 19200, 8 data bis, 1 stop bit and even parity first.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginamperfied.cpp" line="288"/>
<location filename="../integrationpluginamperfied.cpp" line="373"/>
<source>The firmware of this wallbox is too old. Please update the wallbox to at least firmware 1.0.7.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginamperfied.cpp" line="295"/>
<location filename="../integrationpluginamperfied.cpp" line="381"/>
<source>The wallbox is not responding</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>amperfied</name>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="58"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="61"/>
<source>Active power</source>
<extracomment>The name of the StateType ({6221212e-e21d-4006-bfdc-90a8a50b2587}) of ThingClass connectHome
----------
The name of the StateType ({b7ea8449-c76f-4d42-8433-505f542abfd4}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="64"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="67"/>
<source>Amperfied</source>
<extracomment>The name of the vendor ({0f1d4317-fd3d-4f1e-b92a-d48df03d94e9})
----------
The name of the plugin amperfied ({2c463ff6-eea8-4977-a0b7-28b70399925b})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="70"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="73"/>
<source>Charging</source>
<extracomment>The name of the StateType ({88605046-9a5f-4553-82dc-f5ba15be05d4}) of ThingClass connectHome
----------
The name of the StateType ({452e726a-256d-4e69-ac40-20f62c34e531}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="76"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="79"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="82"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="85"/>
<source>Charging enabled</source>
<extracomment>The name of the ParamType (ThingClass: connectHome, ActionType: power, ID: {a109e222-86bd-4699-8ade-3da5a6304fa7})
----------
The name of the StateType ({a109e222-86bd-4699-8ade-3da5a6304fa7}) of ThingClass connectHome
----------
The name of the ParamType (ThingClass: energyControl, ActionType: power, ID: {bb119584-dec6-4bef-8b49-772feb8ca4dd})
----------
The name of the StateType ({bb119584-dec6-4bef-8b49-772feb8ca4dd}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="88"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="91"/>
<source>Connected</source>
<extracomment>The name of the StateType ({5ef1f3b5-d477-4458-a711-d3fa12a5fb75}) of ThingClass connectHome
----------
The name of the StateType ({ed520673-4474-4301-8665-47125e20b5c0}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="94"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="97"/>
<source>Connected phases</source>
<extracomment>The name of the StateType ({50b3df7c-a633-42d6-a690-9063b0c244f0}) of ThingClass connectHome
----------
The name of the StateType ({a5254891-a60d-45b7-beee-a49688a09ca8}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="100"/>
<source>Energy Control</source>
<extracomment>The name of the ThingClass ({5b87b9ab-c78b-48c2-9f5f-5a4efebd2c58})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="103"/>
<source>MAC address</source>
<extracomment>The name of the ParamType (ThingClass: connectHome, Type: thing, ID: {b4b0556e-0d5d-4951-b5cd-e0c7986b8dcf})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="106"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="109"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="112"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="115"/>
<source>Maximum charging current</source>
<extracomment>The name of the ParamType (ThingClass: connectHome, ActionType: maxChargingCurrent, ID: {9e114f85-6f66-4b78-8b03-5d6f191337ab})
----------
The name of the StateType ({9e114f85-6f66-4b78-8b03-5d6f191337ab}) of ThingClass connectHome
----------
The name of the ParamType (ThingClass: energyControl, ActionType: maxChargingCurrent, ID: {7f7d729e-91e8-45c6-af40-442a47f63c23})
----------
The name of the StateType ({7f7d729e-91e8-45c6-af40-442a47f63c23}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="118"/>
<source>Modbus RTU master</source>
<extracomment>The name of the ParamType (ThingClass: energyControl, Type: thing, ID: {22aa91ef-d6bc-4ea3-b4c5-c2f773d86510})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="121"/>
<source>Modbus slave ID</source>
<extracomment>The name of the ParamType (ThingClass: energyControl, Type: thing, ID: {fb3a1559-2fb8-4cc5-9b88-bde1714c746d})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="124"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="127"/>
<source>Plugged in</source>
<extracomment>The name of the StateType ({0ecb5575-2d6e-45e7-983d-af195aa1227f}) of ThingClass connectHome
----------
The name of the StateType ({22c107c6-a23b-40e4-918c-701bb0a9616e}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="130"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="133"/>
<source>Session energy</source>
<extracomment>The name of the StateType ({0a3fd1a6-b952-4dd1-95d1-25dfe3b0ce2f}) of ThingClass connectHome
----------
The name of the StateType ({6fa264a2-96f4-43d1-b89f-06494830f225}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="136"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="139"/>
<source>Set charging enabled</source>
<extracomment>The name of the ActionType ({a109e222-86bd-4699-8ade-3da5a6304fa7}) of ThingClass connectHome
----------
The name of the ActionType ({bb119584-dec6-4bef-8b49-772feb8ca4dd}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="142"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="145"/>
<source>Set maximum charging current</source>
<extracomment>The name of the ActionType ({9e114f85-6f66-4b78-8b03-5d6f191337ab}) of ThingClass connectHome
----------
The name of the ActionType ({7f7d729e-91e8-45c6-af40-442a47f63c23}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="148"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="151"/>
<source>Total consumed energy</source>
<extracomment>The name of the StateType ({11531bb0-82e6-4d07-8d30-7682d538db68}) of ThingClass connectHome
----------
The name of the StateType ({87269ace-fa6b-44a1-83d3-b2e834982407}) of ThingClass energyControl</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/amperfied/plugininfo.h" line="154"/>
<source>connect.home</source>
<extracomment>The name of the ThingClass ({f8805308-1ddd-496c-bea3-ef9163357bfa})</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

9
debian/control vendored
View File

@ -78,6 +78,15 @@ Description: nymea integration plugin for alpha innotec heat pumps
This package contains the nymea integration plugin for alpha innotec head pumps.
Package: nymea-plugin-amperfied
Architecture: any
Section: libs
Depends: ${shlibs:Depends},
${misc:Depends},
Description: nymea integration plugin for Amperfeid/Heidelberg wallboxes
This package contains the nymea integration plugin for Amperfeid/Heidelberg wallboxes.
Package: nymea-plugin-bgetech
Architecture: any
Multi-Arch: same

View File

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

View File

@ -6,6 +6,7 @@ SUBDIRS += nymea-modbus-cli libnymea-modbus libnymea-sunspec
PLUGIN_DIRS = \
alphainnotec \
amperfied \
bgetech \
drexelundweiss \
huawei \