devices to things

This commit is contained in:
Boernsman 2020-06-15 22:26:36 +02:00
parent 344239fe0d
commit 197c1e0019
32 changed files with 910 additions and 834 deletions

View File

@ -1,78 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 DEVICEPLUGINDREXELUNDWEISS_H
#define DEVICEPLUGINDREXELUNDWEISS_H
#include "devices/devicemanager.h"
#include "plugintimer.h"
#include <QDateTime>
#include "modbusrtumaster.h"
#include <QSerialPortInfo>
class DevicePluginDrexelUndWeiss : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "deviceplugindrexelundweiss.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginDrexelUndWeiss();
~DevicePluginDrexelUndWeiss() override;
void init() override;
void discoverDevices(DeviceDiscoveryInfo *info) override;
void setupDevice(DeviceSetupInfo *info) override;
void postSetupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void executeAction(DeviceActionInfo *info) override;
private:
QList<QString> m_usedSerialPorts;
QHash<Device *, ModbusRTUMaster *> m_modbusRTUMasters;
PluginTimer *m_refreshTimer = nullptr;
QHash<QUuid, DeviceActionInfo *> m_pendingActions;
void updateStates(Device *device);
void discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress);
private slots:
void onRefreshTimer();
void onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value);
void onConnectionStateChanged(bool status);
void onReceivedCoil(int slaveAddress, int modbusRegister, bool value);
void onReceivedDiscreteInput(int slaveAddress, int modbusRegister, bool value);
void onReceivedHoldingRegister(int slaveAddress, int modbusRegister, int value);
void onReceivedInputRegister(int slaveAddress, int modbusRegister, int value);
void onWriteRequestFinished(QUuid requestId, bool success);
};
#endif // DEVICEPLUGINDREXELUNDWEISS_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -1,17 +1,15 @@
include(../plugins.pri)
TARGET = $$qtLibraryTarget(nymea_deviceplugindrexelundweiss)
QT += \
serialport \
serialbus \
SOURCES += \
deviceplugindrexelundweiss.cpp \
integrationplugindrexelundweiss.cpp \
modbusrtumaster.cpp \
HEADERS += \
deviceplugindrexelundweiss.h \
integrationplugindrexelundweiss.h \
modbusrtumaster.h \
modbusdegisterdefinition.h

View File

