Merge PR #53: New Plugin: Schrack i-CHARGE CION

This commit is contained in:
jenkins 2022-04-25 23:54:53 +02:00
commit 70f8b12001
15 changed files with 1786 additions and 0 deletions

8
debian/control vendored
View File

@ -122,6 +122,14 @@ Description: nymea integration plugin for M-TEC heat pumps
This package contains the nymea integration plugin for M-TEC heat pumps.
Package: nymea-plugin-schrack
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
Description: nymea integration plugin for Schrack wallboxes
This package contains the nymea integration plugin for Schrack wallboxes.
Package: nymea-plugin-sunspec
Architecture: any
Depends: ${shlibs:Depends},

View File

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

View File

@ -14,6 +14,7 @@ PLUGIN_DIRS = \
modbuscommander \
mtec \
mypv \
schrack \
sunspec \
unipi \
wallbe \

View File

@ -15,3 +15,5 @@ isEmpty(PLUGIN_PRI) {
# message("Using $$PLUGIN_PRI")
include($$PLUGIN_PRI)
}
top_srcdir=$${PWD}

163
schrack/cion-registers.json Normal file
View File

@ -0,0 +1,163 @@
{
"protocol": "RTU",
"endianness": "LittleEndian",
"blocks": [
{
"id": "e3",
"readSchedule": "update",
"registers": [
{
"id": "currentChargingCurrentE3",
"address": 126,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Current charging Ampere",
"unit": "A",
"defaultValue": 6,
"access": "R"
},
{
"id": "maxChargingCurrentE3",
"address": 127,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Maximum charging current",
"unit": "A",
"defaultValue": 32,
"access": "R"
},
{
"id": "maxChargingCurrentCableE3",
"address": 128,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Maximum charging current of connected cable",
"unit": "A",
"defaultValue": 32,
"access": "R"
}
]
},
{
"id": "durations",
"readSchedule": "update",
"registers": [
{
"id": "chargingDuration",
"address": 151,
"size": 2,
"type": "uint32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Charging duration",
"unit": "ms",
"defaultValue": 0,
"access": "R"
},
{
"id": "pluggedInDuration",
"address": 153,
"size": 2,
"type": "uint32",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Plugged in duration",
"unit": "ms",
"defaultValue": 0,
"access": "R"
}
]
}
],
"registers": [
{
"id": "chargingEnabled",
"address": 100,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Charging enabled",
"defaultValue": 0,
"access": "RW"
},
{
"id": "chargingCurrentSetpoint",
"address": 101,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Charging current setpoint",
"unit": "A",
"defaultValue": 6,
"access": "RW"
},
{
"id": "statusBits",
"address": 121,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Mode3-State A, B, C, D, U",
"defaultValue": 85,
"access": "R"
},
{
"id": "cpSignalState",
"address": 139,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Status bits",
"defaultValue": 0,
"access": "R"
},
{
"id": "u1Voltage",
"address": 167,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "U1 voltage",
"staticScaleFactor": -2,
"unit": "V",
"defaultValue": 32,
"access": "R"
},
{
"id": "gridVoltage",
"address": 302,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Voltage of the power supply grid",
"staticScaleFactor": -2,
"unit": "V",
"defaultValue": 0,
"access": "R"
},
{
"id": "minChargingCurrent",
"address": 507,
"size": 1,
"type": "uint16",
"registerType": "holdingRegister",
"readSchedule": "update",
"description": "Minimum charging current",
"unit": "A",
"defaultValue": 13,
"access": "R"
}
]
}

BIN
schrack/cion-registers.pdf Normal file

Binary file not shown.

View File

