Readout working

master
Hermann Detz 2020-10-16 11:28:31 +02:00 committed by Michael Zanetti
parent bd5f3be35d
commit 9b346848a2
6 changed files with 179 additions and 44 deletions

View File

@ -29,16 +29,21 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "idm.h" #include "idm.h"
#include "../modbus/modbushelpers.h"
#include <cstring>
Idm::Idm(const QHostAddress &address, QObject *parent) : Idm::Idm(const QHostAddress &address, QObject *parent) :
QObject(parent), QObject(parent),
m_hostAddress(address) m_hostAddress(address)
{ {
/* qCDebug(dcIdm()) << "Creating Idm with addr: " << address; */
m_modbusMaster = new ModbusTCPMaster(address, 502, this); m_modbusMaster = new ModbusTCPMaster(address, 502, this);
connect(m_modbusMaster, &ModbusTCPMaster::receivedHoldingRegister, this, &Idm::onReceivedHoldingRegister); if (m_modbusMaster) {
m_modbusMaster->connectDevice();
connect(m_modbusMaster, &ModbusTCPMaster::receivedHoldingRegister, this, &Idm::onReceivedHoldingRegister);
}
} }
Idm::~Idm() Idm::~Idm()
@ -48,31 +53,104 @@ Idm::~Idm()
} }
} }
double Idm::getOutsideTemperature()
{
//m_modbusMaster->
return 0.0;
}
void Idm::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value) void Idm::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value)
{ {
/* qCDebug(dcIdm()) << "Idm::onReceivedHoldingRegister"; */
Q_UNUSED(slaveAddress); Q_UNUSED(slaveAddress);
Q_UNUSED(modbusRegister);
Q_UNUSED(value);
IdmInfo *info = new IdmInfo; switch (modbusRegister) {
info->m_outsideTemperature = 24.3; case Idm::OutsideTemperature:
if (value.length() == 2) {
m_info->m_roomTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::OutsideTemperature - modbusRegister]);
}
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::CurrentFaultNumber, 1);
break;
case Idm::CurrentFaultNumber:
if (value.length() == 1) {
if (value[0] > 0) {
m_info->m_error = true;
} else {
m_info->m_error = false;
}
}
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::TargetHotWaterTemperature, 2);
break;
case Idm::TargetHotWaterTemperature:
if (value.length() == 2) {
m_info->m_targetWaterTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::TargetHotWaterTemperature - modbusRegister]);
}
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::HeatPumpOperatingMode, 1);
break;
case Idm::HeatPumpOperatingMode:
if (value.length() == 1) {
printf("read heat pump operation mode: %d\n", value[0]);
m_info->m_mode = heatPumpOperationModeToString((Idm::IdmHeatPumpMode)value[RegisterList::HeatPumpOperatingMode-modbusRegister]);
}
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::ExternalOutsideTemperature, 2);
break;
case Idm::ExternalOutsideTemperature:
if (value.length() == 2) {
m_info->m_outsideTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::ExternalOutsideTemperature - modbusRegister]);
}
emit statusUpdated(info); emit statusUpdated(m_info);
break;
}
} }
void Idm::onRequestStatus() void Idm::onRequestStatus()
{ {
/* Reading a total of 16 bytes, starting from address 1000. m_info = new IdmInfo;
* This covers the following parameters:
* */ m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::OutsideTemperature, 2);
m_modbusMaster->readHoldingRegister(0xff, RegisterList::OutsideTemperature, 16); }
QString Idm::systemOperationModeToString(IdmSysMode mode) {
QString result{};
/* Operation modes according to table of manual p. 13 */
switch (mode) {
case IdmSysModeStandby:
result = "Standby";
break;
case IdmSysModeAutomatic:
result = "Automatik";
break;
case IdmSysModeAway:
result = "Abwesend";
break;
case IdmSysModeOnlyHotwater:
result = "Nur Warmwasser";
break;
case IdmSysModeOnlyRoomHeating:
result = "Nur Heizung/Kühlung";
break;
}
return result;
}
QString Idm::heatPumpOperationModeToString(IdmHeatPumpMode mode) {
QString result{};
/* Operation modes according to table of manual p. 14 */
switch (mode) {
case IdmHeatPumpModeOff:
result = "Off";
break;
case IdmHeatPumpModeHeating:
result = "Heating";
break;
case IdmHeatPumpModeCooling:
result = "Cooling";
break;
case IdmHeatPumpModeHotWater:
result = "Hot water";
break;
case IdmHeatPumpModeDefrost:
result = "Defrost";
break;
}
return result;
} }

View File