@ -1,55 +1,58 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 "deviceplugindrexelundweiss.h"
#include "integrationplugindrexelundweiss.h"
#include "plugininfo.h"
#include "modbusdegisterdefinition.h"
DevicePluginDrexelUndWeiss::DevicePluginDrexelUndWeiss()
IntegrationPluginDrexelUndWeiss::IntegrationPluginDrexelUndWeiss()
{
}
DevicePluginDrexelUndWeiss::~DevicePluginDrexelUndWeiss()
IntegrationPluginDrexelUndWeiss::~IntegrationPluginDrexelUndWeiss()
{
}
void DevicePluginDrexelUndWeiss::init()
void IntegrationPluginDrexelUndWeiss::init()
{
connect(this, &DevicePluginDrexelUndWeiss::configValueChanged, this, &DevicePluginDrexelUndWeiss::onPluginConfigurationChanged);
connect(this, &IntegrationPluginDrexelUndWeiss::configValueChanged, this, &IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged);
}
void DevicePluginDrexelUndWeiss::discoverDevices(DeviceDiscoveryInfo *info)
void IntegrationPluginDrexelUndWeiss::discoverThings(ThingDiscoveryInfo *info)
{
// Create the list of available serial interfaces
QList<DeviceDescriptor> deviceDescriptors;
QList<ThingDescriptor> thingDescriptors;
if (info->deviceClassId() == modbusConnectionDeviceClassId) {
if (info->thingClassId() == modbusConnectionThingClassId) {
Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
if (m_usedSerialPorts.contains(port.systemLocation())){
//device already in use
@ -58,87 +61,87 @@ void DevicePluginDrexelUndWeiss::discoverDevices(DeviceDiscoveryInfo *info)
//Serial port is not yet used, create now a new one
qCDebug(dcDrexelUndWeiss()) << "Found serial port:" << port.portName();
QString description = port.manufacturer() + " " + port.description();
DeviceDescriptor descriptor(info->deviceClassId(), port.portName(), description);
ThingDescriptor descriptor(info->thingClassId(), port.portName(), description);
ParamList parameters;
parameters.append(Param(modbusConnectionDeviceSerialPortParamTypeId, port.systemLocation()));
parameters.append(Param(modbusConnectionThingSerialPortParamTypeId, port.systemLocation()));
descriptor.setParams(parameters);
info->addDeviceDescriptor(descriptor);
info->addThingDescriptor(descriptor);
}
}
info->finish(Device::DeviceErrorNoError);
info->finish(Thing::ThingErrorNoError);
return;
}
if (info->deviceClassId() == x2luDeviceClassId) {
info->finish(Device::DeviceErrorNoError);
if (info->thingClassId() == x2luThingClassId) {
info->finish(Thing::ThingErrorNoError);
return;
}
if (info->deviceClassId() == x2wpDeviceClassId) {
info->finish(Device::DeviceErrorNoError);
if (info->thingClassId() == x2wpThingClassId) {
info->finish(Thing::ThingErrorNoError);
return;
}
info->finish(Device::DeviceErrorDeviceClassNotFound);
info->finish(Thing::ThingErrorDeviceClassNotFound);
return;
}
void DevicePluginDrexelUndWeiss::setupDevice(DeviceSetupInfo *info)
void IntegrationPluginDrexelUndWeiss::setupThing(ThingSetupInfo *info)
{
Device *device = info->device();
Thing *thing = info->thing();
if (device->deviceClassId() == modbusConnectionDeviceClassId) {
if (thing->thingClassId() == modbusConnectionThingClassId) {
QString serialPort = device->paramValue(modbusConnectionDeviceSerialPortParamTypeId).toString();
int baudRate = device->paramValue(modbusConnectionDeviceBaudRateParamTypeId).toInt();
QString serialPort = thing->paramValue(modbusConnectionThingSerialPortParamTypeId).toString();
int baudRate = thing->paramValue(modbusConnectionThingBaudRateParamTypeId).toInt();
ModbusRTUMaster *modbus = new ModbusRTUMaster(serialPort, baudRate, QSerialPort::Parity::NoParity, 8, 1, this);
connect(modbus, &ModbusRTUMaster::connectionStateChanged, this, &DevicePluginDrexelUndWeiss::onConnectionStateChanged);
connect(modbus, &ModbusRTUMaster::receivedCoil, this, &DevicePluginDrexelUndWeiss::onReceivedCoil);
connect(modbus, &ModbusRTUMaster::receivedDiscreteInput, this, &DevicePluginDrexelUndWeiss::onReceivedDiscreteInput);
connect(modbus, &ModbusRTUMaster::receivedHoldingRegister, this, &DevicePluginDrexelUndWeiss::onReceivedHoldingRegister);
connect(modbus, &ModbusRTUMaster::receivedInputRegister, this, &DevicePluginDrexelUndWeiss::onReceivedInputRegister);
connect(modbus, &ModbusRTUMaster::connectionStateChanged, this, &IntegrationPluginDrexelUndWeiss::onConnectionStateChanged);
connect(modbus, &ModbusRTUMaster::receivedCoil, this, &IntegrationPluginDrexelUndWeiss::onReceivedCoil);
connect(modbus, &ModbusRTUMaster::receivedDiscreteInput, this, &IntegrationPluginDrexelUndWeiss::onReceivedDiscreteInput);
connect(modbus, &ModbusRTUMaster::receivedHoldingRegister, this, &IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister);
connect(modbus, &ModbusRTUMaster::receivedInputRegister, this, &IntegrationPluginDrexelUndWeiss::onReceivedInputRegister);
m_modbusRTUMasters.insert(device, modbus);
m_modbusRTUMasters.insert(thing, modbus);
m_usedSerialPorts.append(serialPort);
info->finish(Device::DeviceErrorNoError);
info->finish(Thing::ThingErrorNoError);
return;
}
if (device->deviceClassId() == x2luDeviceClassId) {
info->finish(Device::DeviceErrorNoError);
if (thing->thingClassId() == x2luThingClassId) {
info->finish(Thing::ThingErrorNoError);
return;
}
if (device->deviceClassId() == x2wpDeviceClassId) {
info->finish(Device::DeviceErrorNoError);
if (thing->thingClassId() == x2wpThingClassId) {
info->finish(Thing::ThingErrorNoError);
return;
}
info->finish(Device::DeviceErrorDeviceClassNotFound);
info->finish(Thing::ThingErrorDeviceClassNotFound);
return;
}
void DevicePluginDrexelUndWeiss::postSetupDevice(Device *device)
void IntegrationPluginDrexelUndWeiss::postSetupDevice(Thing *thing)
{
if (!m_refreshTimer) {
// Refresh timer for TCP read
int refreshTime = configValue(drexelUndWeissPluginUpdateIntervalParamTypeId).toInt();
m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(refreshTime);
connect(m_refreshTimer, &PluginTimer::timeout, this, &DevicePluginDrexelUndWeiss::onRefreshTimer);
connect(m_refreshTimer, &PluginTimer::timeout, this, &IntegrationPluginDrexelUndWeiss::onRefreshTimer);
}
if (device->deviceClassId() == modbusConnectionDeviceClassId) {
if (thing->thingClassId() == modbusConnectionThingClassId) {
// read Register 5000 and emit auto-device
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(device);
if (!modbus){
qCWarning(dcDrexelUndWeiss()) << "No modbus master available";
}
device->setStateValue(modbusConnectionConnectedStateTypeId, true);
thing->setStateValue(modbusConnectionConnectedStateTypeId, true);
}
if ((device->deviceClassId() == x2luDeviceClassId) || (device->deviceClassId() == x2wpDeviceClassId)) {
Device *parentDevice = myDevices().findById(device->parentId());
if ((thing->thingClassId() == x2luThingClassId) || (thing->thingClassId() == x2wpThingClassId)) {
Device *parentDevice = myThings().findById(thing->parentId());
if (!parentDevice) {
qWarning(dcDrexelUndWeiss()) << "Could not find the parent device";
return;
@ -152,40 +155,40 @@ void DevicePluginDrexelUndWeiss::postSetupDevice(Device *device)
}
}
void DevicePluginDrexelUndWeiss::executeAction(DeviceActionInfo *info)
void IntegrationPluginDrexelUndWeiss::executeAction(DeviceActionInfo *info)
{
Device *device = info->device();
Thing *thing = info->device();
Action action = info->action();
if (device->deviceClassId() == modbusConnectionDeviceClassId) {
if (thing->thingClassId() == modbusConnectionThingClassId) {
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(device);
if (!modbus){
qCWarning(dcDrexelUndWeiss()) << "No modbus interface available";
info->finish(Device::DeviceErrorHardwareFailure);
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
if (action.actionTypeId() == modbusConnectionDiscoverDevicesActionTypeId) {
int slave = action.param(modbusConnectionDiscoverDevicesActionSlaveAddressParamTypeId).value().toInt();
discoverModbusSlaves(modbus, slave);
info->finish(Device::DeviceErrorNoError);
info->finish(Thing::ThingErrorNoError);
return;
} else {
info->finish(Device::DeviceErrorActionTypeNotFound);
info->finish(Thing::ThingErrorActionTypeNotFound);
}
} else if (device->deviceClassId() == x2luDeviceClassId) {
Device *parentDevice = myDevices().findById(device->parentId());
} else if (thing->thingClassId() == x2luThingClassId) {
Device *parentDevice = myThings().findById(thing->parentId());
if (!parentDevice) {
qWarning(dcDrexelUndWeiss()) << "Could not find the parent device";
info->finish(Device::DeviceErrorHardwareFailure);
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parentDevice);
int slave = device->paramValue(x2luDeviceSlaveAddressParamTypeId).toInt();
int slave = thing->paramValue(x2luThingSlaveAddressParamTypeId).toInt();
if (!modbus){
qCWarning(dcDrexelUndWeiss()) << "No modbus interface available";
info->finish(Device::DeviceErrorHardwareFailure);
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
@ -209,20 +212,20 @@ void DevicePluginDrexelUndWeiss::executeAction(DeviceActionInfo *info)
m_pendingActions.insert(modbus->writeHoldingRegister(slave, ModbusRegisterX2::Betriebsart, data), info);
return;
} else {
info->finish(Device::DeviceErrorActionTypeNotFound);
info->finish(Thing::ThingErrorActionTypeNotFound);
}
} else if (device->deviceClassId() == x2wpDeviceClassId) {
Device *parentDevice = myDevices().findById(device->parentId());
} else if (thing->thingClassId() == x2wpThingClassId) {
Device *parentDevice = myThings().findById(thing->parentId());
if (!parentDevice) {
qWarning(dcDrexelUndWeiss()) << "Could not find modbus interface";
info->finish(Device::DeviceErrorHardwareFailure);
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parentDevice);
int slave = device->paramValue(x2wpDeviceSlaveAddressParamTypeId).toInt();
int slave = thing->paramValue(x2wpThingSlaveAddressParamTypeId).toInt();
if (!modbus){
qCWarning(dcDrexelUndWeiss()) << "No modbus master available";
info->finish(Device::DeviceErrorHardwareFailure);
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
@ -237,17 +240,17 @@ void DevicePluginDrexelUndWeiss::executeAction(DeviceActionInfo *info)
m_pendingActions.insert(modbus->writeHoldingRegister(slave, ModbusRegisterX2::BrauchwasserSolltermperatur, data), info);
return;
} else {
info->finish(Device::DeviceErrorActionTypeNotFound);
info->finish(Thing::ThingErrorActionTypeNotFound);
}
} else {
info->finish(Device::DeviceErrorDeviceClassNotFound);
info->finish(Thing::ThingErrorDeviceClassNotFound);
}
}
void DevicePluginDrexelUndWeiss::deviceRemoved(Device *device)
void IntegrationPluginDrexelUndWeiss::deviceRemoved(Thing *thing)
{
if (device->deviceClassId() == modbusConnectionDeviceClassId) {
if (thing->thingClassId() == modbusConnectionThingClassId) {
ModbusRTUMaster *modbus = m_modbusRTUMasters.take(device);
if (!modbus){
@ -259,39 +262,39 @@ void DevicePluginDrexelUndWeiss::deviceRemoved(Device *device)
}
}
void DevicePluginDrexelUndWeiss::onRefreshTimer()
void IntegrationPluginDrexelUndWeiss::onRefreshTimer()
{
foreach (Device *device, myDevices()) {
foreach (Thing *thing, myThings()) {
if (device->deviceClassId() == modbusConnectionDeviceClassId) {
if (thing->thingClassId() == modbusConnectionThingClassId) {
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(device);
if (!modbus) {
qCWarning(dcDrexelUndWeiss()) << "No modbus master available";
return;
}
} else if (device->deviceClassId() == x2luDeviceClassId || device->deviceClassId() == x2wpDeviceClassId){
} else if (thing->thingClassId() == x2luThingClassId || thing->thingClassId() == x2wpThingClassId){
updateStates(device);
}
}
}
void DevicePluginDrexelUndWeiss::updateStates(Device *device)
void IntegrationPluginDrexelUndWeiss::updateStates(Thing *thing)
{
if (device->deviceClassId() == x2luDeviceClassId) {
Device *parent = myDevices().findById(device->parentId());
if (thing->thingClassId() == x2luThingClassId) {
Device *parent = myThings().findById(thing->parentId());
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parent);
int slave = device->paramValue(x2luDeviceSlaveAddressParamTypeId).toInt();
int slave = thing->paramValue(x2luThingSlaveAddressParamTypeId).toInt();
modbus->readHoldingRegister(slave, ModbusRegisterX2::AktiveLuefterstufe);
modbus->readHoldingRegister(slave, ModbusRegisterX2::Betriebsart); // Ventilation mode
modbus->readHoldingRegister(slave, ModbusRegisterX2::CO2);
}
if (device->deviceClassId() == x2wpDeviceClassId) {
Device *parent = myDevices().findById(device->parentId());
if (thing->thingClassId() == x2wpThingClassId) {
Device *parent = myThings().findById(thing->parentId());
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parent);
int slave = device->paramValue(x2wpDeviceSlaveAddressParamTypeId).toInt();
int slave = thing->paramValue(x2wpThingSlaveAddressParamTypeId).toInt();
modbus->readHoldingRegister(slave, ModbusRegisterX2::Waermepumpe);
modbus->readHoldingRegister(slave, ModbusRegisterX2::RaumSoll);
@ -312,7 +315,7 @@ void DevicePluginDrexelUndWeiss::updateStates(Device *device)
}
void DevicePluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value)
void IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value)
{
// Check refresh schedule
if (paramTypeId == drexelUndWeissPluginUpdateIntervalParamTypeId) {
@ -324,226 +327,226 @@ void DevicePluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTypeId
}
}
void DevicePluginDrexelUndWeiss::onConnectionStateChanged(bool status)
void IntegrationPluginDrexelUndWeiss::onConnectionStateChanged(bool status)
{
Q_UNUSED(status)
}
void DevicePluginDrexelUndWeiss::onReceivedCoil(int slaveAddress, int modbusRegister, bool value)
void IntegrationPluginDrexelUndWeiss::onReceivedCoil(int slaveAddress, int modbusRegister, bool value)
{
Q_UNUSED(slaveAddress)
Q_UNUSED(modbusRegister)
Q_UNUSED(value)
}
void DevicePluginDrexelUndWeiss::onReceivedDiscreteInput(int slaveAddress, int modbusRegister, bool value)
void IntegrationPluginDrexelUndWeiss::onReceivedDiscreteInput(int slaveAddress, int modbusRegister, bool value)
{
Q_UNUSED(slaveAddress)
Q_UNUSED(modbusRegister)
Q_UNUSED(value)
}
void DevicePluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, int value)
void IntegrationPluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, int value)
{
ModbusRTUMaster *modbus = static_cast<ModbusRTUMaster *>(sender());
if (m_modbusRTUMasters.values().contains(modbus) ){
Device *parentDevice = m_modbusRTUMasters.key(static_cast<ModbusRTUMaster *>(modbus));
foreach(Device *device, myDevices().filterByParentDeviceId(parentDevice->id())) {
if (device->deviceClassId() == x2luDeviceClassId && device->paramValue(x2luDeviceSlaveAddressParamTypeId) == slaveAddress) {
foreach(Thing *thing, myThings().filterByParentDeviceId(parentthing->id())) {
if (thing->thingClassId() == x2luThingClassId && thing->paramValue(x2luThingSlaveAddressParamTypeId) == slaveAddress) {
switch (modbusRegister) {
case ModbusRegisterX2::Waermepumpe:
device->setStateValue(x2wpPowerStateTypeId, value);
thing->setStateValue(x2wpPowerStateTypeId, value);
break;
case ModbusRegisterX2::RaumSoll:
device->setStateValue(x2wpTargetTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpTargetTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::Raum:
device->setStateValue(x2wpTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::TemperaturWarmwasserspeicherUnten:
device->setStateValue(x2wpWaterTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpWaterTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::BrauchwasserSolltermperatur:
device->setStateValue(x2wpTargetWaterTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpTargetWaterTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::Auszenluft:
device->setStateValue(x2wpOutsideAirTemperatureStateTypeId, value/1000.00);
thing->setStateValue(x2wpOutsideAirTemperatureStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::Summenstoerung:
if (value != 0) {
//get actual error
} else {
device->setStateValue(x2wpErrorStateTypeId, "No Error");
thing->setStateValue(x2wpErrorStateTypeId, "No Error");
}
break;
case ModbusRegisterX2::StoerungAbluftventilator:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Exhaust fan");
thing->setStateValue(x2wpErrorStateTypeId, "Exhaust fan");
break;
case ModbusRegisterX2::StoerungBoilerfuehlerElektroheizstab:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Boiler sensor electric heating element");
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor electric heating element");
break;
case ModbusRegisterX2::StoerungBoilerfuehlerSolar:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Boiler sensor solar");
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor solar");
break;
case ModbusRegisterX2::StoerungBoilerfuehlerWaermepumpe:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Boiler sensor heat pump");
thing->setStateValue(x2wpErrorStateTypeId, "Boiler sensor heat pump");
break;
case ModbusRegisterX2::StoerungBoileruebertemperatur:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Boiler overtemperature");
thing->setStateValue(x2wpErrorStateTypeId, "Boiler overtemperature");
break;
case ModbusRegisterX2::StoerungCO2Sensor:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "CO2-Sensor");
thing->setStateValue(x2wpErrorStateTypeId, "CO2-Sensor");
break;
case ModbusRegisterX2::StoerungDruckverlustAbluftZuGrosz:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Pressure loss exhaust air too big");
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss exhaust air too big");
break;
case ModbusRegisterX2::StoerungDruckverlustZuluftZuGrosz:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Pressure loss supply air too large");
thing->setStateValue(x2wpErrorStateTypeId, "Pressure loss supply air too large");
break;
case ModbusRegisterX2::StoerungDurchflussmengeHeizgkreis:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Flow rate of heating circuit");
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate of heating circuit");
break;
case ModbusRegisterX2::StoerungDurchflussmengeSolekreis:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Flow rate brine circuit");
thing->setStateValue(x2wpErrorStateTypeId, "Flow rate brine circuit");
break;
case ModbusRegisterX2::StoerungTeilnehmerNichtErreichbar:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Participant not available");
thing->setStateValue(x2wpErrorStateTypeId, "Participant not available");
break;
case ModbusRegisterX2::StoerungTemperaturfuehlerAuszenluft:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Temperature sensor outside air");
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor outside air");
break;
case ModbusRegisterX2::StoerungTemperaturfuehlerHeizkreisVorlauf:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Temperature sensor heating circuit flow");
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor heating circuit flow");
break;
case ModbusRegisterX2::StoerungTemperaturfuehlerRaum:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Temperature sensor room");
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor room");
break;
case ModbusRegisterX2::StoerungTemperaturfuehlerSolarkollektor:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Temperature sensor solar collector");
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor solar collector");
break;
case ModbusRegisterX2::StoerungTemperaturfuehlerSole:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine");
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine");
break;
case ModbusRegisterX2::StoerungTemperaturfuehlerSoleAuszenluft:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine outside air");
thing->setStateValue(x2wpErrorStateTypeId, "Temperature sensor brine outside air");
break;
case ModbusRegisterX2::StoerungWaermepumpeHochdruck:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Heat pump high pressure");
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump high pressure");
break;
case ModbusRegisterX2::StoerungWaermepumpeNiederdruck:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Heat pump low pressure");
thing->setStateValue(x2wpErrorStateTypeId, "Heat pump low pressure");
break;
case ModbusRegisterX2::StoerungWertNichtZulaessig:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Value not allowed");
thing->setStateValue(x2wpErrorStateTypeId, "Value not allowed");
break;
case ModbusRegisterX2::StoerungZuluftventilator:
if (value != 0)
device->setStateValue(x2wpErrorStateTypeId, "Supply air fan");
thing->setStateValue(x2wpErrorStateTypeId, "Supply air fan");
break;
case ModbusRegisterX2::LeistungKompressor:
device->setStateValue(x2wpPowerCompressorStateTypeId, value/1000.00);
thing->setStateValue(x2wpPowerCompressorStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::LeistungWarmwasser:
device->setStateValue(x2wpPowerWaterHeatingStateTypeId, value/1000.00);
thing->setStateValue(x2wpPowerWaterHeatingStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::LeistungRaumheizung:
device->setStateValue(x2wpPowerRoomHeatingStateTypeId, value/1000.00);
thing->setStateValue(x2wpPowerRoomHeatingStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::LeistungLuftvorwaermung:
device->setStateValue(x2wpPowerAirPreheatingStateTypeId, value/1000.00);
thing->setStateValue(x2wpPowerAirPreheatingStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::EnergieKompressor:
device->setStateValue(x2wpEnergyCompressorStateTypeId, value/1000.00);
thing->setStateValue(x2wpEnergyCompressorStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::EnergieWarmwasser:
device->setStateValue(x2wpEnergyWaterHeatingStateTypeId, value/1000.00);
thing->setStateValue(x2wpEnergyWaterHeatingStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::EnergieRaumheizung:
device->setStateValue(x2wpEnergyRoomHeatingStateTypeId, value/1000.00);
thing->setStateValue(x2wpEnergyRoomHeatingStateTypeId, value/1000.00);
break;
case ModbusRegisterX2::EnergieLuftvorerwarrmung:
device->setStateValue(x2wpEnergyAirPreheatingStateTypeId, value/1000.00);
thing->setStateValue(x2wpEnergyAirPreheatingStateTypeId, value/1000.00);
break;
default:
break;
}
} else if (device->deviceClassId() == x2wpDeviceClassId && device->paramValue(x2wpDeviceSlaveAddressParamTypeId) == slaveAddress) {
} else if (thing->thingClassId() == x2wpThingClassId && thing->paramValue(x2wpThingSlaveAddressParamTypeId) == slaveAddress) {
switch (modbusRegister) {
case ModbusRegisterX2::Betriebsart:
if (value == VentialtionMode::ManuellStufe0) {
device->setStateValue(x2luVentilationModeStateTypeId, "Manual level 0");
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 0");
} else if (value == VentialtionMode::ManuellStufe1) {
device->setStateValue(x2luVentilationModeStateTypeId, "Manual level 1");
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 1");
} else if (value == VentialtionMode::ManuellStufe2) {
device->setStateValue(x2luVentilationModeStateTypeId, "Manual level 2");
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 2");
} else if (value == VentialtionMode::ManuellStufe3) {
device->setStateValue(x2luVentilationModeStateTypeId, "Manual level 3");
thing->setStateValue(x2luVentilationModeStateTypeId, "Manual level 3");
} else if (value == VentialtionMode::Automatikbetrieb) {
device->setStateValue(x2luVentilationModeStateTypeId, "Automatic");
thing->setStateValue(x2luVentilationModeStateTypeId, "Automatic");
} else if (value == VentialtionMode::Party) {
device->setStateValue(x2luVentilationModeStateTypeId, "Party");
thing->setStateValue(x2luVentilationModeStateTypeId, "Party");
}
break;
case ModbusRegisterX2::AktiveLuefterstufe:
device->setStateValue(x2luActiveVentilationLevelStateTypeId, value);
thing->setStateValue(x2luActiveVentilationLevelStateTypeId, value);
break;
case ModbusRegisterX2::CO2:
device->setStateValue(x2luCo2StateTypeId, value);
thing->setStateValue(x2luCo2StateTypeId, value);
break;
}
}
@ -553,30 +556,30 @@ void DevicePluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress, int
switch (value) {
case DeviceType::X2_WP: {
qDebug(dcDrexelUndWeiss()) << "Discovered X2 heat pump";
QList<DeviceDescriptor> deviceDescriptors;
DeviceDescriptor descriptor(x2wpDeviceClassId, "X2 WP", "Drexel und Weiss", parentDevice->id());
QList<ThingDescriptor> thingDescriptors;
ThingDescriptor descriptor(x2wpThingClassId, "X2 WP", "Drexel und Weiss", parentthing->id());
ParamList params;
//modbus->readHoldingRegister(slaveAddress, ModbusRegisterX2::SoftwareVersion);
//params.append(Param(x2wpDeviceSofwareVersionParamTypeId, data));
params.append(Param(x2wpDeviceSlaveAddressParamTypeId, slaveAddress));
//params.append(Param(x2wpThingSofwareVersionParamTypeId, data));
params.append(Param(x2wpThingSlaveAddressParamTypeId, slaveAddress));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
emit autoDevicesAppeared(deviceDescriptors);
thingDescriptors.append(descriptor);
emit autoDevicesAppeared(thingDescriptors);
break;
}
case DeviceType::X2_LU: {
qDebug(dcDrexelUndWeiss()) << "Discovered X2 ventilation unit";
QList<DeviceDescriptor> deviceDescriptors;
DeviceDescriptor descriptor(x2luDeviceClassId, "X2 LU", "Drexel und Weiss", parentDevice->id());
QList<ThingDescriptor> thingDescriptors;
ThingDescriptor descriptor(x2luThingClassId, "X2 LU", "Drexel und Weiss", parentthing->id());
ParamList params;
//modbus->readHoldingRegister(slaveAddress, ModbusRegisterX2::SoftwareVersion);
//params.append(Param(x2luDeviceSofwareVersionParamTypeId, data));
params.append(Param(x2luDeviceSlaveAddressParamTypeId, slaveAddress));
//params.append(Param(x2luThingSofwareVersionParamTypeId, data));
params.append(Param(x2luThingSlaveAddressParamTypeId, slaveAddress));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
emit autoDevicesAppeared(deviceDescriptors);
thingDescriptors.append(descriptor);
emit autoDevicesAppeared(thingDescriptors);
break;
}
case DeviceType::AerosilentBianco:
@ -590,38 +593,38 @@ void DevicePluginDrexelUndWeiss::onReceivedHoldingRegister(int slaveAddress, int
}
}
void DevicePluginDrexelUndWeiss::onReceivedInputRegister(int slaveAddress, int modbusRegister, int value)
void IntegrationPluginDrexelUndWeiss::onReceivedInputRegister(int slaveAddress, int modbusRegister, int value)
{
Q_UNUSED(slaveAddress)
Q_UNUSED(modbusRegister)
Q_UNUSED(value)
}
void DevicePluginDrexelUndWeiss::onWriteRequestFinished(QUuid requestId, bool success)
void IntegrationPluginDrexelUndWeiss::onWriteRequestFinished(QUuid requestId, bool success)
{
DeviceActionInfo *info = m_pendingActions.take(requestId);
if (!info)
return;
if (success) {
info->finish(Device::DeviceErrorNoError);
info->finish(Thing::ThingErrorNoError);
} else {
info->finish(Device::DeviceErrorHardwareFailure);
info->finish(Thing::ThingErrorHardwareFailure);
}
}
void DevicePluginDrexelUndWeiss::discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress)
void IntegrationPluginDrexelUndWeiss::discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress)
{
foreach (Device *device, myDevices()) {
if (device->deviceClassId() == x2luDeviceClassId) {
if (device->paramValue(x2luDeviceSlaveAddressParamTypeId).toInt() == slaveAddress) {
foreach (Thing *thing, myThings()) {
if (thing->thingClassId() == x2luThingClassId) {
if (thing->paramValue(x2luThingSlaveAddressParamTypeId).toInt() == slaveAddress) {
qWarning(dcDrexelUndWeiss()) << "Device with slave address" << slaveAddress << "already added";
return;
}
}
if (device->deviceClassId() == x2wpDeviceClassId) {
if (device->paramValue(x2wpDeviceSlaveAddressParamTypeId).toInt() == slaveAddress) {
qWarning(dcDrexelUndWeiss()) << "Device with slave address" << slaveAddress << "already added";
if (thing->thingClassId() == x2wpThingClassId) {
if (thing->paramValue(x2wpThingSlaveAddressParamTypeId).toInt() == slaveAddress) {
qWarning(dcDrexelUndWeiss()) << "Thing with slave address" << slaveAddress << "already added";
return;
}
}

View File

@ -0,0 +1,81 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 INTEGRATIONPLUGINDREXELUNDWEISS_H
#define INTEGRATIONPLUGINDREXELUNDWEISS_H
#include "integrations/integrationplugin.h"
#include "plugintimer.h"
#include <QDateTime>
#include "modbusrtumaster.h"
#include <QSerialPortInfo>
class DevicePluginDrexelUndWeiss : public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationplugindrexelundweiss.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit DevicePluginDrexelUndWeiss();
~DevicePluginDrexelUndWeiss() override;
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:
QList<QString> m_usedSerialPorts;
QHash<Thing *, ModbusRTUMaster *> m_modbusRTUMasters;
PluginTimer *m_refreshTimer = nullptr;
QHash<QUuid, ThingActionInfo *> m_pendingActions;
void updateStates(Device *device);
void discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress);
private slots:
void onRefreshTimer();
void onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value);
void onConnectionStateChanged(bool status);
void onReceivedCoil(int slaveAddress, int modbusRegister, bool value);
void onReceivedDiscreteInput(int slaveAddress, int modbusRegister, bool value);
void onReceivedHoldingRegister(int slaveAddress, int modbusRegister, int value);
void onReceivedInputRegister(int slaveAddress, int modbusRegister, int value);
void onWriteRequestFinished(QUuid requestId, bool success);
};
#endif // INTEGRATIONPLUGINDREXELUNDWEISS_H

View File

@ -17,7 +17,7 @@
"name": "DrexelUndWeiss",
"displayName": "Drexel und Weiss",
"id": "9f476e8b-7e95-448e-b03b-874747e8fb1f",
"deviceClasses": [
"thingClasses": [
{
"name": "modbusConnection",
"displayName": "Modbus Connection",

13
drexelundweiss/meta.json Normal file
View File

@ -0,0 +1,13 @@
{
"title": "Drexel und Weiss",
"tagline": "Connect to Drexel und Weiss HVAC systems.",
"icon": "drexelundweiss.png",
"stability": "community",
"offline": true,
"technologies": [
"network"
],
"categories": [
"heating"
]
}

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 MODBUSDEGISTERDEFINITION
#define MODBUSDEGISTERDEFINITION

View File

@ -24,6 +24,7 @@
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "modbusrtumaster.h"
#include "extern-plugininfo.h"

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 MODBUSRTUMASTER_H
#define MODBUSRTUMASTER_H

View File

@ -1,87 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 DEVICEPLUGINMYPV_H
#define DEVICEPLUGINMYPV_H
#include "devices/deviceplugin.h"
#include "plugintimer.h"
#include "modbustcpmaster.h"
#include <QUdpSocket>
class DevicePluginMyPv: public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginmypv.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginMyPv();
void discoverDevices(DeviceDiscoveryInfo *info) override;
void setupDevice(DeviceSetupInfo *info) override;
void postSetupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
void executeAction(DeviceActionInfo *info) override;
private:
enum ElwaModbusRegisters {
Power= 1000,
WaterTemperature = 1001,
TargetWaterTemperature = 1002,
Status = 1003,
ManuelStart = 1012
};
enum ElwaStatus {
Heating = 2,
Standby = 3,
Boosted = 4,
HeatFinished = 5,
Setup = 9,
ErrorOvertempFuseBlown = 201,
ErrorOvertempMeasured = 202,
ErrorOvertempElectronics = 203,
ErrorHardwareFault = 204,
ErrorTempSensor = 205
};
PluginTimer *m_refreshTimer = nullptr;
QHash<Device *, ModbusTCPMaster *> m_modbusTcpMasters;
void update(Device *device);
private slots:
void onRefreshTimer();
};
#endif // DEVICEPLUGINMYPV_H

View File

@ -1,43 +1,46 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 "plugininfo.h"
#include "devicepluginmypv.h"
#include "integrationpluginmypv.h"
#include <QUdpSocket>
#include <QHostAddress>
DevicePluginMyPv::DevicePluginMyPv()
IntegrationPluginMyPv::IntegrationPluginMyPv()
{
}
void DevicePluginMyPv::discoverDevices(DeviceDiscoveryInfo *info)
void IntegrationPluginMyPv::discoverThings(ThingDiscoveryInfo *info)
{
QUdpSocket *searchSocket = new QUdpSocket(this);
@ -59,7 +62,7 @@ void DevicePluginMyPv::discoverDevices(DeviceDiscoveryInfo *info)
}
QTimer::singleShot(2000, this, [this, searchSocket, info](){
QList<DeviceDescriptor> descriptorList;
QList<ThingDescriptor> descriptorList;
while(searchSocket->hasPendingDatagrams()) {
char buffer[1024];
QHostAddress senderAddress;
@ -93,8 +96,8 @@ void DevicePluginMyPv::discoverDevices(DeviceDiscoveryInfo *info)
QByteArray serialNumber = data.mid(8, 16);
bool existing = false;
foreach (Device *existingDev, myDevices()) {
if (existingDev->deviceClassId() == info->deviceClassId() && existingDev->paramValue(elwaDeviceIpAddressParamTypeId).toString() == address.toString()) {
foreach (Thing *existingThing, myThings()) {
if (existingThing->thingClassId() == info->thingClassId() && existingThing->paramValue(elwaThingIpAddressParamTypeId).toString() == address.toString()) {
existing = true;
}
}
@ -102,24 +105,24 @@ void DevicePluginMyPv::discoverDevices(DeviceDiscoveryInfo *info)
qCDebug(dcMypv()) << "Already have device" << senderAddress << "in configured devices. Skipping...";
continue;
}
DeviceDescriptor deviceDescriptors(info->deviceClassId(), "AC ELWA-E", address.toString());
ThingDescriptor thingDescriptors(info->thingClassId(), "AC ELWA-E", address.toString());
ParamList params;
params << Param(elwaDeviceIpAddressParamTypeId, address.toString());
params << Param(elwaDeviceSerialNumberParamTypeId, serialNumber);
deviceDescriptors.setParams(params);
descriptorList << deviceDescriptors;
params << Param(elwaThingIpAddressParamTypeId, address.toString());
params << Param(elwaThingSerialNumberParamTypeId, serialNumber);
thingDescriptors.setParams(params);
descriptorList << thingDescriptors;
}
info->addDeviceDescriptors(descriptorList);;
info->addThingDescriptors(descriptorList);;
searchSocket->deleteLater();
});
}
void DevicePluginMyPv::setupDevice(DeviceSetupInfo *info)
void IntegrationPluginMyPv::setupThing(ThingSetupInfo *info)
{
Device *device = info->device();
Thing *thing = info->thing();
if(device->deviceClassId() == elwaDeviceClassId) {
QHostAddress address = QHostAddress(device->paramValue(elwaDeviceIpAddressParamTypeId).toString());
if(thing->thingClassId() == elwaThingClassId) {
QHostAddress address = QHostAddress(thing->paramValue(elwaThingIpAddressParamTypeId).toString());
ModbusTCPMaster *modbusTcpMaster = new ModbusTCPMaster(address, 502, this);
if (!modbusTcpMaster->createInterface()) {
@ -127,134 +130,134 @@ void DevicePluginMyPv::setupDevice(DeviceSetupInfo *info)
return;
}
m_modbusTcpMasters.insert(device, modbusTcpMaster);
m_modbusTcpMasters.insert(thing, modbusTcpMaster);
} else {
Q_ASSERT_X(false, "setupDevice", QString("Unhandled deviceClassId: %1").arg(device->deviceClassId().toString()).toUtf8());
Q_ASSERT_X(false, "setupDevice", QString("Unhandled deviceClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
}
}
void DevicePluginMyPv::postSetupDevice(Device *device)
void IntegrationPluginMyPv::postSetupThing(Thing *thing)
{
if (device->deviceClassId() == elwaDeviceClassId) {
update(device);
if (thing->thingClassId() == elwaThingClassId) {
update(thing);
}
}
void DevicePluginMyPv::deviceRemoved(Device *device)
void IntegrationPluginMyPv::thingRemoved(Thing *thing)
{
if (device->deviceClassId() == elwaDeviceClassId) {
ModbusTCPMaster *modbusTCPMaster = m_modbusTcpMasters.take(device);
if (thing->thingClassId() == elwaThingClassId) {
ModbusTCPMaster *modbusTCPMaster = m_modbusTcpMasters.take(thing);
modbusTCPMaster->deleteLater();
}
}
void DevicePluginMyPv::executeAction(DeviceActionInfo *info)
void IntegrationPluginMyPv::executeAction(ThingActionInfo *info)
{
Device *device = info->device();
Thing *thing = info->thing();
Action action = info->action();
if (device->deviceClassId() == elwaDeviceClassId) {
if (thing->thingClassId() == elwaThingClassId) {
ModbusTCPMaster *modbusTCPMaster = m_modbusTcpMasters.value(device);
ModbusTCPMaster *modbusTCPMaster = m_modbusTcpMasters.value(thing);
if (action.actionTypeId() == elwaHeatingPowerActionTypeId) {
int heatingPower = action.param(elwaHeatingPowerActionHeatingPowerParamTypeId).value().toInt();
if(!modbusTCPMaster->setRegister(0xff, ElwaModbusRegisters::Power, heatingPower)){
return info->finish(Device::DeviceErrorHardwareFailure);
return info->finish(Thing::ThingErrorHardwareFailure);
}
return;
} else if (action.actionTypeId() == elwaPowerActionTypeId) {
bool power = action.param(elwaHeatingPowerActionHeatingPowerParamTypeId).value().toBool();
if(power) {
if(!modbusTCPMaster->setRegister(0xff, ElwaModbusRegisters::ManuelStart, 1)){
return info->finish(Device::DeviceErrorHardwareFailure);
return info->finish(Thing::ThingErrorHardwareFailure);
}
}
} else {
Q_ASSERT_X(false, "executeAction", QString("Unhandled actionTypeId: %1").arg(action.actionTypeId().toString()).toUtf8());
}
} else {
Q_ASSERT_X(false, "executeAction", QString("Unhandled deviceClassId: %1").arg(device->deviceClassId().toString()).toUtf8());
Q_ASSERT_X(false, "executeAction", QString("Unhandled deviceClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
}
}
void DevicePluginMyPv::onRefreshTimer(){
void IntegrationPluginMyPv::onRefreshTimer(){
foreach (Device *device, myDevices()) {
update(device);
foreach (Thing *thing, myThings()) {
update(thing);
}
}
void DevicePluginMyPv::update(Device *device) {
if (device->deviceClassId() == elwaDeviceClassId)
void IntegrationPluginMyPv::update(Thing *thing) {
if (thing->thingClassId() == elwaThingClassId)
{
ModbusTCPMaster *modbusTCPMaster = m_modbusTcpMasters.value(device);
ModbusTCPMaster *modbusTCPMaster = m_modbusTcpMasters.value(thing);
int data;
if (modbusTCPMaster->getRegister(0xff, ElwaModbusRegisters::Status, &data)) {
switch (data) {
case Heating: {
device->setStateValue(elwaStatusStateTypeId, "Heating");
device->setStateValue(elwaPowerStateTypeId, true);
thing->setStateValue(elwaStatusStateTypeId, "Heating");
thing->setStateValue(elwaPowerStateTypeId, true);
break;
}
case Standby:{
device->setStateValue(elwaStatusStateTypeId, "Standby");
device->setStateValue(elwaPowerStateTypeId, false);
thing->setStateValue(elwaStatusStateTypeId, "Standby");
thing->setStateValue(elwaPowerStateTypeId, false);
break;
}
case Boosted:{
device->setStateValue(elwaStatusStateTypeId, "Boosted");
device->setStateValue(elwaPowerStateTypeId, true);
thing->setStateValue(elwaStatusStateTypeId, "Boosted");
thing->setStateValue(elwaPowerStateTypeId, true);
break;
}
case HeatFinished:{
device->setStateValue(elwaStatusStateTypeId, "Heat finished");
device->setStateValue(elwaPowerStateTypeId, false);
thing->setStateValue(elwaStatusStateTypeId, "Heat finished");
thing->setStateValue(elwaPowerStateTypeId, false);
break;
}
case Setup:{
device->setStateValue(elwaStatusStateTypeId, "Setup");
device->setStateValue(elwaPowerStateTypeId, false);
thing->setStateValue(elwaStatusStateTypeId, "Setup");
thing->setStateValue(elwaPowerStateTypeId, false);
break;
}
case ErrorOvertempFuseBlown:{
device->setStateValue(elwaStatusStateTypeId, "Error Overtemp Fuse blown");
thing->setStateValue(elwaStatusStateTypeId, "Error Overtemp Fuse blown");
break;
}
case ErrorOvertempMeasured:{
device->setStateValue(elwaStatusStateTypeId, "Error Overtemp measured");
thing->setStateValue(elwaStatusStateTypeId, "Error Overtemp measured");
break;
}
case ErrorOvertempElectronics:{
device->setStateValue(elwaStatusStateTypeId, "Error Overtemp Electronics");
thing->setStateValue(elwaStatusStateTypeId, "Error Overtemp Electronics");
break;
}
case ErrorHardwareFault:{
device->setStateValue(elwaStatusStateTypeId, "Error Hardware Fault");
thing->setStateValue(elwaStatusStateTypeId, "Error Hardware Fault");
break;
}
case ErrorTempSensor:{
device->setStateValue(elwaStatusStateTypeId, "Error Temp Sensor");
thing->setStateValue(elwaStatusStateTypeId, "Error Temp Sensor");
break;
}
default:
device->setStateValue(elwaStatusStateTypeId, "Unknown");
thing->setStateValue(elwaStatusStateTypeId, "Unknown");
}
device->setStateValue(elwaConnectedStateTypeId, true);
thing->setStateValue(elwaConnectedStateTypeId, true);
} else {
device->setStateValue(elwaConnectedStateTypeId, false);
thing->setStateValue(elwaConnectedStateTypeId, false);
}
if (modbusTCPMaster->getRegister(0xff, ElwaModbusRegisters::WaterTemperature, &data)) {
device->setStateValue(elwaTemperatureStateTypeId, data/10.00);
thing->setStateValue(elwaTemperatureStateTypeId, data/10.00);
}
if (modbusTCPMaster->getRegister(0xff, ElwaModbusRegisters::TargetWaterTemperature, &data)) {
device->setStateValue(elwaTargetWaterTemperatureStateTypeId, data/10.00);
thing->setStateValue(elwaTargetWaterTemperatureStateTypeId, data/10.00);
}
if (modbusTCPMaster->getRegister(0xff, ElwaModbusRegisters::Power, &data)) {
device->setStateValue(elwaHeatingPowerStateTypeId, data);
thing->setStateValue(elwaHeatingPowerStateTypeId, data);
}
}
}

View File

@ -0,0 +1,90 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 INTEGRATIONPLUGINMYPV_H
#define INTEGRATIONPLUGINMYPV_H
#include "integrations/integrationplugin.h"
#include "plugintimer.h"
#include "modbustcpmaster.h"
#include <QUdpSocket>
class IntegrationPluginMyPv: public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginmypv.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginMyPv();
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:
enum ElwaModbusRegisters {
Power= 1000,
WaterTemperature = 1001,
TargetWaterTemperature = 1002,
Status = 1003,
ManuelStart = 1012
};
enum ElwaStatus {
Heating = 2,
Standby = 3,
Boosted = 4,
HeatFinished = 5,
Setup = 9,
ErrorOvertempFuseBlown = 201,
ErrorOvertempMeasured = 202,
ErrorOvertempElectronics = 203,
ErrorHardwareFault = 204,
ErrorTempSensor = 205
};
PluginTimer *m_refreshTimer = nullptr;
QHash<Thing *, ModbusTCPMaster *> m_modbusTcpMasters;
void update(Thing *thing);
private slots:
void onRefreshTimer();
};
#endif // INTEGRATIONPLUGINMYPV_H

View File

@ -7,7 +7,7 @@
"name": "myPV",
"displayName": "my-PV",
"id": "1f17597f-e0d0-459b-858d-ec9cbcd10b2c",
"deviceClasses": [
"thingClasses": [
{
"name": "elwa",
"displayName": "AC Elwa E",

13
mypv/meta.json Normal file
View File

@ -0,0 +1,13 @@
{
"title": "my-PV",
"tagline": "Control my-PV network enabled heating rods.",
"icon": "mypv.png",
"stability": "community",
"offline": true,
"technologies": [
"network"
],
"categories": [
"heating"
]
}

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 "modbustcpmaster.h"
#include "extern-plugininfo.h"

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 MODBUSTCPMASTER_H
#define MODBUSTCPMASTER_H

BIN
mypv/mypv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -1,19 +1,15 @@
include(../plugins.pri)
TARGET = $$qtLibraryTarget(nymea_devicepluginmypv)
QT += \
network \
serialbus \
LIBS += -lmodbus
SOURCES += \
devicepluginmypv.cpp \
integrationpluginmypv.cpp \
modbustcpmaster.cpp \
HEADERS += \
devicepluginmypv.h \
integrationpluginmypv.h \
modbustcpmaster.h \

View File

@ -1,207 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 "devicepluginwallbe.h"
#include "plugininfo.h"
#include "devices/devicemanager.h"
#include "devices/device.h"
#include "types/param.h"
#include <QDebug>
#include <QStringList>
#include <QJsonDocument>
#include <QNetworkInterface>
DevicePluginWallbe::DevicePluginWallbe()
{
}
void DevicePluginWallbe::setupDevice(DeviceSetupInfo *info)
{
Device *device = info->device();
qCDebug(dcWallbe) << "Setting up a new device:" << device->params();
QHostAddress address(device->paramValue(wallbeEcoDeviceIpParamTypeId).toString());
if (address.isNull()){
qCWarning(dcWallbe) << "IP address is null";
info->finish(Device::DeviceErrorSetupFailed, tr("IP address parameter not valid"));
return;
}
WallBe *wallbe = new WallBe(address, 502, this);
m_connections.insert(device, wallbe);
info->finish(Device::DeviceErrorNoError);
}
void DevicePluginWallbe::discoverDevices(DeviceDiscoveryInfo *info)
{
if (info->deviceClassId() == wallbeEcoDeviceClassId){
Discover *discover = new Discover(QStringList("-xO" "-p 502"));
connect(discover, &Discover::devicesDiscovered, this, [info, this](QList<Host> hosts){
foreach (Host host, hosts) {
DeviceDescriptor descriptor;
foreach(Device *device, myDevices().filterByParam(wallbeEcoDeviceMacParamTypeId, host.macAddress())) {
descriptor.setDeviceId(device->id());
break;
}
descriptor.setTitle(host.hostName());
ParamList params;
params.append(Param(wallbeEcoDeviceIpParamTypeId, host.address()));
params.append(Param(wallbeEcoDeviceMacParamTypeId, host.macAddress()));
descriptor.setParams(params);
info->addDeviceDescriptor(descriptor);
}
info->finish(Device::DeviceErrorNoError);
});
return;
}
Q_ASSERT_X(false, "discoverDevices", QString("Unhandled deviceClassId: %1").arg(info->deviceClassId().toString()).toUtf8());
}
void DevicePluginWallbe::postSetupDevice(Device *device)
{
if (!m_pluginTimer) {
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(120);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
foreach(Device *device, m_connections.keys()) {
update(device);
}
});
}
if (device->deviceClassId() == wallbeEcoDeviceClassId){
update(device);
return;
}
Q_ASSERT_X(false, "postSetupDevice", QString("Unhandled deviceClassId: %1").arg(device->deviceClassId().toString()).toUtf8());
}
void DevicePluginWallbe::executeAction(DeviceActionInfo *info)
{
Device *device = info->device();
Action action = info->action();
WallBe *wallbe = m_connections.value(device);
if (!wallbe) {
qCWarning(dcWallbe()) << "Wallbe object not available";
info->finish(Device::DeviceErrorHardwareFailure);
return;
}
if (device->deviceClassId() == wallbeEcoDeviceClassId){
// check if this is the "set power" action
if (action.actionTypeId() == wallbeEcoPowerActionTypeId) {
// get the param value of the charging action
bool charging = action.param(wallbeEcoPowerActionPowerParamTypeId).value().toBool();
qCDebug(dcWallbe) << "start Charging button" << device->name() << "set power to" << charging;
wallbe->setChargingStatus(charging);
// Set the "power" state
device->setStateValue(wallbeEcoPowerStateTypeId, charging);
info->finish(Device::DeviceErrorNoError);
return;
} else if(action.actionTypeId() == wallbeEcoChargeCurrentActionTypeId){
uint16_t current = action.param(wallbeEcoChargeCurrentEventChargeCurrentParamTypeId).value().toUInt();
qCDebug(dcWallbe) << "Charging power set to" << current;
wallbe->setChargingCurrent(current);
device->setStateValue(wallbeEcoChargeCurrentStateTypeId, current);
info->finish(Device::DeviceErrorNoError);
return;
}
Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8());
}
Q_ASSERT_X(false, "executeAction", QString("Unhandled deviceClassId: %1").arg(device->deviceClassId().toString()).toUtf8());
}
void DevicePluginWallbe::deviceRemoved(Device *device)
{
m_address.removeOne(QHostAddress(device->paramValue(wallbeEcoDeviceIpParamTypeId).toString()));
WallBe *wallbe = m_connections.take(device);
if (wallbe) {
qCDebug(dcWallbe) << "Remove device" << device->name();
wallbe->deleteLater();
}
if (myDevices().isEmpty()) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
m_pluginTimer = nullptr;
}
}
void DevicePluginWallbe::update(Device *device)
{
WallBe * wallbe = m_connections.value(device);
if(!wallbe->isAvailable())
return;
device->setStateValue(wallbeEcoConnectedStateTypeId, true);
//EV state - 16 bit ASCII (8bit)
switch (wallbe->getEvStatus()) {
case 65:
device->setStateValue(wallbeEcoEvStatusStateTypeId, "A - No car plugged in");
break;
case 66:
device->setStateValue(wallbeEcoEvStatusStateTypeId, "B - Supply equipment not yet ready");
break;
case 67:
device->setStateValue(wallbeEcoEvStatusStateTypeId, "C - Ready to charge");
break;
case 68:
device->setStateValue(wallbeEcoEvStatusStateTypeId, "D - Ready to charge, ventilation needed");
break;
case 69:
device->setStateValue(wallbeEcoEvStatusStateTypeId, "E - Short circuit detected");
break;
case 70:
device->setStateValue(wallbeEcoEvStatusStateTypeId, "F - Supply equipment not available");
break;
default:
device->setStateValue(wallbeEcoEvStatusStateTypeId, "F - Supply equipment not available");
}
qCDebug(dcWallbe) << "EV State:" << device->stateValue(wallbeEcoEvStatusStateTypeId).toString();
// Extract Input Register 102 - load time - 32bit integer
device->setStateValue(wallbeEcoChargeTimeStateTypeId, wallbe->getChargingTime());
// Read the charge current state
device->setStateValue(wallbeEcoChargeCurrentStateTypeId, wallbe->getChargingCurrent());
device->setStateValue(wallbeEcoPowerStateTypeId, wallbe->getChargingStatus());
}

View File

@ -1,64 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 DEVICEPLUGINWALLBE_H
#define DEVICEPLUGINWALLBE_H
#include "devices/deviceplugin.h"
#include "wallbe.h"
#include "host.h"
#include "discover.h"
#include "plugintimer.h"
#include <QObject>
#include <QHostAddress>
class DevicePluginWallbe : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginwallbe.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginWallbe();
void discoverDevices(DeviceDiscoveryInfo *info) override;
void setupDevice(DeviceSetupInfo *info) override;
void postSetupDevice(Device *device) override;
void executeAction(DeviceActionInfo *info) override;
void deviceRemoved(Device *device) override;
private:
QHash<Device *, WallBe *> m_connections;
QList<QHostAddress> m_address;
PluginTimer *m_pluginTimer = nullptr;
void update(Device *device);
};
#endif // DEVICEPLUGINWALLBE_H

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 <QHostAddress>
#include <QNetworkInterface>

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 DISCOVER_H
#define DISCOVER_H

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 "host.h"

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 HOST_H
#define HOST_H

View File

@ -0,0 +1,209 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 "integrationpluginwallbe.h"
#include "plugininfo.h"
#include "types/param.h"
#include <QDebug>
#include <QStringList>
#include <QJsonDocument>
#include <QNetworkInterface>
IntegrationPluginWallbe::IntegrationPluginWallbe()
{
}
void IntegrationPluginWallbe::setupThing(ThingSetupInfo *info)
{
Thing *thing = info->thing();
qCDebug(dcWallbe) << "Setting up a new device:" << thing->params();
QHostAddress address(thing->paramValue(wallbeEcoThingIpParamTypeId).toString());
if (address.isNull()){
qCWarning(dcWallbe) << "IP address is null";
info->finish(Thing::ThingErrorSetupFailed, tr("IP address parameter not valid"));
return;
}
WallBe *wallbe = new WallBe(address, 502, this);
m_connections.insert(thing, wallbe);
info->finish(Thing::ThingErrorNoError);
}
void IntegrationPluginWallbe::discoverThings(ThingDiscoveryInfo *info)
{
if (info->thingClassId() == wallbeEcoThingClassId){
Discover *discover = new Discover(QStringList("-xO" "-p 502"));
connect(discover, &Discover::devicesDiscovered, this, [info, this](QList<Host> hosts){
foreach (Host host, hosts) {
ThingDescriptor descriptor;
foreach(Thing *thing, myThings().filterByParam(wallbeEcoThingMacParamTypeId, host.macAddress())) {
descriptor.setThingId(thing->id());
break;
}
descriptor.setTitle(host.hostName());
ParamList params;
params.append(Param(wallbeEcoThingIpParamTypeId, host.address()));
params.append(Param(wallbeEcoThingMacParamTypeId, host.macAddress()));
descriptor.setParams(params);
info->addThingDescriptor(descriptor);
}
info->finish(Thing::ThingErrorNoError);
});
return;
}
Q_ASSERT_X(false, "discoverThings", QString("Unhandled thingClassId: %1").arg(info->thingClassId().toString()).toUtf8());
}
void IntegrationPluginWallbe::postSetupThing(Thing *thing)
{
if (!m_pluginTimer) {
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(120);
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
foreach(Thing *thing, m_connections.keys()) {
update(thing);
}
});
}
if (thing->thingClassId() == wallbeEcoThingClassId){
update(thing);
} else {
Q_ASSERT_X(false, "postSetupThing", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
}
}
void IntegrationPluginWallbe::executeAction(ThingActionInfo *info)
{
Thing *thing = info->thing();
Action action = info->action();
WallBe *wallbe = m_connections.value(thing);
if (!wallbe) {
qCWarning(dcWallbe()) << "Wallbe object not available";
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
if (thing->thingClassId() == wallbeEcoThingClassId){
// check if this is the "set power" action
if (action.actionTypeId() == wallbeEcoPowerActionTypeId) {
// get the param value of the charging action
bool charging = action.param(wallbeEcoPowerActionPowerParamTypeId).value().toBool();
qCDebug(dcWallbe) << "start Charging button" << thing->name() << "set power to" << charging;
wallbe->setChargingStatus(charging);
// Set the "power" state
thing->setStateValue(wallbeEcoPowerStateTypeId, charging);
info->finish(Thing::ThingErrorNoError);
return;
} else if(action.actionTypeId() == wallbeEcoChargeCurrentActionTypeId){
uint16_t current = action.param(wallbeEcoChargeCurrentEventChargeCurrentParamTypeId).value().toUInt();
qCDebug(dcWallbe) << "Charging power set to" << current;
wallbe->setChargingCurrent(current);
thing->setStateValue(wallbeEcoChargeCurrentStateTypeId, current);
info->finish(Thing::ThingErrorNoError);
return;
}
Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8());
}
Q_ASSERT_X(false, "executeAction", QString("Unhandled thingClassId: %1").arg(thing->thingClassId().toString()).toUtf8());
}
void IntegrationPluginWallbe::thingRemoved(Thing *thing)
{
m_address.removeOne(QHostAddress(thing->paramValue(wallbeEcoThingIpParamTypeId).toString()));
WallBe *wallbe = m_connections.take(thing);
if (wallbe) {
qCDebug(dcWallbe) << "Remove device" << thing->name();
wallbe->deleteLater();
}
if (myThings().isEmpty()) {
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
m_pluginTimer = nullptr;
}
}
void IntegrationPluginWallbe::update(Thing *thing)
{
WallBe * wallbe = m_connections.value(thing);
if(!wallbe->isAvailable())
return;
thing->setStateValue(wallbeEcoConnectedStateTypeId, true);
//EV state - 16 bit ASCII (8bit)
switch (wallbe->getEvStatus()) {
case 65:
thing->setStateValue(wallbeEcoEvStatusStateTypeId, "A - No car plugged in");
break;
case 66:
thing->setStateValue(wallbeEcoEvStatusStateTypeId, "B - Supply equipment not yet ready");
break;
case 67:
thing->setStateValue(wallbeEcoEvStatusStateTypeId, "C - Ready to charge");
break;
case 68:
thing->setStateValue(wallbeEcoEvStatusStateTypeId, "D - Ready to charge, ventilation needed");
break;
case 69:
thing->setStateValue(wallbeEcoEvStatusStateTypeId, "E - Short circuit detected");
break;
case 70:
thing->setStateValue(wallbeEcoEvStatusStateTypeId, "F - Supply equipment not available");
break;
default:
thing->setStateValue(wallbeEcoEvStatusStateTypeId, "F - Supply equipment not available");
}
qCDebug(dcWallbe) << "EV State:" << thing->stateValue(wallbeEcoEvStatusStateTypeId).toString();
// Extract Input Register 102 - load time - 32bit integer
thing->setStateValue(wallbeEcoChargeTimeStateTypeId, wallbe->getChargingTime());
// Read the charge current state
thing->setStateValue(wallbeEcoChargeCurrentStateTypeId, wallbe->getChargingCurrent());
thing->setStateValue(wallbeEcoPowerStateTypeId, wallbe->getChargingStatus());
}

View File

@ -0,0 +1,67 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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 INTEGRATIONPLUGINWALLBE_H
#define INTEGRATIONPLUGINWALLBE_H
#include "integrations/integrationplugin.h"
#include "wallbe.h"
#include "host.h"
#include "discover.h"
#include "plugintimer.h"
#include <QObject>
#include <QHostAddress>
class IntegrationPluginWallbe : public IntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginwallbe.json")
Q_INTERFACES(IntegrationPlugin)
public:
explicit IntegrationPluginWallbe();
void discoverThings(ThingDiscoveryInfo *info) override;
void setupThing(ThingSetupInfo *info) override;
void postSetupThing(Thing *thing) override;
void executeAction(ThingActionInfo *info) override;
void thingRemoved(Thing *thing) override;
private:
QHash<Thing *, WallBe *> m_connections;
QList<QHostAddress> m_address;
PluginTimer *m_pluginTimer = nullptr;
void update(Thing *thing);
};
#endif // INTEGRATIONPLUGINWALLBE_H

View File

@ -7,7 +7,7 @@
"displayName": "Petring",
"name": "petring",
"id": "831b4b87-0a6c-4d51-b055-967bb6e5fab5",
"deviceClasses": [
"thingClasses": [
{
"id": "e66c84f6-b398-47e9-8aeb-33840e7b4492",
"displayName": "Wallbe eco 2.0",

13
wallbe/meta.json Normal file
View File

@ -0,0 +1,13 @@
{
"title": "Wall-Be",
"tagline": "Integrate Wall-Be EV-Charger into nymea-",
"icon": "walllbe.png",
"stability": "community",
"offline": true,
"technologies": [
"network"
],
"categories": [
"tool"
]
}

View File

@ -1,29 +1,32 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, 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
* 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.
* 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/>.
* 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
* 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 WALLBE_H
#define WALLBE_H

BIN
wallbe/wallbe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,19 +1,17 @@
include(../plugins.pri)
TARGET = $$qtLibraryTarget(nymea_devicepluginwallbe)
QT += \
network \
serialbus \
SOURCES += \
devicepluginwallbe.cpp \
integrationpluginwallbe.cpp \
wallbe.cpp \
host.cpp \
discover.cpp
HEADERS += \
devicepluginwallbe.h \
integrationpluginwallbe.h \
wallbe.h \
host.h \
discover.h