added set target temperature action

This commit is contained in:
Boernsman 2021-05-10 11:19:40 +02:00 committed by Michael Zanetti
parent f004899127
commit 4c1ec41a15
8 changed files with 94 additions and 57 deletions

View File

@ -46,6 +46,7 @@ Idm::Idm(const QHostAddress &address, QObject *parent) :
connect(m_modbusMaster, &ModbusTCPMaster::receivedHoldingRegister, this, &Idm::onReceivedHoldingRegister);
connect(m_modbusMaster, &ModbusTCPMaster::readRequestError, this, &Idm::onModbusError);
connect(m_modbusMaster, &ModbusTCPMaster::writeRequestError, this, &Idm::onModbusError);
connect(m_modbusMaster, &ModbusTCPMaster::writeRequestExecuted, this, &Idm::writeRequestExecuted);
}
}
@ -65,6 +66,18 @@ QHostAddress Idm::getIdmAddress() const
return m_hostAddress;
}
void Idm::getStatus()
{
//this request starts an update cycle
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::OutsideTemperature, 2);
}
QUuid Idm::setTargetTemperature(double targetTemperature)
{
QVector<uint16_t> value = ModbusHelpers::convertFloatToRegister(targetTemperature);
return m_modbusMaster->writeHoldingRegisters(Idm::modbusUnitID, Idm::RegisterList::RoomTemperatureTargetHeatingEcoHKA, value);
}
void Idm::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value)
{
Q_UNUSED(slaveAddress);
@ -74,81 +87,81 @@ void Idm::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const
case Idm::OutsideTemperature:
/* qCDebug(dcIdm()) << "received outside temperature"; */
if (value.length() == 2) {
m_info.outsideTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::OutsideTemperature - modbusRegister]);
m_idmInfo.outsideTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::OutsideTemperature - modbusRegister]);
}
QTimer::singleShot(200, this, [this] {
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::CurrentFaultNumber, 1);
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::CurrentFaultNumber, 1);
});
break;
case Idm::CurrentFaultNumber:
/* qCDebug(dcIdm()) << "current fault number"; */
if (value.length() == 1) {
if (value[0] > 0) {
m_info.error = true;
m_idmInfo.error = true;
} else {
m_info.error = false;
m_idmInfo.error = false;
}
}
QTimer::singleShot(200, this, [this] {
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::HeatStorageTemperature, 2);
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::HeatStorageTemperature, 2);
});
break;
case Idm::HeatStorageTemperature:
/* qCDebug(dcIdm()) << "received storage temperature"; */
if (value.length() == 2) {
m_info.waterTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::HeatStorageTemperature - modbusRegister]);
m_idmInfo.waterTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::HeatStorageTemperature - modbusRegister]);
}
QTimer::singleShot(200, this, [this] {
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::TargetHotWaterTemperature, 1);
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::TargetHotWaterTemperature, 1);
});
break;
case Idm::TargetHotWaterTemperature:
/* qCDebug(dcIdm()) << "received target hot water temperature"; */
if (value.length() == 1) {
/* The hot water target temperature is stored as UCHAR (manual p. 13) */
m_info.targetWaterTemperature = (double)value[RegisterList::TargetHotWaterTemperature - modbusRegister];
m_idmInfo.targetWaterTemperature = (double)value[RegisterList::TargetHotWaterTemperature - modbusRegister];
}
QTimer::singleShot(200, this, [this] {
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::HeatPumpOperatingMode, 1);
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::HeatPumpOperatingMode, 1);
});
break;
case Idm::HeatPumpOperatingMode:
/* qCDebug(dcIdm()) << "received heat pump operating mode"; */
if (value.length() == 1) {
m_info.mode = heatPumpOperationModeToString((Idm::IdmHeatPumpMode)value[RegisterList::HeatPumpOperatingMode-modbusRegister]);
m_idmInfo.mode = heatPumpOperationModeToString((Idm::IdmHeatPumpMode)value[RegisterList::HeatPumpOperatingMode-modbusRegister]);
}
QTimer::singleShot(200, this, [this] {
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::RoomTemperatureHKA, 2);
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::RoomTemperatureHKA, 2);
});
break;
case Idm::RoomTemperatureHKA:
/* qCDebug(dcIdm()) << "received room temperature hka"; */
if (value.length() == 2) {
m_info.roomTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::RoomTemperatureHKA - modbusRegister]);
m_idmInfo.roomTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::RoomTemperatureHKA - modbusRegister]);
}
QTimer::singleShot(200, this, [this] {
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::RoomTemperatureTargetHeatingEcoHKA, 2);
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::RoomTemperatureTargetHeatingEcoHKA, 2);
});
break;
case Idm::RoomTemperatureTargetHeatingEcoHKA:
/* qCDebug(dcIdm()) << "received room temprature hka eco"; */
if (value.length() == 2) {
m_info.targetRoomTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::RoomTemperatureTargetHeatingEcoHKA - modbusRegister]);
m_idmInfo.targetRoomTemperature = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::RoomTemperatureTargetHeatingEcoHKA - modbusRegister]);
}
QTimer::singleShot(200, this, [this] {
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::CurrentPowerConsumptionHeatPump, 2);
m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::CurrentPowerConsumptionHeatPump, 2);
});
break;
case Idm::CurrentPowerConsumptionHeatPump:
/* qCDebug(dcIdm()) << "received power consumption heat pump"; */
if (value.length() == 2) {
m_info.powerConsumptionHeatPump = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::CurrentPowerConsumptionHeatPump - modbusRegister]);
m_idmInfo.powerConsumptionHeatPump = ModbusHelpers::convertRegisterToFloat(&value[RegisterList::CurrentPowerConsumptionHeatPump - modbusRegister]);
}
/* Everything read without an error
* -> set connected to true */
m_info.connected = true;
emit statusUpdated(m_info);
m_idmInfo.connected = true;
emit statusUpdated(m_idmInfo);
break;
}
}
@ -156,13 +169,8 @@ void Idm::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const
void Idm::onModbusError()
{
qCDebug(dcIdm()) << "iDM: Received modbus error";
m_info.connected = false;
emit statusUpdated(m_info);
}
void Idm::onRequestStatus()
{
m_modbusMaster->readHoldingRegister(Idm::ModbusUnitID, Idm::OutsideTemperature, 2);
m_idmInfo.connected = false;
emit statusUpdated(m_idmInfo);
}
QString Idm::systemOperationModeToString(IdmSysMode mode)