@ -0,0 +1,723 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* WARNING
*
* This file has been autogenerated. Any changes in this file may be overwritten.
* If you want to change something, update the register json or the tool.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "cionmodbusrtuconnection.h"
#include "loggingcategories.h"
#include "math.h"
NYMEA_LOGGING_CATEGORY(dcCionModbusRtuConnection, "CionModbusRtuConnection")
CionModbusRtuConnection::CionModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent) :
QObject(parent),
m_modbusRtuMaster(modbusRtuMaster),
m_slaveId(slaveId)
{
}
ModbusRtuMaster *CionModbusRtuConnection::modbusRtuMaster() const
{
return m_modbusRtuMaster;
}
quint16 CionModbusRtuConnection::slaveId() const
{
return m_slaveId;
}
ModbusDataUtils::ByteOrder CionModbusRtuConnection::endianness() const
{
return m_endianness;
}
void CionModbusRtuConnection::setEndianness(ModbusDataUtils::ByteOrder endianness)
{
if (m_endianness == endianness)
return;
m_endianness = endianness;
emit endiannessChanged(m_endianness);
}
quint16 CionModbusRtuConnection::chargingEnabled() const
{
return m_chargingEnabled;
}
ModbusRtuReply *CionModbusRtuConnection::setChargingEnabled(quint16 chargingEnabled)
{
QVector<quint16> values = ModbusDataUtils::convertFromUInt16(chargingEnabled);
qCDebug(dcCionModbusRtuConnection()) << "--> Write \"Charging enabled\" register:" << 100 << "size:" << 1 << values;
return m_modbusRtuMaster->writeHoldingRegisters(m_slaveId, 100, values);
}
quint16 CionModbusRtuConnection::chargingCurrentSetpoint() const
{
return m_chargingCurrentSetpoint;
}
ModbusRtuReply *CionModbusRtuConnection::setChargingCurrentSetpoint(quint16 chargingCurrentSetpoint)
{
QVector<quint16> values = ModbusDataUtils::convertFromUInt16(chargingCurrentSetpoint);
qCDebug(dcCionModbusRtuConnection()) << "--> Write \"Charging current setpoint\" register:" << 101 << "size:" << 1 << values;
return m_modbusRtuMaster->writeHoldingRegisters(m_slaveId, 101, values);
}
quint16 CionModbusRtuConnection::statusBits() const
{
return m_statusBits;
}
quint16 CionModbusRtuConnection::cpSignalState() const
{
return m_cpSignalState;
}
float CionModbusRtuConnection::u1Voltage() const
{
return m_u1Voltage;
}
float CionModbusRtuConnection::gridVoltage() const
{
return m_gridVoltage;
}
quint16 CionModbusRtuConnection::minChargingCurrent() const
{
return m_minChargingCurrent;
}
quint16 CionModbusRtuConnection::currentChargingCurrentE3() const
{
return m_currentChargingCurrentE3;
}
quint16 CionModbusRtuConnection::maxChargingCurrentE3() const
{
return m_maxChargingCurrentE3;
}
quint16 CionModbusRtuConnection::maxChargingCurrentCableE3() const
{
return m_maxChargingCurrentCableE3;
}
quint32 CionModbusRtuConnection::chargingDuration() const
{
return m_chargingDuration;
}
quint32 CionModbusRtuConnection::pluggedInDuration() const
{
return m_pluggedInDuration;
}
void CionModbusRtuConnection::initialize()
{
// No init registers defined. Nothing to be done and we are finished.
emit initializationFinished();
}
void CionModbusRtuConnection::update()
{
updateChargingEnabled();
updateChargingCurrentSetpoint();
updateStatusBits();
updateCpSignalState();
updateU1Voltage();
updateGridVoltage();
updateMinChargingCurrent();
updateE3Block();
updateDurationsBlock();
}
void CionModbusRtuConnection::updateChargingEnabled()
{
// Update registers from Charging enabled
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Charging enabled\" register:" << 100 << "size:" << 1;
ModbusRtuReply *reply = readChargingEnabled();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Charging enabled\" register" << 100 << "size:" << 1 << values;
processChargingEnabledRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Charging enabled\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Charging enabled\" registers";
}
}
void CionModbusRtuConnection::updateChargingCurrentSetpoint()
{
// Update registers from Charging current setpoint
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Charging current setpoint\" register:" << 101 << "size:" << 1;
ModbusRtuReply *reply = readChargingCurrentSetpoint();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Charging current setpoint\" register" << 101 << "size:" << 1 << values;
processChargingCurrentSetpointRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Charging current setpoint\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Charging current setpoint\" registers";
}
}
void CionModbusRtuConnection::updateStatusBits()
{
// Update registers from Mode3-State A, B, C, D, U
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Mode3-State A, B, C, D, U\" register:" << 121 << "size:" << 1;
ModbusRtuReply *reply = readStatusBits();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Mode3-State A, B, C, D, U\" register" << 121 << "size:" << 1 << values;
processStatusBitsRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Mode3-State A, B, C, D, U\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Mode3-State A, B, C, D, U\" registers";
}
}
void CionModbusRtuConnection::updateCpSignalState()
{
// Update registers from Status bits
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Status bits\" register:" << 139 << "size:" << 1;
ModbusRtuReply *reply = readCpSignalState();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Status bits\" register" << 139 << "size:" << 1 << values;
processCpSignalStateRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Status bits\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Status bits\" registers";
}
}
void CionModbusRtuConnection::updateU1Voltage()
{
// Update registers from U1 voltage
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"U1 voltage\" register:" << 167 << "size:" << 1;
ModbusRtuReply *reply = readU1Voltage();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"U1 voltage\" register" << 167 << "size:" << 1 << values;
processU1VoltageRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"U1 voltage\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"U1 voltage\" registers";
}
}
void CionModbusRtuConnection::updateGridVoltage()
{
// Update registers from Voltage of the power supply grid
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Voltage of the power supply grid\" register:" << 302 << "size:" << 1;
ModbusRtuReply *reply = readGridVoltage();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Voltage of the power supply grid\" register" << 302 << "size:" << 1 << values;
processGridVoltageRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Voltage of the power supply grid\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Voltage of the power supply grid\" registers";
}
}
void CionModbusRtuConnection::updateMinChargingCurrent()
{
// Update registers from Minimum charging current
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Minimum charging current\" register:" << 507 << "size:" << 1;
ModbusRtuReply *reply = readMinChargingCurrent();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Minimum charging current\" register" << 507 << "size:" << 1 << values;
processMinChargingCurrentRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Minimum charging current\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Minimum charging current\" registers";
}
}
void CionModbusRtuConnection::updateCurrentChargingCurrentE3()
{
// Update registers from Current charging Ampere
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Current charging Ampere\" register:" << 126 << "size:" << 1;
ModbusRtuReply *reply = readCurrentChargingCurrentE3();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Current charging Ampere\" register" << 126 << "size:" << 1 << values;
processCurrentChargingCurrentE3RegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Current charging Ampere\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Current charging Ampere\" registers";
}
}
void CionModbusRtuConnection::updateMaxChargingCurrentE3()
{
// Update registers from Maximum charging current
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Maximum charging current\" register:" << 127 << "size:" << 1;
ModbusRtuReply *reply = readMaxChargingCurrentE3();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Maximum charging current\" register" << 127 << "size:" << 1 << values;
processMaxChargingCurrentE3RegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Maximum charging current\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Maximum charging current\" registers";
}
}
void CionModbusRtuConnection::updateMaxChargingCurrentCableE3()
{
// Update registers from Maximum charging current of connected cable
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Maximum charging current of connected cable\" register:" << 128 << "size:" << 1;
ModbusRtuReply *reply = readMaxChargingCurrentCableE3();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Maximum charging current of connected cable\" register" << 128 << "size:" << 1 << values;
processMaxChargingCurrentCableE3RegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Maximum charging current of connected cable\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Maximum charging current of connected cable\" registers";
}
}
void CionModbusRtuConnection::updateChargingDuration()
{
// Update registers from Charging duration
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Charging duration\" register:" << 151 << "size:" << 2;
ModbusRtuReply *reply = readChargingDuration();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Charging duration\" register" << 151 << "size:" << 2 << values;
processChargingDurationRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Charging duration\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Charging duration\" registers";
}
}
void CionModbusRtuConnection::updatePluggedInDuration()
{
// Update registers from Plugged in duration
qCDebug(dcCionModbusRtuConnection()) << "--> Read \"Plugged in duration\" register:" << 153 << "size:" << 2;
ModbusRtuReply *reply = readPluggedInDuration();
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> values = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from \"Plugged in duration\" register" << 153 << "size:" << 2 << values;
processPluggedInDurationRegisterValues(values);
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating \"Plugged in duration\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading \"Plugged in duration\" registers";
}
}
void CionModbusRtuConnection::updateE3Block()
{
// Update register block "e3"
qCDebug(dcCionModbusRtuConnection()) << "--> Read block \"e3\" registers from:" << 126 << "size:" << 3;
ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 126, 3);
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> blockValues = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from reading block \"e3\" register" << 126 << "size:" << 3 << blockValues;
processCurrentChargingCurrentE3RegisterValues(blockValues.mid(0, 1));
processMaxChargingCurrentE3RegisterValues(blockValues.mid(1, 1));
processMaxChargingCurrentCableE3RegisterValues(blockValues.mid(2, 1));
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"e3\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading block \"e3\" registers";
}
}
void CionModbusRtuConnection::updateDurationsBlock()
{
// Update register block "durations"
qCDebug(dcCionModbusRtuConnection()) << "--> Read block \"durations\" registers from:" << 151 << "size:" << 4;
ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, 151, 4);
if (reply) {
if (!reply->isFinished()) {
connect(reply, &ModbusRtuReply::finished, this, [this, reply](){
if (reply->error() == ModbusRtuReply::NoError) {
QVector<quint16> blockValues = reply->result();
qCDebug(dcCionModbusRtuConnection()) << "<-- Response from reading block \"durations\" register" << 151 << "size:" << 4 << blockValues;
processChargingDurationRegisterValues(blockValues.mid(0, 2));
processPluggedInDurationRegisterValues(blockValues.mid(2, 2));
}
});
connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){
qCWarning(dcCionModbusRtuConnection()) << "ModbusRtu reply error occurred while updating block \"durations\" registers" << error << reply->errorString();
emit reply->finished();
});
}
} else {
qCWarning(dcCionModbusRtuConnection()) << "Error occurred while reading block \"durations\" registers";
}
}
ModbusRtuReply *CionModbusRtuConnection::readChargingEnabled()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 100, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readChargingCurrentSetpoint()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 101, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readStatusBits()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 121, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readCpSignalState()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 139, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readU1Voltage()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 167, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readGridVoltage()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 302, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readMinChargingCurrent()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 507, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readCurrentChargingCurrentE3()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 126, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readMaxChargingCurrentE3()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 127, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readMaxChargingCurrentCableE3()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 128, 1);
}
ModbusRtuReply *CionModbusRtuConnection::readChargingDuration()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 151, 2);
}
ModbusRtuReply *CionModbusRtuConnection::readPluggedInDuration()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 153, 2);
}
ModbusRtuReply *CionModbusRtuConnection::readBlockE3()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 126, 3);
}
ModbusRtuReply *CionModbusRtuConnection::readBlockDurations()
{
return m_modbusRtuMaster->readHoldingRegister(m_slaveId, 151, 4);
}
void CionModbusRtuConnection::processChargingEnabledRegisterValues(const QVector<quint16> values)
{
quint16 receivedChargingEnabled = ModbusDataUtils::convertToUInt16(values);
if (m_chargingEnabled != receivedChargingEnabled) {
m_chargingEnabled = receivedChargingEnabled;
emit chargingEnabledChanged(m_chargingEnabled);
}
}
void CionModbusRtuConnection::processChargingCurrentSetpointRegisterValues(const QVector<quint16> values)
{
quint16 receivedChargingCurrentSetpoint = ModbusDataUtils::convertToUInt16(values);
if (m_chargingCurrentSetpoint != receivedChargingCurrentSetpoint) {
m_chargingCurrentSetpoint = receivedChargingCurrentSetpoint;
emit chargingCurrentSetpointChanged(m_chargingCurrentSetpoint);
}
}
void CionModbusRtuConnection::processStatusBitsRegisterValues(const QVector<quint16> values)
{
quint16 receivedStatusBits = ModbusDataUtils::convertToUInt16(values);
if (m_statusBits != receivedStatusBits) {
m_statusBits = receivedStatusBits;
emit statusBitsChanged(m_statusBits);
}
}
void CionModbusRtuConnection::processCpSignalStateRegisterValues(const QVector<quint16> values)
{
quint16 receivedCpSignalState = ModbusDataUtils::convertToUInt16(values);
if (m_cpSignalState != receivedCpSignalState) {
m_cpSignalState = receivedCpSignalState;
emit cpSignalStateChanged(m_cpSignalState);
}
}
void CionModbusRtuConnection::processU1VoltageRegisterValues(const QVector<quint16> values)
{
float receivedU1Voltage = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -2);
if (m_u1Voltage != receivedU1Voltage) {
m_u1Voltage = receivedU1Voltage;
emit u1VoltageChanged(m_u1Voltage);
}
}
void CionModbusRtuConnection::processGridVoltageRegisterValues(const QVector<quint16> values)
{
float receivedGridVoltage = ModbusDataUtils::convertToUInt16(values) * 1.0 * pow(10, -2);
if (m_gridVoltage != receivedGridVoltage) {
m_gridVoltage = receivedGridVoltage;
emit gridVoltageChanged(m_gridVoltage);
}
}
void CionModbusRtuConnection::processMinChargingCurrentRegisterValues(const QVector<quint16> values)
{
quint16 receivedMinChargingCurrent = ModbusDataUtils::convertToUInt16(values);
if (m_minChargingCurrent != receivedMinChargingCurrent) {
m_minChargingCurrent = receivedMinChargingCurrent;
emit minChargingCurrentChanged(m_minChargingCurrent);
}
}
void CionModbusRtuConnection::processCurrentChargingCurrentE3RegisterValues(const QVector<quint16> values)
{
quint16 receivedCurrentChargingCurrentE3 = ModbusDataUtils::convertToUInt16(values);
if (m_currentChargingCurrentE3 != receivedCurrentChargingCurrentE3) {
m_currentChargingCurrentE3 = receivedCurrentChargingCurrentE3;
emit currentChargingCurrentE3Changed(m_currentChargingCurrentE3);
}
}
void CionModbusRtuConnection::processMaxChargingCurrentE3RegisterValues(const QVector<quint16> values)
{
quint16 receivedMaxChargingCurrentE3 = ModbusDataUtils::convertToUInt16(values);
if (m_maxChargingCurrentE3 != receivedMaxChargingCurrentE3) {
m_maxChargingCurrentE3 = receivedMaxChargingCurrentE3;
emit maxChargingCurrentE3Changed(m_maxChargingCurrentE3);
}
}
void CionModbusRtuConnection::processMaxChargingCurrentCableE3RegisterValues(const QVector<quint16> values)
{
quint16 receivedMaxChargingCurrentCableE3 = ModbusDataUtils::convertToUInt16(values);
if (m_maxChargingCurrentCableE3 != receivedMaxChargingCurrentCableE3) {
m_maxChargingCurrentCableE3 = receivedMaxChargingCurrentCableE3;
emit maxChargingCurrentCableE3Changed(m_maxChargingCurrentCableE3);
}
}
void CionModbusRtuConnection::processChargingDurationRegisterValues(const QVector<quint16> values)
{
quint32 receivedChargingDuration = ModbusDataUtils::convertToUInt32(values, m_endianness);
if (m_chargingDuration != receivedChargingDuration) {
m_chargingDuration = receivedChargingDuration;
emit chargingDurationChanged(m_chargingDuration);
}
}
void CionModbusRtuConnection::processPluggedInDurationRegisterValues(const QVector<quint16> values)
{
quint32 receivedPluggedInDuration = ModbusDataUtils::convertToUInt32(values, m_endianness);
if (m_pluggedInDuration != receivedPluggedInDuration) {
m_pluggedInDuration = receivedPluggedInDuration;
emit pluggedInDurationChanged(m_pluggedInDuration);
}
}
void CionModbusRtuConnection::verifyInitFinished()
{
if (m_pendingInitReplies.isEmpty()) {
qCDebug(dcCionModbusRtuConnection()) << "Initialization finished of CionModbusRtuConnection";
emit initializationFinished();
}
}
QDebug operator<<(QDebug debug, CionModbusRtuConnection *cionModbusRtuConnection)
{
debug.nospace().noquote() << "CionModbusRtuConnection(" << cionModbusRtuConnection->modbusRtuMaster()->modbusUuid().toString() << ", " << cionModbusRtuConnection->modbusRtuMaster()->serialPort() << ", slave ID:" << cionModbusRtuConnection->slaveId() << ")" << "\n";
debug.nospace().noquote() << " - Charging enabled:" << cionModbusRtuConnection->chargingEnabled() << "\n";
debug.nospace().noquote() << " - Charging current setpoint:" << cionModbusRtuConnection->chargingCurrentSetpoint() << " [A]" << "\n";
debug.nospace().noquote() << " - Mode3-State A, B, C, D, U:" << cionModbusRtuConnection->statusBits() << "\n";
debug.nospace().noquote() << " - Status bits:" << cionModbusRtuConnection->cpSignalState() << "\n";
debug.nospace().noquote() << " - U1 voltage:" << cionModbusRtuConnection->u1Voltage() << " [V]" << "\n";
debug.nospace().noquote() << " - Voltage of the power supply grid:" << cionModbusRtuConnection->gridVoltage() << " [V]" << "\n";
debug.nospace().noquote() << " - Minimum charging current:" << cionModbusRtuConnection->minChargingCurrent() << " [A]" << "\n";
debug.nospace().noquote() << " - Current charging Ampere:" << cionModbusRtuConnection->currentChargingCurrentE3() << " [A]" << "\n";
debug.nospace().noquote() << " - Maximum charging current:" << cionModbusRtuConnection->maxChargingCurrentE3() << " [A]" << "\n";
debug.nospace().noquote() << " - Maximum charging current of connected cable:" << cionModbusRtuConnection->maxChargingCurrentCableE3() << " [A]" << "\n";
debug.nospace().noquote() << " - Charging duration:" << cionModbusRtuConnection->chargingDuration() << " [ms]" << "\n";
debug.nospace().noquote() << " - Plugged in duration:" << cionModbusRtuConnection->pluggedInDuration() << " [ms]" << "\n";
return debug.quote().space();
}