@ -41,13 +41,23 @@ class Idm : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
/** Constructor */
explicit Idm(const QHostAddress &address, QObject *parent = nullptr); explicit Idm(const QHostAddress &address, QObject *parent = nullptr);
~Idm();
double getOutsideTemperature();
//void getCurrentFaultNumber();
/** Destructor */
~Idm();
private: private:
/* Note: It would be desirable to read the modbus registers
* of the Idm heat pump in groups to minimize the number
* of read requests. However, a maximum of 6 registers
* can be read simultaneously. With the given set of
* addresses it is not possible to reasonably group the
* registers, therefore they are read individually.
*/
/** Modbus Unit ID of Idm device */
static const quint16 ModbusUnitID = 1;
enum IscModus { enum IscModus {
KeineAbwarme = 0, KeineAbwarme = 0,
@ -56,11 +66,29 @@ private:
Warmequelle = 8, Warmequelle = 8,
}; };
/** System operation modes according to manual p. 13 */
enum IdmSysMode {
IdmSysModeStandby = 0,
IdmSysModeAutomatic = 1,
IdmSysModeAway = 2,
IdmSysModeOnlyHotwater = 4,
IdmSysModeOnlyRoomHeating = 5
};
/** Heat pump operation modes according to manual p. 14 */
enum IdmHeatPumpMode {
IdmHeatPumpModeOff = 0,
IdmHeatPumpModeHeating = 1,
IdmHeatPumpModeCooling = 2,
IdmHeatPumpModeHotWater = 4,
IdmHeatPumpModeDefrost = 8
};
/** The following modbus addresses are according to the manual
* Modbus TCP Navigatorregelung 2.0 pages 13-31.
* Comments at the end of each line give their original name
* in the German manual. */
enum RegisterList { enum RegisterList {
/* The following modbus addresses are according to the manual
* Modbus TCP Navigatorregelung 2.0 pages 13-31.
* Comments at the end of each line give their original name
* in the German manual. */
OutsideTemperature = 1000, // Außentemperatur (B31) OutsideTemperature = 1000, // Außentemperatur (B31)
MeanOutsideTemperature = 1002, // Gemittelte Außentemperature MeanOutsideTemperature = 1002, // Gemittelte Außentemperature
CurrentFaultNumber = 1004, // Aktuelle Störungsnummer CurrentFaultNumber = 1004, // Aktuelle Störungsnummer
@ -75,6 +103,7 @@ private:
HeatPumpOperatingMode = 1090, // Betriebsart Wärmepumpe HeatPumpOperatingMode = 1090, // Betriebsart Wärmepumpe
SummationFaultHeatPump = 1099, // Summenstörung Wärepumpe SummationFaultHeatPump = 1099, // Summenstörung Wärepumpe
Humiditysensor = 1392, // Feuchtesensor Humiditysensor = 1392, // Feuchtesensor
RoomTemperatureTargetHeatingHKA = 1401, // Raumsolltemperatur Heizen Normal HK A
ExternalOutsideTemperature = 1690, // Externe Außentemperatur ExternalOutsideTemperature = 1690, // Externe Außentemperatur
ExternalHumidity = 1692, // Externe Feuchte ExternalHumidity = 1692, // Externe Feuchte
ExternalRequestTemperatureHeating = 1694, // Externe Anforderungstemperatur Heizen ExternalRequestTemperatureHeating = 1694, // Externe Anforderungstemperatur Heizen
@ -97,6 +126,7 @@ private:
SolarOperatingMode = 1856, // Betriebsart Solar SolarOperatingMode = 1856, // Betriebsart Solar
ISCMode = 1875, // ISCModus ISCMode = 1875, // ISCModus
AcknowledgeFaultMessages = 1999, // Störmeldungen quittieren AcknowledgeFaultMessages = 1999, // Störmeldungen quittieren
TargetRoomTemperatureZ1R1 = 2004, // Zonenmodul 1 Raumsolltemperatur Raum 1
CurrentPhotovoltaicsSurplus = 74, // Aktueller PV-Überschuss CurrentPhotovoltaicsSurplus = 74, // Aktueller PV-Überschuss
CurrentPhotovoltaicsProduction = 78, // Aktueller PV Produktion CurrentPhotovoltaicsProduction = 78, // Aktueller PV Produktion
CurrentPowerConsumption = 4122, // Aktuelle Leistungsaufnahme Wärmepumpe CurrentPowerConsumption = 4122, // Aktuelle Leistungsaufnahme Wärmepumpe
@ -106,18 +136,26 @@ private:
* TCP Modbus connection. Multiple devices are managed * TCP Modbus connection. Multiple devices are managed
* within the IntegrationPluginIdm class. */ * within the IntegrationPluginIdm class. */
QHostAddress m_hostAddress; QHostAddress m_hostAddress;
/** Pointer to ModbusTCPMaster object, responseible for low-level communicaiton */
ModbusTCPMaster *m_modbusMaster = nullptr; ModbusTCPMaster *m_modbusMaster = nullptr;
/** This structure is allocated within onRequestStatus and filled
* by the receivedStatusGroupx functions */
IdmInfo *m_info = nullptr;
/** Converts a system operation mode code to a string (according to manual p. 13) */
QString systemOperationModeToString(IdmSysMode mode);
/** Converts a heat pump operation mode code to a string (according to manual p. 14) */
QString heatPumpOperationModeToString(IdmHeatPumpMode mode);
signals: signals:
void statusUpdated(IdmInfo *info); void statusUpdated(IdmInfo *info);
private slots:
void onRequestStatus();
// only public for debugging!
public slots: public slots:
void onRequestStatus();
void onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value); void onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value);
}; };
#endif // IDM_H #endif // IDM_H

