Update mtec plugin with network device discovery and internal connection mechanism
This commit is contained in:
parent
82dc46cd3b
commit
446b3e3dda
@ -28,6 +28,7 @@
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "network/networkdevicediscovery.h"
|
||||
#include "integrationpluginmtec.h"
|
||||
#include "plugininfo.h"
|
||||
|
||||
@ -38,81 +39,96 @@ IntegrationPluginMTec::IntegrationPluginMTec()
|
||||
|
||||
void IntegrationPluginMTec::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
qCDebug(dcMTec()) << "Discover M-Tec heat pumps";
|
||||
|
||||
if (info->thingClassId() == mtecThingClassId) {
|
||||
QString description = "Heatpump";
|
||||
ThingDescriptor descriptor(info->thingClassId(), "M-Tec", description);
|
||||
info->addThingDescriptor(descriptor);
|
||||
|
||||
// TODO Find out, if a discovery is possible/needed
|
||||
// Otherwise, just report no error for now
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
if (!hardwareManager()->networkDeviceDiscovery()->available()) {
|
||||
qCWarning(dcMTec()) << "The network discovery is not available on this platform.";
|
||||
info->finish(Thing::ThingErrorUnsupportedFeature, QT_TR_NOOP("The network device discovery is not available."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform a network device discovery and filter for "go-eCharger" hosts
|
||||
NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
|
||||
foreach (const NetworkDevice &networkDevice, discoveryReply->networkDevices()) {
|
||||
|
||||
qCDebug(dcMTec()) << "Found" << networkDevice;
|
||||
|
||||
QString title;
|
||||
if (networkDevice.hostName().isEmpty()) {
|
||||
title = networkDevice.address().toString();
|
||||
} else {
|
||||
title = networkDevice.hostName() + " (" + networkDevice.address().toString() + ")";
|
||||
}
|
||||
|
||||
QString description;
|
||||
if (networkDevice.macAddressManufacturer().isEmpty()) {
|
||||
description = networkDevice.macAddress();
|
||||
} else {
|
||||
description = networkDevice.macAddress() + " (" + networkDevice.macAddressManufacturer() + ")";
|
||||
}
|
||||
|
||||
ThingDescriptor descriptor(mtecThingClassId, title, description);
|
||||
ParamList params;
|
||||
params << Param(mtecThingIpAddressParamTypeId, networkDevice.address().toString());
|
||||
params << Param(mtecThingMacAddressParamTypeId, networkDevice.macAddress());
|
||||
descriptor.setParams(params);
|
||||
|
||||
// Check if we already have set up this device
|
||||
Things existingThings = myThings().filterByParam(mtecThingMacAddressParamTypeId, networkDevice.macAddress());
|
||||
if (existingThings.count() == 1) {
|
||||
qCDebug(dcMTec()) << "This heat pump already exists in the system!" << networkDevice;
|
||||
descriptor.setThingId(existingThings.first()->id());
|
||||
}
|
||||
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginMTec::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
qCDebug(dcMTec()) << "Setup" << info->thing();
|
||||
|
||||
Thing *thing = info->thing();
|
||||
qCDebug(dcMTec()) << "Setup" << thing;
|
||||
|
||||
if (thing->thingClassId() == mtecThingClassId) {
|
||||
QHostAddress hostAddress = QHostAddress(thing->paramValue(mtecThingIpAddressParamTypeId).toString());
|
||||
|
||||
if (hostAddress.isNull()) {
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("No IP address given"));
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcMTec()) << "User entered address: " << hostAddress.toString();
|
||||
|
||||
/* Check, if address is already in use for another device */
|
||||
/* for (QHash<Thing *, MTec *>::iterator item=m_mtecConnections.begin(); item != m_mtecConnections.end(); item++) { */
|
||||
/* if (hostAddress.isEqual(item.value()->getHostAddress())) { */
|
||||
/* qCDebug(dcMTec()) << "Address of thing: " << item.value()->getHostAddress().toString(); */
|
||||
|
||||
/* qCDebug(dcMTec()) << "Address in use already"; */
|
||||
/* } else { */
|
||||
/* qCDebug(dcMTec()) << "Different address of other thing: " << item.value()->getHostAddress().toString(); */
|
||||
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
foreach (MTec *mtecConnection, m_mtecConnections.values()) {
|
||||
if (mtecConnection->getHostAddress().isEqual(hostAddress)) {
|
||||
qCWarning(dcMTec()) << "Address" << hostAddress.toString() << "already in use by" << m_mtecConnections.key(mtecConnection);
|
||||
info->finish(Thing::ThingErrorThingInUse, QT_TR_NOOP("IP address already in use by another thing."));
|
||||
return;
|
||||
}
|
||||
qCDebug(dcMTec()) << "Using ip address" << hostAddress.toString();
|
||||
if (myThings().filterByParam(mtecThingIpAddressParamTypeId, hostAddress.toString()).count() > 0) {
|
||||
info->finish(Thing::ThingErrorThingInUse, QT_TR_NOOP("IP address already in use by another thing."));
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcMTec()) << "Creating M-Tec object";
|
||||
// TODO: start timer and give 15 seconds until connected, since the controler is down for ~10 seconds after a disconnect
|
||||
|
||||
/* Create new MTec object and store it in hash table */
|
||||
MTec *mtec = new MTec(hostAddress, this);
|
||||
m_mtecConnections.insert(thing, mtec);
|
||||
connect(mtec, &MTec::statusUpdated, this, &IntegrationPluginMTec::onStatusUpdated);
|
||||
connect(mtec, &MTec::connectedChanged, thing, [=](bool connected){
|
||||
qCDebug(dcMTec()) << "Connected changed to" << connected;
|
||||
thing->setStateValue(mtecConnectedStateTypeId, connected);
|
||||
});
|
||||
|
||||
m_mtecConnections.insert(thing, mtec);
|
||||
if (!mtec->connectDevice()) {
|
||||
qCWarning(dcMTec()) << "Initial connect returned false. Lets wait 15 seconds until the connection can be established.";
|
||||
}
|
||||
|
||||
info->thing()->setStateValue(mtecConnectedStateTypeId, true);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginMTec::postSetupThing(Thing *thing)
|
||||
{
|
||||
qCDebug(dcMTec()) << "PostSetup called for" << thing;
|
||||
|
||||
if (thing->thingClassId() == mtecThingClassId) {
|
||||
MTec *mtec = m_mtecConnections.value(thing);
|
||||
|
||||
if (mtec) {
|
||||
connect(mtec, &MTec::statusUpdated, this, &IntegrationPluginMTec::onStatusUpdated);
|
||||
connect(mtec, &MTec::connectedChanged, this, &IntegrationPluginMTec::onConnectedChanged);
|
||||
|
||||
qCDebug(dcMTec()) << "Thing set up, calling update";
|
||||
update(thing);
|
||||
|
||||
thing->setStateValue(mtecConnectedStateTypeId, true);
|
||||
//thing->setStateValue(mtecConnectedStateTypeId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,63 +142,38 @@ void IntegrationPluginMTec::thingRemoved(Thing *thing)
|
||||
|
||||
void IntegrationPluginMTec::executeAction(ThingActionInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
Action action = info->action();
|
||||
// Thing *thing = info->thing();
|
||||
// Action action = info->action();
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
if (thing->thingClassId() == mtecThingClassId) {
|
||||
/* if (action.actionTypeId() == mtecPowerActionTypeId) { */
|
||||
|
||||
/* } else { */
|
||||
/* Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8()); */
|
||||
/* } */
|
||||
} else {
|
||||
Q_ASSERT_X(false, "executeAction", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
}
|
||||
// if (thing->thingClassId() == mtecThingClassId) {
|
||||
// /* if (action.actionTypeId() == mtecPowerActionTypeId) { */
|
||||
|
||||
// } else {
|
||||
// Q_ASSERT_X(false, "executeAction", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
|
||||
// }
|
||||
}
|
||||
|
||||
void IntegrationPluginMTec::update(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == mtecThingClassId) {
|
||||
qCDebug(dcMTec()) << "Updating thing" << thing;
|
||||
|
||||
MTec *mtec = m_mtecConnections.value(thing);
|
||||
|
||||
if (mtec) {
|
||||
mtec->onRequestStatus();
|
||||
}
|
||||
if (!mtec) return;
|
||||
mtec->requestStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginMTec::onConnectedChanged(MTecHelpers::ConnectionState state)
|
||||
{
|
||||
MTec *mtec = qobject_cast<MTec *>(sender());
|
||||
Thing *thing = m_mtecConnections.key(mtec);
|
||||
|
||||
qCDebug(dcMTec()) << "Received connection change event from heat pump" << thing;
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
if (state == MTecHelpers::ConnectionState::Online) {
|
||||
thing->setStateValue(mtecConnectedStateTypeId, true);
|
||||
}
|
||||
|
||||
thing->setStateValue(mtecStatusStateTypeId, MTecHelpers::connectionStateToString(state));
|
||||
}
|
||||
|
||||
void IntegrationPluginMTec::onStatusUpdated(const MTecInfo &info)
|
||||
{
|
||||
MTec *mtec = qobject_cast<MTec *>(sender());
|
||||
Thing *thing = m_mtecConnections.key(mtec);
|
||||
|
||||
qCDebug(dcMTec()) << "Received status from heat pump" << thing;
|
||||
|
||||
if (!thing)
|
||||
return;
|
||||
|
||||
qCDebug(dcMTec()) << "Received status from heat pump" << thing;
|
||||
/* Received a structure holding the status info of the
|
||||
* heat pump. Update the thing states with the individual fields. */
|
||||
thing->setStateValue(mtecStatusStateTypeId, info.status);
|
||||
thing->setStateValue(mtecActualPowerConsumptionStateTypeId, info.actualPowerConsumption);
|
||||
thing->setStateValue(mtecActualExcessEnergySmartHomeStateTypeId, info.actualExcessEnergySmartHome);
|
||||
thing->setStateValue(mtecActualExcessEnergyElectricityMeterStateTypeId, info.actualExcessEnergyElectricityMeter);
|
||||
@ -192,8 +183,6 @@ void IntegrationPluginMTec::onStatusUpdated(const MTecInfo &info)
|
||||
|
||||
void IntegrationPluginMTec::onRefreshTimer()
|
||||
{
|
||||
qCDebug(dcMTec()) << "onRefreshTimer called";
|
||||
|
||||
foreach (Thing *thing, myThings().filterByThingClassId(mtecThingClassId)) {
|
||||
update(thing);
|
||||
}
|
||||
|
||||
@ -51,19 +51,16 @@ public:
|
||||
|
||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
|
||||
|
||||
private:
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
private:
|
||||
QHash<Thing *, MTec *> m_mtecConnections;
|
||||
|
||||
void update(Thing *thing);
|
||||
|
||||
QHash<Thing *, MTec *> m_mtecConnections;
|
||||
QHash<QUuid, ThingActionInfo *> m_asyncActions;
|
||||
|
||||
private slots:
|
||||
void onConnectedChanged(MTecHelpers::ConnectionState state);
|
||||
void onRefreshTimer();
|
||||
void onStatusUpdated(const MTecInfo &info);
|
||||
|
||||
|
||||
@ -8,98 +8,94 @@
|
||||
"displayName": "M-Tec",
|
||||
"id": "04d3fa7c-e469-4a79-a119-155426e5a846",
|
||||
"thingClasses": [
|
||||
{
|
||||
"name": "mtec",
|
||||
"displayName": "MTec",
|
||||
"id": "451e38d8-50d5-4ae9-8d9f-21af9347128d",
|
||||
"createMethods": ["user"],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "f1c43b1e-cffe-4d30-bda0-c23ed648dd71",
|
||||
"name": "ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "8d64954a-855d-44ea-8bc9-88a71ab47b6b",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "9bf5f8d6-116a-4399-a728-51470a3a5620",
|
||||
"name": "status",
|
||||
"displayName": "Status",
|
||||
"displayNameEvent": "Status changed",
|
||||
"type": "QString",
|
||||
"defaultValue": "Off",
|
||||
"possibleValues": [
|
||||
"Off",
|
||||
"Connecting",
|
||||
"Connected",
|
||||
"Error"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c67c79cf-7369-409f-b170-16c4ece9d25a",
|
||||
"name": "actualPowerConsumption",
|
||||
"displayName": "Actual power consumption",
|
||||
"displayNameEvent": "Actual power consumption changed",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "663718fa-807e-4d85-bd78-61a65f8c0b5e",
|
||||
"name": "actualExcessEnergySmartHome",
|
||||
"displayName": "Actual excess energy from Smart home System",
|
||||
"displayNameEvent": "Actual excess energy from Smart home System changed",
|
||||
"displayNameAction": "Change actual excess energy from Smart home System",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "fd94d39c-0db6-497f-a0a5-6c5452cbcaaf",
|
||||
"name": "actualExcessEnergyElectricityMeter",
|
||||
"displayName": "Actual excess energy from Electricity Meter",
|
||||
"displayNameEvent": "Actual excess energy from Electricity Meter changed",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "087c0296-705b-483a-b1e9-7ce08202c035",
|
||||
"name": "externalSetValueScaling",
|
||||
"displayName": "Control of the heat source by an external control [100%]",
|
||||
"displayNameEvent": "Control of the heat source by an external control [100%] changed",
|
||||
"type": "double",
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 100
|
||||
},
|
||||
{
|
||||
"id": "90b17788-ce63-47e3-b97d-1b025a41ce35",
|
||||
"name": "requestExternalHeatSource",
|
||||
"displayName": "Request external heat source",
|
||||
"displayNameEvent": "Request external heat source changed",
|
||||
"type": "QString",
|
||||
"defaultValue": "No request, external heat source must be turned off",
|
||||
"possibleValues": [
|
||||
"No request, external heat source must be turned off",
|
||||
"External heat source is released and can be switched on",
|
||||
"External heat source is required and must be turned on"
|
||||
"name": "mtec",
|
||||
"displayName": "MTec",
|
||||
"id": "451e38d8-50d5-4ae9-8d9f-21af9347128d",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"interfaces": ["connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "f1c43b1e-cffe-4d30-bda0-c23ed648dd71",
|
||||
"name": "ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": "127.0.0.1"
|
||||
},
|
||||
{
|
||||
"id": "906f6099-d0e1-4297-a2b3-f8ec4482c578",
|
||||
"name":"macAddress",
|
||||
"displayName": "MAC address",
|
||||
"type": "QString",
|
||||
"inputType": "MacAddress",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "8d64954a-855d-44ea-8bc9-88a71ab47b6b",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "c67c79cf-7369-409f-b170-16c4ece9d25a",
|
||||
"name": "actualPowerConsumption",
|
||||
"displayName": "Actual power consumption",
|
||||
"displayNameEvent": "Actual power consumption changed",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "663718fa-807e-4d85-bd78-61a65f8c0b5e",
|
||||
"name": "actualExcessEnergySmartHome",
|
||||
"displayName": "Actual excess energy from Smart home System",
|
||||
"displayNameEvent": "Actual excess energy from Smart home System changed",
|
||||
"displayNameAction": "Change actual excess energy from Smart home System",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "fd94d39c-0db6-497f-a0a5-6c5452cbcaaf",
|
||||
"name": "actualExcessEnergyElectricityMeter",
|
||||
"displayName": "Actual excess energy from Electricity Meter",
|
||||
"displayNameEvent": "Actual excess energy from Electricity Meter changed",
|
||||
"type": "double",
|
||||
"unit": "Watt",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "087c0296-705b-483a-b1e9-7ce08202c035",
|
||||
"name": "externalSetValueScaling",
|
||||
"displayName": "Control of the heat source by an external control [100%]",
|
||||
"displayNameEvent": "Control of the heat source by an external control [100%] changed",
|
||||
"type": "double",
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 100
|
||||
},
|
||||
{
|
||||
"id": "90b17788-ce63-47e3-b97d-1b025a41ce35",
|
||||
"name": "requestExternalHeatSource",
|
||||
"displayName": "Request external heat source",
|
||||
"displayNameEvent": "Request external heat source changed",
|
||||
"type": "QString",
|
||||
"defaultValue": "No request, external heat source must be turned off",
|
||||
"possibleValues": [
|
||||
"No request, external heat source must be turned off",
|
||||
"External heat source is released and can be switched on",
|
||||
"External heat source is required and must be turned on"
|
||||
]
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
]
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -39,13 +39,11 @@ MTec::MTec(const QHostAddress &address, QObject *parent) :
|
||||
m_hostAddress(address)
|
||||
{
|
||||
m_modbusMaster = new ModbusTCPMaster(address, 502, this);
|
||||
m_modbusMaster->setTimeout(2000);
|
||||
m_modbusMaster->setNumberOfRetries(5);
|
||||
|
||||
qCDebug(dcMTec()) << "created ModbusTCPMaster";
|
||||
|
||||
if (m_modbusMaster->connectDevice()) {
|
||||
emit connectedChanged(MTecHelpers::ConnectionState::Connecting);
|
||||
}
|
||||
|
||||
qCDebug(dcMTec()) << "Created ModbusTCPMaster for" << address.toString();
|
||||
connect(m_modbusMaster, &ModbusTCPMaster::connectionStateChanged, this, &MTec::connectedChanged);
|
||||
connect(m_modbusMaster, &ModbusTCPMaster::receivedHoldingRegister, this, &MTec::onReceivedHoldingRegister);
|
||||
connect(m_modbusMaster, &ModbusTCPMaster::readRequestError, this, &MTec::onModbusError);
|
||||
connect(m_modbusMaster, &ModbusTCPMaster::writeRequestError, this, &MTec::onModbusError);
|
||||
@ -55,59 +53,35 @@ MTec::~MTec()
|
||||
{
|
||||
}
|
||||
|
||||
void MTec::onModbusError()
|
||||
bool MTec::connectDevice()
|
||||
{
|
||||
qCWarning(dcMTec()) << "MTec: Received modbus error";
|
||||
|
||||
/* Only emit connected changed signal, if a soft connection
|
||||
* had already been established.
|
||||
* This avoids a series of possibly fake connection state changes,
|
||||
* while the modbus server in the heatpump is starting up. */
|
||||
if (m_softConnection) {
|
||||
m_softConnection = false;
|
||||
emit connectedChanged(MTecHelpers::ConnectionState::Offline);
|
||||
}
|
||||
return m_modbusMaster->connectDevice();
|
||||
}
|
||||
|
||||
void MTec::onRequestStatus()
|
||||
void MTec::disconnectDevice()
|
||||
{
|
||||
if ((m_softConnection) ||
|
||||
((m_connected) && (m_requestsSent < MTec::ConnectionRetries))) {
|
||||
m_modbusMaster->disconnectDevice();
|
||||
}
|
||||
|
||||
if (m_requestsSent < MTec::ConnectionRetries) {
|
||||
m_firstTimeout = QDateTime::currentDateTime();
|
||||
m_firstTimeout = m_firstTimeout.addSecs(MTec::FirstConnectionTimeout);
|
||||
|
||||
/* Save original modbus timeout, will be set again
|
||||
* after first response is received */
|
||||
m_modbusTimeout = m_modbusMaster->timeout();
|
||||
|
||||
/* The M-Tec heatpump requires a longer timeout to
|
||||
* start-up the modbus communication */
|
||||
m_modbusMaster->setTimeout(MTec::FirstConnectionTimeout);
|
||||
} else {
|
||||
/* Set back original modbus timeout */
|
||||
m_modbusMaster->setTimeout(m_modbusTimeout);
|
||||
}
|
||||
|
||||
} else {
|
||||
qCDebug(dcMTec()) << "Max number of modbus connects reached, giving up";
|
||||
void MTec::requestStatus()
|
||||
{
|
||||
if (!m_modbusMaster->connected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_modbusMaster->readHoldingRegister(MTec::ModbusUnitID, MTec::ActualPowerConsumption, 1);
|
||||
m_requestsSent ++;
|
||||
}
|
||||
|
||||
void MTec::onModbusError()
|
||||
{
|
||||
qCWarning(dcMTec()) << "MTec: Received modbus error";
|
||||
}
|
||||
|
||||
|
||||
void MTec::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value)
|
||||
{
|
||||
Q_UNUSED(slaveAddress);
|
||||
|
||||
/* Some response was received, so the modbus communication is
|
||||
* established. */
|
||||
m_softConnection = true;
|
||||
emit connectedChanged(MTecHelpers::ConnectionState::Online);
|
||||
|
||||
switch (modbusRegister) {
|
||||
case ActualPowerConsumption:
|
||||
if (value.length() == 1) {
|
||||
|
||||
30
mtec/mtec.h
30
mtec/mtec.h
@ -49,23 +49,17 @@ public:
|
||||
/** Destructor */
|
||||
~MTec();
|
||||
|
||||
inline QHostAddress getHostAddress() const { return m_hostAddress; };
|
||||
inline QHostAddress hostAddress() const { return m_hostAddress; };
|
||||
|
||||
bool connectDevice();
|
||||
void disconnectDevice();
|
||||
|
||||
void requestStatus();
|
||||
|
||||
private:
|
||||
/**
|
||||
* The first response of the M-Tec heatpump may be delayed
|
||||
* by 10 s. The plugin will wait for the defined time in milliseconds
|
||||
* for a response before sending an additional request or setting
|
||||
* an error code.
|
||||
*/
|
||||
static const int FirstConnectionTimeout = 15000;
|
||||
|
||||
/** Modbus Unit ID (undocumented, guessing 1 for now) */
|
||||
static const quint16 ModbusUnitID = 1;
|
||||
|
||||
/** Number of retries to establish a modbus connection with the heat pump */
|
||||
static const int ConnectionRetries = 3;
|
||||
|
||||
/** The following modbus addresses can be read: */
|
||||
enum RegisterList {
|
||||
/**
|
||||
@ -112,21 +106,13 @@ private:
|
||||
/** This structure is filled by the receivedStatus... functions */
|
||||
MTecInfo m_info ;
|
||||
|
||||
int m_requestsSent = 0;
|
||||
bool m_connected = false;
|
||||
bool m_softConnection = false;
|
||||
|
||||
QDateTime m_firstTimeout;
|
||||
|
||||
int m_modbusTimeout;
|
||||
|
||||
signals:
|
||||
void connectedChanged(MTecHelpers::ConnectionState state);
|
||||
void connectedChanged(bool connected);
|
||||
void statusUpdated(const MTecInfo &info);
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void onModbusError();
|
||||
void onRequestStatus();
|
||||
void onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector<quint16> &value);
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user