View File

@ -73,12 +73,12 @@ public:
bool connectDevice();
QHostAddress getIdmAddress() const;
bool setTargetTemperature;
QUuid setTargetTemperature(double targetTemperature);
void getStatus();
private:
/** Modbus Unit ID of Idm device */
static const quint16 ModbusUnitID = 1;
static const quint16 modbusUnitID = 1;
enum IscModus {
KeineAbwarme = 0,
@ -160,12 +160,12 @@ private:
* within the IntegrationPluginIdm class. */
QHostAddress m_hostAddress;
/** Pointer to ModbusTCPMaster object, responseible for low-level communicaiton */
/** Pointer to ModbusTCPMaster object, responsible for low-level communicaiton */
ModbusTCPMaster *m_modbusMaster = nullptr;
/** This structure is allocated within onRequestStatus and filled
* by the receivedStatusGroupx functions */
IdmInfo m_info;
IdmInfo m_idmInfo;
/** Converts a system operation mode code to a string (according to manual p. 13) */
QString systemOperationModeToString(IdmSysMode mode);
@ -176,10 +176,10 @@ private:
signals:
void statusUpdated(const IdmInfo &info);
void targetRoomTemperatureChanged();
void writeRequestExecuted(const QUuid &requestId, bool success);
public slots:
private slots:
void onModbusError();
void onRequestStatus();
void onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value);
};

View File