View File

@ -8,9 +8,12 @@ SOURCES += \
idm.cpp \ idm.cpp \
integrationpluginidm.cpp \ integrationpluginidm.cpp \
../modbus/modbustcpmaster.cpp \ ../modbus/modbustcpmaster.cpp \
../modbus/modbushelpers.cpp \
HEADERS += \ HEADERS += \
idm.h \ idm.h \
idminfo.h \ idminfo.h \
integrationpluginidm.h \ integrationpluginidm.h \
../modbus/modbustcpmaster.h \ ../modbus/modbustcpmaster.h \
../modbus/modbushelpers.h \

View File

@ -31,19 +31,40 @@
#ifndef IDMINFO_H #ifndef IDMINFO_H
#define IDMINFO_H #define IDMINFO_H
#include <QMetaType>
#include <QString> #include <QString>
/** This struct holds the status information that is read from the IDM device
* and passed to the nymea framework within this plugin.
*/
struct IdmInfo { struct IdmInfo {
bool m_connected; bool m_connected;
bool m_power; bool m_power;
/** RegisterList::OutsideTemperature */
double m_roomTemperature; double m_roomTemperature;
/** RegisterList::ExternalOutsideTemperature */
double m_outsideTemperature; double m_outsideTemperature;
/** RegisterList::HeatStorageTemperature */
double m_waterTemperature; double m_waterTemperature;
/** RegisterList::TargetRoomTemperatureZ1R1 (zone 1, room 1) */
double m_targetRoomTemperature; double m_targetRoomTemperature;
/** RegisterList::TargetHotWaterTemperature */
double m_targetWaterTemperature; double m_targetWaterTemperature;
/** RegisterList::OperationModeSystem */
QString m_mode; QString m_mode;
/** True if there is an error code set
* (RegisterList::CurrentFaultNumber != 0) */
bool m_error; bool m_error;
}; };
Q_DECLARE_METATYPE(IdmInfo);
#endif #endif

View File

@ -43,7 +43,7 @@ void IntegrationPluginIdm::discoverThings(ThingDiscoveryInfo *info)
// The plugin has a parameter for the IP address // The plugin has a parameter for the IP address
QString description = "Navigator 2"; QString description = "Navigator 2";
ThingDescriptor descriptor(info->thingClassId(), "", description); ThingDescriptor descriptor(info->thingClassId(), "Idm", description);
info->addThingDescriptor(descriptor); info->addThingDescriptor(descriptor);
// Just report no error for now, until the above question // Just report no error for now, until the above question
@ -58,8 +58,12 @@ void IntegrationPluginIdm::setupThing(ThingSetupInfo *info)
if (thing->thingClassId() == navigator2ThingClassId) { if (thing->thingClassId() == navigator2ThingClassId) {
QHostAddress hostAddress = QHostAddress(thing->paramValue(navigator2ThingIpAddressParamTypeId).toString()); QHostAddress hostAddress = QHostAddress(thing->paramValue(navigator2ThingIpAddressParamTypeId).toString());
/* Create new Idm object and store it in hash table */
Idm *idm = new Idm(hostAddress, this); Idm *idm = new Idm(hostAddress, this);
m_idmConnections.insert(thing, idm); m_idmConnections.insert(thing, idm);
/* Store thing info in hash table */
m_idmInfos.insert(thing, info); m_idmInfos.insert(thing, info);
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);
@ -119,10 +123,8 @@ void IntegrationPluginIdm::update(Thing *thing)
QVector<quint16> val{}; QVector<quint16> val{};
idm->onReceivedHoldingRegister(0, 1021, val); idm->onRequestStatus();
//idm->onRequestStatus();
//idm->readHoldingRegister(0xff, RegisterList::OutsideTemperature);
if (m_idmInfos.contains(thing)) { if (m_idmInfos.contains(thing)) {
ThingSetupInfo *info = m_idmInfos.take(thing); ThingSetupInfo *info = m_idmInfos.take(thing);
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);

View File

@ -48,6 +48,7 @@ class IntegrationPluginIdm: public IntegrationPlugin
public: public:
/** Constructor */
explicit IntegrationPluginIdm(); explicit IntegrationPluginIdm();
void discoverThings(ThingDiscoveryInfo *info) override; void discoverThings(ThingDiscoveryInfo *info) override;
@ -59,14 +60,6 @@ public:
private: private:
enum IdmSysMode {
IdmSysModeStandby = 0,
IdmSysModeAutomatic,
IdmSysModeAway,
IdmSysModeOnlyWarmwater,
IdmSysModeOnlyRoomHeating
};
enum IdmSmartGridMode { enum IdmSmartGridMode {
EVUSperreKeinPVErtrag, EVUSperreKeinPVErtrag,
EVUBezugKeinPVErtrag, EVUBezugKeinPVErtrag,