diff --git a/drexelundweiss/deviceplugindrexelundweiss.h b/drexelundweiss/deviceplugindrexelundweiss.h deleted file mode 100644 index 87f72ec..0000000 --- a/drexelundweiss/deviceplugindrexelundweiss.h +++ /dev/null @@ -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 . -* -* 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 -#include "modbusrtumaster.h" -#include - -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 m_usedSerialPorts; - QHash m_modbusRTUMasters; - PluginTimer *m_refreshTimer = nullptr; - QHash m_pendingActions; - - void updateStates(Device *device); - void discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress); - -private slots: - void onRefreshTimer(); - void onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, 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 diff --git a/drexelundweiss/drexelundweiss.png b/drexelundweiss/drexelundweiss.png new file mode 100644 index 0000000..7b87495 Binary files /dev/null and b/drexelundweiss/drexelundweiss.png differ diff --git a/drexelundweiss/drexelundweiss.pro b/drexelundweiss/drexelundweiss.pro index f8fe629..0638497 100644 --- a/drexelundweiss/drexelundweiss.pro +++ b/drexelundweiss/drexelundweiss.pro @@ -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 diff --git a/drexelundweiss/deviceplugindrexelundweiss.cpp b/drexelundweiss/integrationplugindrexelundweiss.cpp similarity index 56% rename from drexelundweiss/deviceplugindrexelundweiss.cpp rename to drexelundweiss/integrationplugindrexelundweiss.cpp index efefece..94ed650 100644 --- a/drexelundweiss/deviceplugindrexelundweiss.cpp +++ b/drexelundweiss/integrationplugindrexelundweiss.cpp @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 deviceDescriptors; + QList 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 ¶mTypeId, const QVariant &value) +void IntegrationPluginDrexelUndWeiss::onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, 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(sender()); if (m_modbusRTUMasters.values().contains(modbus) ){ Device *parentDevice = m_modbusRTUMasters.key(static_cast(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 deviceDescriptors; - DeviceDescriptor descriptor(x2wpDeviceClassId, "X2 WP", "Drexel und Weiss", parentDevice->id()); + QList 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 deviceDescriptors; - DeviceDescriptor descriptor(x2luDeviceClassId, "X2 LU", "Drexel und Weiss", parentDevice->id()); + QList 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; } } diff --git a/drexelundweiss/integrationplugindrexelundweiss.h b/drexelundweiss/integrationplugindrexelundweiss.h new file mode 100644 index 0000000..84133b4 --- /dev/null +++ b/drexelundweiss/integrationplugindrexelundweiss.h @@ -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 . +* +* 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 +#include "modbusrtumaster.h" +#include + +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 m_usedSerialPorts; + QHash m_modbusRTUMasters; + PluginTimer *m_refreshTimer = nullptr; + QHash m_pendingActions; + + void updateStates(Device *device); + void discoverModbusSlaves(ModbusRTUMaster *modbus, int slaveAddress); + +private slots: + void onRefreshTimer(); + void onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, 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 diff --git a/drexelundweiss/deviceplugindrexelundweiss.json b/drexelundweiss/integrationplugindrexelundweiss.json similarity index 99% rename from drexelundweiss/deviceplugindrexelundweiss.json rename to drexelundweiss/integrationplugindrexelundweiss.json index 462ed36..57fb5d0 100644 --- a/drexelundweiss/deviceplugindrexelundweiss.json +++ b/drexelundweiss/integrationplugindrexelundweiss.json @@ -17,7 +17,7 @@ "name": "DrexelUndWeiss", "displayName": "Drexel und Weiss", "id": "9f476e8b-7e95-448e-b03b-874747e8fb1f", - "deviceClasses": [ + "thingClasses": [ { "name": "modbusConnection", "displayName": "Modbus Connection", diff --git a/drexelundweiss/meta.json b/drexelundweiss/meta.json new file mode 100644 index 0000000..994ede4 --- /dev/null +++ b/drexelundweiss/meta.json @@ -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" + ] +} diff --git a/drexelundweiss/modbusdegisterdefinition.h b/drexelundweiss/modbusdegisterdefinition.h index 2440882..534583b 100644 --- a/drexelundweiss/modbusdegisterdefinition.h +++ b/drexelundweiss/modbusdegisterdefinition.h @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 diff --git a/drexelundweiss/modbusrtumaster.cpp b/drexelundweiss/modbusrtumaster.cpp index 5b14dcd..ccf2e97 100644 --- a/drexelundweiss/modbusrtumaster.cpp +++ b/drexelundweiss/modbusrtumaster.cpp @@ -24,6 +24,7 @@ * or see our FAQ/Licensing Information on https://nymea.io/license/faq * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "modbusrtumaster.h" #include "extern-plugininfo.h" diff --git a/drexelundweiss/modbusrtumaster.h b/drexelundweiss/modbusrtumaster.h index e281f73..b7abc28 100644 --- a/drexelundweiss/modbusrtumaster.h +++ b/drexelundweiss/modbusrtumaster.h @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 diff --git a/mypv/devicepluginmypv.h b/mypv/devicepluginmypv.h deleted file mode 100644 index 48a14f2..0000000 --- a/mypv/devicepluginmypv.h +++ /dev/null @@ -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 . -* -* 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 - -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 m_modbusTcpMasters; - - void update(Device *device); - -private slots: - void onRefreshTimer(); -}; - -#endif // DEVICEPLUGINMYPV_H - diff --git a/mypv/devicepluginmypv.cpp b/mypv/integrationpluginmypv.cpp similarity index 56% rename from mypv/devicepluginmypv.cpp rename to mypv/integrationpluginmypv.cpp index dd1d734..e04be9d 100644 --- a/mypv/devicepluginmypv.cpp +++ b/mypv/integrationpluginmypv.cpp @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 #include -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 descriptorList; + QList 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); } } } diff --git a/mypv/integrationpluginmypv.h b/mypv/integrationpluginmypv.h new file mode 100644 index 0000000..83d923a --- /dev/null +++ b/mypv/integrationpluginmypv.h @@ -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 . +* +* 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 + +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 m_modbusTcpMasters; + + void update(Thing *thing); + +private slots: + void onRefreshTimer(); +}; + +#endif // INTEGRATIONPLUGINMYPV_H + diff --git a/mypv/devicepluginmypv.json b/mypv/integrationpluginmypv.json similarity index 99% rename from mypv/devicepluginmypv.json rename to mypv/integrationpluginmypv.json index 4327b07..c13fddd 100644 --- a/mypv/devicepluginmypv.json +++ b/mypv/integrationpluginmypv.json @@ -7,7 +7,7 @@ "name": "myPV", "displayName": "my-PV", "id": "1f17597f-e0d0-459b-858d-ec9cbcd10b2c", - "deviceClasses": [ + "thingClasses": [ { "name": "elwa", "displayName": "AC Elwa E", diff --git a/mypv/meta.json b/mypv/meta.json new file mode 100644 index 0000000..43fa0ad --- /dev/null +++ b/mypv/meta.json @@ -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" + ] +} diff --git a/mypv/modbustcpmaster.cpp b/mypv/modbustcpmaster.cpp index 4590e9b..e895d77 100644 --- a/mypv/modbustcpmaster.cpp +++ b/mypv/modbustcpmaster.cpp @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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" diff --git a/mypv/modbustcpmaster.h b/mypv/modbustcpmaster.h index b214282..73907c0 100644 --- a/mypv/modbustcpmaster.h +++ b/mypv/modbustcpmaster.h @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 diff --git a/mypv/mypv.png b/mypv/mypv.png new file mode 100644 index 0000000..a7b664d Binary files /dev/null and b/mypv/mypv.png differ diff --git a/mypv/mypv.pro b/mypv/mypv.pro index 51ab21d..9754d69 100644 --- a/mypv/mypv.pro +++ b/mypv/mypv.pro @@ -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 \ diff --git a/wallbe/devicepluginwallbe.cpp b/wallbe/devicepluginwallbe.cpp deleted file mode 100644 index 361e7de..0000000 --- a/wallbe/devicepluginwallbe.cpp +++ /dev/null @@ -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 . -* -* 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 -#include -#include -#include - - -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 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()); -} diff --git a/wallbe/devicepluginwallbe.h b/wallbe/devicepluginwallbe.h deleted file mode 100644 index 051cd3a..0000000 --- a/wallbe/devicepluginwallbe.h +++ /dev/null @@ -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 . -* -* 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 -#include - -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 m_connections; - QList m_address; - PluginTimer *m_pluginTimer = nullptr; - - void update(Device *device); -}; - -#endif // DEVICEPLUGINWALLBE_H diff --git a/wallbe/discover.cpp b/wallbe/discover.cpp index 5af54e4..41d4034 100644 --- a/wallbe/discover.cpp +++ b/wallbe/discover.cpp @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 #include diff --git a/wallbe/discover.h b/wallbe/discover.h index 4c75916..6e07191 100644 --- a/wallbe/discover.h +++ b/wallbe/discover.h @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 diff --git a/wallbe/host.cpp b/wallbe/host.cpp index bf6c388..6eb0468 100644 --- a/wallbe/host.cpp +++ b/wallbe/host.cpp @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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" diff --git a/wallbe/host.h b/wallbe/host.h index 71463c4..41e5ac0 100644 --- a/wallbe/host.h +++ b/wallbe/host.h @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 diff --git a/wallbe/integrationpluginwallbe.cpp b/wallbe/integrationpluginwallbe.cpp new file mode 100644 index 0000000..417a241 --- /dev/null +++ b/wallbe/integrationpluginwallbe.cpp @@ -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 . +* +* 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 +#include +#include +#include + + +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 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()); +} diff --git a/wallbe/integrationpluginwallbe.h b/wallbe/integrationpluginwallbe.h new file mode 100644 index 0000000..9ebc8c5 --- /dev/null +++ b/wallbe/integrationpluginwallbe.h @@ -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 . +* +* 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 +#include + +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 m_connections; + QList m_address; + PluginTimer *m_pluginTimer = nullptr; + + void update(Thing *thing); +}; + +#endif // INTEGRATIONPLUGINWALLBE_H diff --git a/wallbe/devicepluginwallbe.json b/wallbe/integrationpluginwallbe.json similarity index 99% rename from wallbe/devicepluginwallbe.json rename to wallbe/integrationpluginwallbe.json index 0e6aca3..3c3335c 100644 --- a/wallbe/devicepluginwallbe.json +++ b/wallbe/integrationpluginwallbe.json @@ -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", diff --git a/wallbe/meta.json b/wallbe/meta.json new file mode 100644 index 0000000..cacab09 --- /dev/null +++ b/wallbe/meta.json @@ -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" + ] +} diff --git a/wallbe/wallbe.h b/wallbe/wallbe.h index 3bb8d7f..5abf454 100644 --- a/wallbe/wallbe.h +++ b/wallbe/wallbe.h @@ -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 . +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . * -* 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 diff --git a/wallbe/wallbe.png b/wallbe/wallbe.png new file mode 100644 index 0000000..79eaae8 Binary files /dev/null and b/wallbe/wallbe.png differ diff --git a/wallbe/wallbe.pro b/wallbe/wallbe.pro index 7af11bf..a140a4b 100644 --- a/wallbe/wallbe.pro +++ b/wallbe/wallbe.pro @@ -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