View File

@ -0,0 +1,231 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* WARNING
*
* This file has been autogenerated. Any changes in this file may be overwritten.
* If you want to change something, update the register json or the tool.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef CIONMODBUSRTUCONNECTION_H
#define CIONMODBUSRTUCONNECTION_H
#include <QObject>
#include "../modbus/modbusdatautils.h"
#include <hardware/modbus/modbusrtumaster.h>
class CionModbusRtuConnection : public QObject
{
Q_OBJECT
public:
enum Registers {
RegisterChargingEnabled = 100,
RegisterChargingCurrentSetpoint = 101,
RegisterStatusBits = 121,
RegisterCurrentChargingCurrentE3 = 126,
RegisterMaxChargingCurrentE3 = 127,
RegisterMaxChargingCurrentCableE3 = 128,
RegisterCpSignalState = 139,
RegisterChargingDuration = 151,
RegisterPluggedInDuration = 153,
RegisterU1Voltage = 167,
RegisterGridVoltage = 302,
RegisterMinChargingCurrent = 507
};
Q_ENUM(Registers)
explicit CionModbusRtuConnection(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent = nullptr);
~CionModbusRtuConnection() = default;
ModbusRtuMaster *modbusRtuMaster() const;
quint16 slaveId() const;
ModbusDataUtils::ByteOrder endianness() const;
void setEndianness(ModbusDataUtils::ByteOrder endianness);
/* Charging enabled - Address: 100, Size: 1 */
quint16 chargingEnabled() const;
ModbusRtuReply *setChargingEnabled(quint16 chargingEnabled);
/* Charging current setpoint [A] - Address: 101, Size: 1 */
quint16 chargingCurrentSetpoint() const;
ModbusRtuReply *setChargingCurrentSetpoint(quint16 chargingCurrentSetpoint);
/* Mode3-State A, B, C, D, U - Address: 121, Size: 1 */
quint16 statusBits() const;
/* Status bits - Address: 139, Size: 1 */
quint16 cpSignalState() const;
/* U1 voltage [V] - Address: 167, Size: 1 */
float u1Voltage() const;
/* Voltage of the power supply grid [V] - Address: 302, Size: 1 */
float gridVoltage() const;
/* Minimum charging current [A] - Address: 507, Size: 1 */
quint16 minChargingCurrent() const;
/* Current charging Ampere [A] - Address: 126, Size: 1 */
quint16 currentChargingCurrentE3() const;
/* Maximum charging current [A] - Address: 127, Size: 1 */
quint16 maxChargingCurrentE3() const;
/* Maximum charging current of connected cable [A] - Address: 128, Size: 1 */
quint16 maxChargingCurrentCableE3() const;
/* Charging duration [ms] - Address: 151, Size: 2 */
quint32 chargingDuration() const;
/* Plugged in duration [ms] - Address: 153, Size: 2 */
quint32 pluggedInDuration() const;
/* Read block from start addess 126 with size of 3 registers containing following 3 properties:
- Current charging Ampere [A] - Address: 126, Size: 1
- Maximum charging current [A] - Address: 127, Size: 1
- Maximum charging current of connected cable [A] - Address: 128, Size: 1
*/
void updateE3Block();
/* Read block from start addess 151 with size of 4 registers containing following 2 properties:
- Charging duration [ms] - Address: 151, Size: 2
- Plugged in duration [ms] - Address: 153, Size: 2
*/
void updateDurationsBlock();
virtual void initialize();
virtual void update();
void updateChargingEnabled();
void updateChargingCurrentSetpoint();
void updateStatusBits();
void updateCpSignalState();
void updateU1Voltage();
void updateGridVoltage();
void updateMinChargingCurrent();
void updateCurrentChargingCurrentE3();
void updateMaxChargingCurrentE3();
void updateMaxChargingCurrentCableE3();
void updateChargingDuration();
void updatePluggedInDuration();
ModbusRtuReply *readChargingEnabled();
ModbusRtuReply *readChargingCurrentSetpoint();
ModbusRtuReply *readStatusBits();
ModbusRtuReply *readCpSignalState();
ModbusRtuReply *readU1Voltage();
ModbusRtuReply *readGridVoltage();
ModbusRtuReply *readMinChargingCurrent();
ModbusRtuReply *readCurrentChargingCurrentE3();
ModbusRtuReply *readMaxChargingCurrentE3();
ModbusRtuReply *readMaxChargingCurrentCableE3();
ModbusRtuReply *readChargingDuration();
ModbusRtuReply *readPluggedInDuration();
/* Read block from start addess 126 with size of 3 registers containing following 3 properties:
- Current charging Ampere [A] - Address: 126, Size: 1
- Maximum charging current [A] - Address: 127, Size: 1
- Maximum charging current of connected cable [A] - Address: 128, Size: 1
*/
ModbusRtuReply *readBlockE3();
/* Read block from start addess 151 with size of 4 registers containing following 2 properties:
- Charging duration [ms] - Address: 151, Size: 2
- Plugged in duration [ms] - Address: 153, Size: 2
*/
ModbusRtuReply *readBlockDurations();
signals:
void initializationFinished();
void endiannessChanged(ModbusDataUtils::ByteOrder endianness);
void chargingEnabledChanged(quint16 chargingEnabled);
void chargingCurrentSetpointChanged(quint16 chargingCurrentSetpoint);
void statusBitsChanged(quint16 statusBits);
void cpSignalStateChanged(quint16 cpSignalState);
void u1VoltageChanged(float u1Voltage);
void gridVoltageChanged(float gridVoltage);
void minChargingCurrentChanged(quint16 minChargingCurrent);
void currentChargingCurrentE3Changed(quint16 currentChargingCurrentE3);
void maxChargingCurrentE3Changed(quint16 maxChargingCurrentE3);
void maxChargingCurrentCableE3Changed(quint16 maxChargingCurrentCableE3);
void chargingDurationChanged(quint32 chargingDuration);
void pluggedInDurationChanged(quint32 pluggedInDuration);
protected:
quint16 m_chargingEnabled = 0;
quint16 m_chargingCurrentSetpoint = 6;
quint16 m_statusBits = 85;
quint16 m_cpSignalState = 0;
float m_u1Voltage = 32;
float m_gridVoltage = 0;
quint16 m_minChargingCurrent = 13;
quint16 m_currentChargingCurrentE3 = 6;
quint16 m_maxChargingCurrentE3 = 32;
quint16 m_maxChargingCurrentCableE3 = 32;
quint32 m_chargingDuration = 0;
quint32 m_pluggedInDuration = 0;
void processChargingEnabledRegisterValues(const QVector<quint16> values);
void processChargingCurrentSetpointRegisterValues(const QVector<quint16> values);
void processStatusBitsRegisterValues(const QVector<quint16> values);
void processCpSignalStateRegisterValues(const QVector<quint16> values);
void processU1VoltageRegisterValues(const QVector<quint16> values);
void processGridVoltageRegisterValues(const QVector<quint16> values);
void processMinChargingCurrentRegisterValues(const QVector<quint16> values);
void processCurrentChargingCurrentE3RegisterValues(const QVector<quint16> values);
void processMaxChargingCurrentE3RegisterValues(const QVector<quint16> values);
void processMaxChargingCurrentCableE3RegisterValues(const QVector<quint16> values);
void processChargingDurationRegisterValues(const QVector<quint16> values);
void processPluggedInDurationRegisterValues(const QVector<quint16> values);
private:
ModbusRtuMaster *m_modbusRtuMaster = nullptr;
quint16 m_slaveId = 1;
QVector<ModbusRtuReply *> m_pendingInitReplies;
ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrderBigEndian;
void verifyInitFinished();
};
QDebug operator<<(QDebug debug, CionModbusRtuConnection *cionModbusRtuConnection);
#endif // CIONMODBUSRTUCONNECTION_H