@ -62,7 +62,7 @@ void IntegrationPluginIdm::setupThing(ThingSetupInfo *info)
Q_FOREACH (Idm *idm, m_idmConnections) {
if (hostAddress.isEqual(idm->getIdmAddress())) {
qCWarning(dcIdm()) << "Address already in use";
info->finish(Thing::ThingErrorSetupFailed, "IP address already in use");
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("IP address already in use"));
return;
}
}
@ -75,15 +75,18 @@ void IntegrationPluginIdm::setupThing(ThingSetupInfo *info)
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
m_idmConnections.insert(thing, idm);
connect(idm, &Idm::statusUpdated, info, [info] (const IdmInfo &idmInfo) {
connect(idm, &Idm::statusUpdated, info, [info, thing, idm, this] (const IdmInfo &idmInfo) {
if (idmInfo.connected) {
m_idmConnections.insert(thing, idm);
connect(idm, &Idm::statusUpdated, this, &IntegrationPluginIdm::onStatusUpdated);
connect(idm, &Idm::writeRequestExecuted, this, &IntegrationPluginIdm::onWriteRequestExecuted);
info->finish(Thing::ThingErrorNoError);
}
});
connect(idm, &Idm::destroyed, this, [thing, this] {m_idmConnections.remove(thing);});
connect(info, &ThingSetupInfo::aborted, idm, &Idm::deleteLater);
connect(idm, &Idm::statusUpdated, this, &IntegrationPluginIdm::onStatusUpdated);
} else {
Q_ASSERT_X(false, "setupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
@ -101,16 +104,14 @@ void IntegrationPluginIdm::postSetupThing(Thing *thing)
}
if (thing->thingClassId() == navigator2ThingClassId) {
qCDebug(dcIdm()) << "Thing id: " << thing->id();
Idm *idm = m_idmConnections.value(thing);
if (idm != nullptr) {
qCDebug(dcIdm()) << "Thing set up, calling update";
update(thing);
thing->setStateValue(navigator2ConnectedStateTypeId, true);
if (!idm) {
qCWarning(dcIdm()) << "Could not find any iDM connection for" << thing->name();
return;
}
thing->setStateValue(navigator2ConnectedStateTypeId, true);
update(thing);
}
}
@ -137,9 +138,14 @@ void IntegrationPluginIdm::executeAction(ThingActionInfo *info)
Action action = info->action();
if (thing->thingClassId() == navigator2ThingClassId) {
Idm *idm = m_idmConnections.value(thing);
if (!idm) {
return info->finish(Thing::ThingErrorHardwareFailure);
}
if (action.actionTypeId() == navigator2TargetTemperatureActionTypeId) {
double targetTemperature = thing->stateValue(navigator2TargetTemperatureStateTypeId).toDouble();
Q_UNUSED(targetTemperature);
QUuid requestId = idm->setTargetTemperature(targetTemperature);
m_asyncActions.insert(requestId, info);
} else {
Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8());
@ -152,13 +158,13 @@ void IntegrationPluginIdm::executeAction(ThingActionInfo *info)
void IntegrationPluginIdm::update(Thing *thing)
{
if (thing->thingClassId() == navigator2ThingClassId) {
qCDebug(dcIdm()) << "Updating thing";
qCDebug(dcIdm()) << "Updating thing" << thing->name();
Idm *idm = m_idmConnections.value(thing);
if (idm != nullptr) {
idm->onRequestStatus();
if (!idm) {
return;
}
idm->getStatus();
}
}
@ -186,6 +192,18 @@ void IntegrationPluginIdm::onStatusUpdated(const IdmInfo &info)
thing->setStateValue(navigator2ErrorStateTypeId, info.error);
}
void IntegrationPluginIdm::onWriteRequestExecuted(const QUuid &requestId, bool success)
{
if (m_asyncActions.contains(requestId)) {
ThingActionInfo *info = m_asyncActions.value(requestId);
if (success) {
info->finish(Thing::ThingErrorNoError);
} else {
info->finish(Thing::ThingErrorHardwareNotAvailable);
}
}
}
void IntegrationPluginIdm::onRefreshTimer()
{
qCDebug(dcIdm()) << "onRefreshTimer called";

View File

@ -38,7 +38,6 @@
#include <QUuid>
class IntegrationPluginIdm: public IntegrationPlugin
{
Q_OBJECT
@ -64,6 +63,8 @@ private:
private slots:
void onStatusUpdated(const IdmInfo &info);
void onWriteRequestExecuted(const QUuid &requestId, bool success);
};
#endif // INTEGRATIONPLUGINIDM_H

View File

@ -31,6 +31,7 @@
#include "modbushelpers.h"
float ModbusHelpers::convertRegisterToFloat(const quint16 *reg) {
float result = 0.0;
if (reg != nullptr) {
@ -47,12 +48,14 @@ float ModbusHelpers::convertRegisterToFloat(const quint16 *reg) {
return result;
}
void ModbusHelpers::convertFloatToRegister(QVector<quint16> &reg, float value) {
QVector<quint16> ModbusHelpers::convertFloatToRegister(float value)
{
quint32 tmp = 0;
memcpy((char *)&tmp, (char *)&value, sizeof(value));
QVector<quint16> reg;
reg.append((quint16)(tmp));
reg.append((quint16)((tmp & 0xFFFF0000) >> 16));
return reg;
}

View File

@ -37,7 +37,7 @@
class ModbusHelpers {
public:
static float convertRegisterToFloat(const quint16 *reg);
static void convertFloatToRegister(QVector<quint16> &reg, float value);
static QVector<quint16> convertFloatToRegister(float value);
};
#endif

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@ -63,7 +63,7 @@ ModbusTCPMaster::~ModbusTCPMaster()
}
bool ModbusTCPMaster::connectDevice() {
// TCP connction to target device
// TCP connection to target device
qCDebug(dcModbusTCP()) << "Setting up TCP connecion";
if (!m_modbusTcpClient)
@ -87,6 +87,11 @@ void ModbusTCPMaster::setTimeout(int timeout)
m_modbusTcpClient->setTimeout(timeout);
}
QString ModbusTCPMaster::errorString() const
{
return m_modbusTcpClient->errorString();
}
uint ModbusTCPMaster::port()
{
return m_modbusTcpClient->connectionParameter(QModbusDevice::NetworkPortParameter).toUInt();

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Copyright 2013 - 2021, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@ -37,7 +37,7 @@
#include <QTimer>
#include <QUuid>
Q_DECLARE_LOGGING_CATEGORY(dcModbus)
Q_DECLARE_LOGGING_CATEGORY(dcModbusTcp)
class ModbusTCPMaster : public QObject
{
@ -51,6 +51,8 @@ public:
void setNumberOfRetries(int number);
void setTimeout(int timeout);
QString errorString() const;
QUuid readCoil(uint slaveAddress, uint registerAddress, uint size = 1);
QUuid readDiscreteInput(uint slaveAddress, uint registerAddress, uint size = 1);
QUuid readInputRegister(uint slaveAddress, uint registerAddress, uint size = 1);