View File

@ -0,0 +1,267 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, 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 "integrationpluginschrack.h"
#include "plugininfo.h"
IntegrationPluginSchrack::IntegrationPluginSchrack()
{
}
void IntegrationPluginSchrack::init()
{
}
void IntegrationPluginSchrack::discoverThings(ThingDiscoveryInfo *info)
{
qCDebug(dcSchrack()) << "Discovering modbus RTU resources...";
if (hardwareManager()->modbusRtuResource()->modbusRtuMasters().isEmpty()) {
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("No Modbus RTU interface available. Please set up a Modbus RTU interface first."));
return;
}
uint slaveAddress = info->params().paramValue(cionDiscoverySlaveAddressParamTypeId).toUInt();
if (slaveAddress > 254 || slaveAddress == 0) {
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The Modbus slave address must be a value between 1 and 254."));
return;
}
foreach (ModbusRtuMaster *modbusMaster, hardwareManager()->modbusRtuResource()->modbusRtuMasters()) {
qCDebug(dcSchrack()) << "Found RTU master resource" << modbusMaster << "connected" << modbusMaster->connected();
if (!modbusMaster->connected())
continue;
ThingDescriptor descriptor(info->thingClassId(), "i-CHARGE CION", QString::number(slaveAddress) + " " + modbusMaster->serialPort());
ParamList params;
params << Param(cionThingSlaveAddressParamTypeId, slaveAddress);
params << Param(cionThingModbusMasterUuidParamTypeId, modbusMaster->modbusUuid());
descriptor.setParams(params);
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
}
void IntegrationPluginSchrack::setupThing(ThingSetupInfo *info)
{
Thing *thing = info->thing();
qCDebug(dcSchrack()) << "Setup thing" << thing << thing->params();
uint address = thing->paramValue(cionThingSlaveAddressParamTypeId).toUInt();
if (address > 254 || address == 0) {
qCWarning(dcSchrack()) << "Setup failed, slave address is not valid" << address;
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus address not valid. It must be a value between 1 and 254."));
return;
}
QUuid uuid = thing->paramValue(cionThingModbusMasterUuidParamTypeId).toUuid();
if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(uuid)) {
qCWarning(dcSchrack()) << "Setup failed, hardware manager not available";
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus RTU resource is not available."));
return;
}
if (m_cionConnections.contains(thing)) {
qCDebug(dcSchrack()) << "Already have a CION connection for this thing. Cleaning up old connection and initializing new one...";
delete m_cionConnections.take(thing);
}
CionModbusRtuConnection *cionConnection = new CionModbusRtuConnection(hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, this);
// Note: This register really only tells us if we can control anything... i.e. if the wallbox is unlocked via RFID
connect(cionConnection, &CionModbusRtuConnection::chargingEnabledChanged, thing, [=](quint16 charging){
qCDebug(dcSchrack()) << "Charging enabled changed:" << charging;
});
// We can write chargingCurrentSetpoint to the preferred charging we want, and the wallbox will take it,
// however, it may not necessarily *do* it, but will give us the actual value it uses in currentChargingCurrentE3
// We'll use that for setting our state, just monitoring this one on the logs
// Setting this to 0 will pause charging, anything else will control the charging (and return the actual value in currentChargingCurrentE3)
connect(cionConnection, &CionModbusRtuConnection::chargingCurrentSetpointChanged, thing, [=](quint16 chargingCurrentSetpoint){
qCDebug(dcSchrack()) << "Charging current setpoint changed:" << chargingCurrentSetpoint;
});
connect(cionConnection, &CionModbusRtuConnection::cpSignalStateChanged, thing, [=](quint16 cpSignalState){
qCDebug(dcSchrack()) << "CP Signal state changed:" << (char)cpSignalState;
thing->setStateValue(cionPluggedInStateTypeId, cpSignalState >= 66);
});
connect(cionConnection, &CionModbusRtuConnection::currentChargingCurrentE3Changed, thing, [=](quint16 currentChargingCurrentE3){
qCDebug(dcSchrack()) << "Current charging current E3 current changed:" << currentChargingCurrentE3;
if (cionConnection->chargingCurrentSetpoint() > 0) {
thing->setStateValue(cionMaxChargingCurrentStateTypeId, currentChargingCurrentE3);
}
});
// The maxChargingCurrentE3 takes into account the DIP switches and connected cable, so this is effectively
// our maximum. However, it will go to 0 when unplugged, which is odd, so we'll ignore 0 values.
connect(cionConnection, &CionModbusRtuConnection::maxChargingCurrentE3Changed, thing, [=](quint16 maxChargingCurrentE3){
qCDebug(dcSchrack()) << "Maximum charging current E3 current changed:" << maxChargingCurrentE3;
if (maxChargingCurrentE3 != 0) {
thing->setStateMaxValue(cionMaxChargingCurrentStateTypeId, maxChargingCurrentE3);
}
});
connect(cionConnection, &CionModbusRtuConnection::statusBitsChanged, thing, [=](quint16 /*statusBits*/){
thing->setStateValue(cionConnectedStateTypeId, true);
// qCDebug(dcSchrack()) << "Status bits changed:" << statusBits;
});
connect(cionConnection, &CionModbusRtuConnection::minChargingCurrentChanged, thing, [=](quint16 minChargingCurrent){
qCDebug(dcSchrack()) << "Minimum charging current changed:" << minChargingCurrent;
thing->setStateMinValue(cionMaxChargingCurrentStateTypeId, minChargingCurrent);
});
connect(cionConnection, &CionModbusRtuConnection::gridVoltageChanged, thing, [=](float /*gridVoltage*/){
// qCDebug(dcSchrack()) << "Grid voltage changed:" << gridVoltage;
});
connect(cionConnection, &CionModbusRtuConnection::u1VoltageChanged, thing, [=](float /*u1Voltage*/){
// qCDebug(dcSchrack()) << "U1 voltage changed:" << u1Voltage;
});
connect(cionConnection, &CionModbusRtuConnection::pluggedInDurationChanged, thing, [=](quint32 /*pluggedInDuration*/){
// qCDebug(dcSchrack()) << "Plugged in duration changed:" << pluggedInDuration;
// Not reliable to determine if plugged in!
// thing->setStateValue(cionPluggedInStateTypeId, pluggedInDuration > 0);
});
connect(cionConnection, &CionModbusRtuConnection::chargingDurationChanged, thing, [=](quint32 chargingDuration){
// qCDebug(dcSchrack()) << "Charging duration changed:" << chargingDuration;
thing->setStateValue(cionChargingStateTypeId, chargingDuration > 0);
});
cionConnection->update();
// Initialize min/max to their defaults. If both, nymea and the wallbox are restarted simultaneously, nymea would cache the min/max while
// the wallbox would revert to its defaults, and being the default, the modbusconnection also never emits "changed" signals for them.
// To prevent running out of sync we'll "uncache" min/max values too.
thing->setStateMinMaxValues(cionMaxChargingCurrentStateTypeId, 6, 32);
m_cionConnections.insert(thing, cionConnection);
info->finish(Thing::ThingErrorNoError);
}
void IntegrationPluginSchrack::postSetupThing(Thing *thing)
{
qCDebug(dcSchrack()) << "Post setup thing" << thing->name();
if (!m_refreshTimer) {
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(2);
connect(m_refreshTimer, &PluginTimer::timeout, this, [this] {
foreach (Thing *thing, myThings()) {
CionModbusRtuConnection *connection = m_cionConnections.value(thing);
connection->update();
// The only apparent way to know whether it is charging, is to compare if lastChargingDuration has changed
// If it didn't change in the last cycle
qulonglong lastChargingDuration = connection->property("lastChargingDuration").toULongLong();
thing->setStateValue(cionChargingStateTypeId, connection->chargingDuration() != lastChargingDuration);
connection->setProperty("lastChargingDuration", connection->chargingDuration());
// Reading the CP signal state to know if the wallbox is reachable.
// Note that this is also an "update" register, hence being read twice.
// We'll not actually evaluate the actual results in here because
// this piece of code should be replaced with the modbus tool internal connected detection when it's ready
ModbusRtuReply *reply = connection->readCpSignalState();
connect(reply, &ModbusRtuReply::finished, thing, [reply, thing, this](){
// qCDebug(dcSchrack) << "CP signal state reply finished" << reply->error();
thing->setStateValue(cionConnectedStateTypeId, reply->error() == ModbusRtuReply::NoError);
// The Cion seems to crap out rather often and needs to be reconnected :/
if (reply->error() == ModbusRtuReply::TimeoutError) {
QUuid uuid = thing->paramValue(cionThingModbusMasterUuidParamTypeId).toUuid();
hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid)->requestReconnect();
}
});
}
});
qCDebug(dcSchrack()) << "Starting refresh timer...";
m_refreshTimer->start();
}
}
void IntegrationPluginSchrack::thingRemoved(Thing *thing)
{
qCDebug(dcSchrack()) << "Thing removed" << thing->name();
if (m_cionConnections.contains(thing))
m_cionConnections.take(thing)->deleteLater();
if (myThings().isEmpty() && m_refreshTimer) {
qCDebug(dcSchrack()) << "Stopping reconnect timer";
hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer);
m_refreshTimer = nullptr;
}
}
void IntegrationPluginSchrack::executeAction(ThingActionInfo *info)
{
CionModbusRtuConnection *cionConnection = m_cionConnections.value(info->thing());
if (info->action().actionTypeId() == cionPowerActionTypeId) {
qCDebug(dcSchrack()) << "Setting charging enabled:" << (info->action().paramValue(cionPowerActionPowerParamTypeId).toBool() ? 1 : 0);
int maxSetPoint = info->thing()->stateValue(cionMaxChargingCurrentStateTypeId).toUInt();
// If user enables it, we'll write the maxChargingPower value
if (info->action().paramValue(cionPowerActionPowerParamTypeId).toBool()) {
ModbusRtuReply *reply = cionConnection->setChargingCurrentSetpoint(maxSetPoint);
waitForActionFinish(info, reply, cionPowerStateTypeId, true);
} else { // we'll write 0 to the max charging power
ModbusRtuReply *reply = cionConnection->setChargingCurrentSetpoint(0);
waitForActionFinish(info, reply, cionPowerStateTypeId, false);
}
} else if (info->action().actionTypeId() == cionMaxChargingCurrentActionTypeId) {
// If charging is set to enabled, we'll write the value to the wallbox
if (info->thing()->stateValue(cionPowerStateTypeId).toBool()) {
int maxChargingCurrent = info->action().paramValue(cionMaxChargingCurrentActionMaxChargingCurrentParamTypeId).toUInt();
ModbusRtuReply *reply = cionConnection->setChargingCurrentSetpoint(maxChargingCurrent);
waitForActionFinish(info, reply, cionMaxChargingCurrentStateTypeId, maxChargingCurrent);
} else { // we'll just memorize what the user wants in our state and write it when enabled is set to true
info->thing()->setStateValue(cionMaxChargingCurrentStateTypeId, info->action().paramValue(cionMaxChargingCurrentActionMaxChargingCurrentParamTypeId));
info->finish(Thing::ThingErrorNoError);
}
}
Q_ASSERT_X(false, "IntegrationPluginSchrack::executeAction", QString("Unhandled action: %1").arg(info->action().actionTypeId().toString()).toLocal8Bit());
}
void IntegrationPluginSchrack::waitForActionFinish(ThingActionInfo *info, ModbusRtuReply *reply, const StateTypeId &stateTypeId, const QVariant &value)
{
connect(reply, &ModbusRtuReply::finished, info, [=](){
info->finish(reply->error() == ModbusRtuReply::NoError ? Thing::ThingErrorNoError : Thing::ThingErrorHardwareFailure);
if (reply->error() == ModbusRtuReply::NoError) {
info->thing()->setStateValue(stateTypeId, value);
}
});
}

View File

@ -0,0 +1,69 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2021, 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 INTEGRATIONPLUGINSCHRACK_H
#define INTEGRATIONPLUGINSCHRACK_H
#include <integrations/integrationplugin.h>
#include <hardware/modbus/modbusrtuhardwareresource.h>
#include <plugintimer.h>
#include "cionmodbusrtuconnection.h"
#include "extern-plugininfo.h"
#include <QObject>
#include <QTimer>
class IntegrationPluginSchrack : public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginschrack.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginSchrack();
void init() override;
void discoverThings(ThingDiscoveryInfo *info) override;
void setupThing(ThingSetupInfo *info) override;
void postSetupThing(Thing *thing) override;
void thingRemoved(Thing *thing) override;
void executeAction(ThingActionInfo *info) override;
private:
void waitForActionFinish(ThingActionInfo *info, ModbusRtuReply *reply, const StateTypeId &stateTypeId, const QVariant &value);
private:
PluginTimer *m_refreshTimer = nullptr;
QHash<Thing *, CionModbusRtuConnection *> m_cionConnections;
};
#endif // INTEGRATIONPLUGINSCHRACK_H

View File

@ -0,0 +1,98 @@
{
"name": "schrack",
"displayName": "Schrack",
"id": "600beeb5-5c34-49fc-b2af-8f83c1b11eab",
"paramTypes":[ ],
"vendors": [
{
"name": "schrack",
"displayName": "Schrack GmbH",
"id": "cadbbbc5-216f-4d25-a8ad-ccf653d1518f",
"thingClasses": [
{
"name": "cion",
"displayName": "i-CHARGE CION",
"id": "075d389d-3330-4d0b-9649-9f085120ca40",
"createMethods": ["discovery"],
"interfaces": ["evcharger", "connectable"],
"discoveryParamTypes": [
{
"id": "8004705f-0e13-4713-b75e-49d115cd9517",
"name": "slaveAddress",
"displayName": "Slave address",
"type": "int",
"defaultValue": 1
}
],
"paramTypes": [
{
"id": "dac10e08-734c-4e71-a5d6-0d2a1f416ca6",
"name": "slaveAddress",
"displayName": "Modbus slave address",
"type": "uint",
"defaultValue": 1
},
{
"id": "636241a9-4838-48ae-bcc8-3427ac3fc102",
"name": "modbusMasterUuid",
"displayName": "Modbus RTU master",
"type": "QUuid",
"defaultValue": "",
"readOnly": true
}
],
"stateTypes": [
{
"id": "b7aa8e49-a6c0-4b48-b65e-47259686185f",
"name": "connected",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "61aea53a-bf8d-4fe6-859a-f1687e15d190",
"name": "power",
"displayName": "Charging enabled",
"displayNameEvent": "Charging enabled or disabled",
"displayNameAction": "Enable or disable charging",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "221af869-a796-46c2-a5e0-27c8972a0bf2",
"name": "maxChargingCurrent",
"displayName": "Maximum charging current",
"displayNameEvent": "Maximum charging current changed",
"displayNameAction": "Set maximum charging current",
"type": "uint",
"unit": "Ampere",
"defaultValue": 6,
"minValue": 1,
"maxValue": 32,
"writable": true
},
{
"id": "13423618-4314-49be-b48c-42d9415199a8",
"name": "pluggedIn",
"displayName": "Plugged in",
"displayNameEvent": "Plugged or unplugged",
"type": "bool",
"defaultValue": false
},
{
"id": "b59b4b4d-2cdb-4534-bf86-90123ae9bb1a",
"name": "charging",
"displayName": "Charging",
"displayNameEvent": "Charging started or stopped",
"type": "bool",
"defaultValue": false
}
]
}
]
}
]
}

13
schrack/meta.json Normal file
View File

@ -0,0 +1,13 @@
{
"title": "Schrack",
"tagline": "Integrate the Schrack i-CHARGE CION wallbox with nymea.",
"icon": "schrack.jpg",
"stability": "consumer",
"offline": true,
"technologies": [
"modbus"
],
"categories": [
"energy"
]
}

BIN
schrack/schrack.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

20
schrack/schrack.pro Normal file
View File

@ -0,0 +1,20 @@
include(../plugins.pri)
QT += serialport serialbus
SOURCES += \
integrationpluginschrack.cpp \
cionmodbusrtuconnection.cpp \
../modbus/modbusdatautils.cpp
HEADERS += \
integrationpluginschrack.h \
cionmodbusrtuconnection.h \
../modbus/modbusdatautils.h
OTHER_FILES += cion-registers.json
modbusconnection.commands = python $${top_srcdir}/modbus/tools/generate-connection.py -j $${_PRO_FILE_PWD_}/cion-registers.json -o $${_PRO_FILE_PWD_} -c CionModbusRtuConnection
QMAKE_EXTRA_TARGETS += modbusconnection
#target.depends += modbusconnection

View File

@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>IntegrationPluginSchrack</name>
<message>
<location filename="../integrationpluginschrack.cpp" line="64"/>
<source>No Modbus RTU interface available. Please set up a Modbus RTU interface first.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginschrack.cpp" line="70"/>
<source>The Modbus slave address must be a value between 1 and 254.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginschrack.cpp" line="99"/>
<source>The Modbus address not valid. It must be a value between 1 and 254.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../integrationpluginschrack.cpp" line="106"/>
<source>The Modbus RTU resource is not available.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>schrack</name>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="56"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="59"/>
<source>Charging</source>
<extracomment>The name of the ParamType (ThingClass: cion, EventType: charging, ID: {b59b4b4d-2cdb-4534-bf86-90123ae9bb1a})
----------
The name of the StateType ({b59b4b4d-2cdb-4534-bf86-90123ae9bb1a}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="62"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="65"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="68"/>
<source>Charging enabled</source>
<extracomment>The name of the ParamType (ThingClass: cion, ActionType: power, ID: {61aea53a-bf8d-4fe6-859a-f1687e15d190})
----------
The name of the ParamType (ThingClass: cion, EventType: power, ID: {61aea53a-bf8d-4fe6-859a-f1687e15d190})
----------
The name of the StateType ({61aea53a-bf8d-4fe6-859a-f1687e15d190}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="71"/>
<source>Charging enabled or disabled</source>
<extracomment>The name of the EventType ({61aea53a-bf8d-4fe6-859a-f1687e15d190}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="74"/>
<source>Charging started or stopped</source>
<extracomment>The name of the EventType ({b59b4b4d-2cdb-4534-bf86-90123ae9bb1a}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="77"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="80"/>
<source>Connected</source>
<extracomment>The name of the ParamType (ThingClass: cion, EventType: connected, ID: {b7aa8e49-a6c0-4b48-b65e-47259686185f})
----------
The name of the StateType ({b7aa8e49-a6c0-4b48-b65e-47259686185f}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="83"/>
<source>Connected changed</source>
<extracomment>The name of the EventType ({b7aa8e49-a6c0-4b48-b65e-47259686185f}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="86"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="89"/>
<source>Current power consumption</source>
<extracomment>The name of the ParamType (ThingClass: cion, EventType: currentPower, ID: {db5c951f-47e0-4cdc-8b8b-285f7ed95285})
----------
The name of the StateType ({db5c951f-47e0-4cdc-8b8b-285f7ed95285}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="92"/>
<source>Current power consumption changed</source>
<extracomment>The name of the EventType ({db5c951f-47e0-4cdc-8b8b-285f7ed95285}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="95"/>
<source>Enable or disable charging</source>
<extracomment>The name of the ActionType ({61aea53a-bf8d-4fe6-859a-f1687e15d190}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="98"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="101"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="104"/>
<source>Maximum charging current</source>
<extracomment>The name of the ParamType (ThingClass: cion, ActionType: maxChargingCurrent, ID: {221af869-a796-46c2-a5e0-27c8972a0bf2})
----------
The name of the ParamType (ThingClass: cion, EventType: maxChargingCurrent, ID: {221af869-a796-46c2-a5e0-27c8972a0bf2})
----------
The name of the StateType ({221af869-a796-46c2-a5e0-27c8972a0bf2}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="107"/>
<source>Maximum charging current changed</source>
<extracomment>The name of the EventType ({221af869-a796-46c2-a5e0-27c8972a0bf2}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="110"/>
<source>Modbus RTU master</source>
<extracomment>The name of the ParamType (ThingClass: cion, Type: thing, ID: {636241a9-4838-48ae-bcc8-3427ac3fc102})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="113"/>
<source>Modbus slave address</source>
<extracomment>The name of the ParamType (ThingClass: cion, Type: thing, ID: {dac10e08-734c-4e71-a5d6-0d2a1f416ca6})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="116"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="119"/>
<source>Plugged in</source>
<extracomment>The name of the ParamType (ThingClass: cion, EventType: pluggedIn, ID: {13423618-4314-49be-b48c-42d9415199a8})
----------
The name of the StateType ({13423618-4314-49be-b48c-42d9415199a8}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="122"/>
<source>Plugged or unplugged</source>
<extracomment>The name of the EventType ({13423618-4314-49be-b48c-42d9415199a8}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="125"/>
<source>Schrack</source>
<extracomment>The name of the plugin schrack ({600beeb5-5c34-49fc-b2af-8f83c1b11eab})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="128"/>
<source>Schrack GmbH</source>
<extracomment>The name of the vendor ({cadbbbc5-216f-4d25-a8ad-ccf653d1518f})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="131"/>
<source>Set maximum charging current</source>
<extracomment>The name of the ActionType ({221af869-a796-46c2-a5e0-27c8972a0bf2}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="134"/>
<source>Slave address</source>
<extracomment>The name of the ParamType (ThingClass: cion, Type: discovery, ID: {8004705f-0e13-4713-b75e-49d115cd9517})</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="137"/>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="140"/>
<source>Total consumed energy</source>
<extracomment>The name of the ParamType (ThingClass: cion, EventType: totalEnergyConsumed, ID: {8390c005-a8ba-4db6-bb94-8f765ddcc784})
----------
The name of the StateType ({8390c005-a8ba-4db6-bb94-8f765ddcc784}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="143"/>
<source>Total consumed energy changed</source>
<extracomment>The name of the EventType ({8390c005-a8ba-4db6-bb94-8f765ddcc784}) of ThingClass cion</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../../build/nymea-plugins-modbus-Desktop-Debug/schrack/plugininfo.h" line="146"/>
<source>i-CHARGE CION</source>
<extracomment>The name of the ThingClass ({075d389d-3330-4d0b-9649-9f085120ca40})</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
</TS>