Merge PR #38: New plugin: Alpha Innotec heat pumps
commit
eee44a113c
|
|
@ -0,0 +1,23 @@
|
|||
# alpha innotec
|
||||
|
||||
Connect nymea to alpha innotec heat pumps.
|
||||
|
||||
In order to use the modbus interface, it is important to enable modbus on the heatpump using the Windows tools from Alpha Innotec.
|
||||
The instructions for that can be found in the user manual of the heat pump.
|
||||
|
||||
Please also make sure all values are configured as readable and writable for modbus, otherwise the heapump can only be monitored, but
|
||||
not optimized for smart heating.
|
||||
|
||||
## Supported Things
|
||||
|
||||
* alpha connect
|
||||
|
||||
## Requirements
|
||||
|
||||
* The package 'nymea-plugin-alphainnotec' must be installed
|
||||
* Both devices must be in the same local area network.
|
||||
* Modbus enabled and all values are readable and writable.
|
||||
|
||||
## More
|
||||
|
||||
https://www.alpha-innotec.de
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,273 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This fileDescriptor is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef ALPHACONNECTMODBUSTCPCONNECTION_H
|
||||
#define ALPHACONNECTMODBUSTCPCONNECTION_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "../modbus/modbusdatautils.h"
|
||||
#include "../modbus/modbustcpmaster.h"
|
||||
|
||||
class AlphaConnectModbusTcpConnection : public ModbusTCPMaster
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum SystemStatus {
|
||||
SystemStatusHeatingMode = 0,
|
||||
SystemStatusDomesticHotWater = 1,
|
||||
SystemStatusSwimmingPool = 2,
|
||||
SystemStatusEVUOff = 3,
|
||||
SystemStatusDefrost = 4,
|
||||
SystemStatusOff = 5,
|
||||
SystemStatusExternalEnergySource = 6,
|
||||
SystemStatusCoolingMode = 7
|
||||
};
|
||||
Q_ENUM(SystemStatus)
|
||||
|
||||
enum SmartGridState {
|
||||
SmartGridStateOff = 0,
|
||||
SmartGridStateLow = 1,
|
||||
SmartGridStateStandard = 2,
|
||||
SmartGridStateHigh = 3
|
||||
};
|
||||
Q_ENUM(SmartGridState)
|
||||
|
||||
explicit AlphaConnectModbusTcpConnection(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);
|
||||
~AlphaConnectModbusTcpConnection() = default;
|
||||
|
||||
/* Flow [°C] - Address: 1, Size: 1 */
|
||||
float flowTemperature() const;
|
||||
|
||||
/* Return [°C] - Address: 2, Size: 1 */
|
||||
float returnTemperature() const;
|
||||
|
||||
/* External return [°C] - Address: 3, Size: 1 */
|
||||
float externalReturnTemperature() const;
|
||||
|
||||
/* Hot water temperature [°C] - Address: 4, Size: 1 */
|
||||
float hotWaterTemperature() const;
|
||||
|
||||
/* Hot gas temperature [°C] - Address: 8, Size: 1 */
|
||||
float hotGasTemperature() const;
|
||||
|
||||
/* Heat source inlet temperature [°C] - Address: 9, Size: 1 */
|
||||
float heatSourceInletTemperature() const;
|
||||
|
||||
/* Heat source outlet temperature [°C] - Address: 10, Size: 1 */
|
||||
float heatSourceOutletTemperature() const;
|
||||
|
||||
/* Room remote adjuster 1 temperature [°C] - Address: 11, Size: 1 */
|
||||
float roomTemperature1() const;
|
||||
|
||||
/* Room remote adjuster 2 temperature [°C] - Address: 12, Size: 1 */
|
||||
float roomTemperature2() const;
|
||||
|
||||
/* Room remote adjuster 3 temperature [°C] - Address: 13, Size: 1 */
|
||||
float roomTemperature3() const;
|
||||
|
||||
/* Solar collector temperature [°C] - Address: 14, Size: 1 */
|
||||
float solarCollectorTemperature() const;
|
||||
|
||||
/* Solar storage tank temperature [°C] - Address: 15, Size: 1 */
|
||||
float solarStorageTankTemperature() const;
|
||||
|
||||
/* External energy source temperature [°C] - Address: 16, Size: 1 */
|
||||
float externalEnergySourceTemperature() const;
|
||||
|
||||
/* Supply air temperature [°C] - Address: 17, Size: 1 */
|
||||
float supplyAirTemperature() const;
|
||||
|
||||
/* External air temperature [°C] - Address: 18, Size: 1 */
|
||||
float externalAirTemperature() const;
|
||||
|
||||
/* RBE actual room temperature [°C] - Address: 24, Size: 1 */
|
||||
float rbeRoomActualTemperature() const;
|
||||
|
||||
/* RBE room temperature setpoint [°C] - Address: 24, Size: 1 */
|
||||
float rbeRoomSetpointTemperature() const;
|
||||
|
||||
/* Heating pump operating hours [h] - Address: 33, Size: 1 */
|
||||
quint16 heatingPumpOperatingHours() const;
|
||||
|
||||
/* System status - Address: 37, Size: 1 */
|
||||
SystemStatus systemStatus() const;
|
||||
|
||||
/* Heating energy [kWh] - Address: 38, Size: 2 */
|
||||
float heatingEnergy() const;
|
||||
|
||||
/* Water heat energy [kWh] - Address: 40, Size: 2 */
|
||||
float waterHeatEnergy() const;
|
||||
|
||||
/* Total energy [kWh] - Address: 44, Size: 2 */
|
||||
float totalHeatEnergy() const;
|
||||
|
||||
/* Outdoor temperature [°C] - Address: 0, Size: 1 */
|
||||
float outdoorTemperature() const;
|
||||
QModbusReply *setOutdoorTemperature(float outdoorTemperature);
|
||||
|
||||
/* Return setpoint temperature [°C] - Address: 1, Size: 1 */
|
||||
float returnSetpointTemperature() const;
|
||||
QModbusReply *setReturnSetpointTemperature(float returnSetpointTemperature);
|
||||
|
||||
/* Hot water setpoint temperature [°C] - Address: 5, Size: 1 */
|
||||
float hotWaterSetpointTemperature() const;
|
||||
QModbusReply *setHotWaterSetpointTemperature(float hotWaterSetpointTemperature);
|
||||
|
||||
/* Smart grid control - Address: 14, Size: 1 */
|
||||
SmartGridState smartGrid() const;
|
||||
QModbusReply *setSmartGrid(SmartGridState smartGrid);
|
||||
|
||||
virtual void initialize();
|
||||
virtual void update();
|
||||
|
||||
void updateFlowTemperature();
|
||||
void updateReturnTemperature();
|
||||
void updateExternalReturnTemperature();
|
||||
void updateHotWaterTemperature();
|
||||
void updateHotGasTemperature();
|
||||
void updateHeatSourceInletTemperature();
|
||||
void updateHeatSourceOutletTemperature();
|
||||
void updateRoomTemperature1();
|
||||
void updateRoomTemperature2();
|
||||
void updateRoomTemperature3();
|
||||
void updateSolarCollectorTemperature();
|
||||
void updateSolarStorageTankTemperature();
|
||||
void updateExternalEnergySourceTemperature();
|
||||
void updateSupplyAirTemperature();
|
||||
void updateExternalAirTemperature();
|
||||
void updateRbeRoomActualTemperature();
|
||||
void updateRbeRoomSetpointTemperature();
|
||||
void updateHeatingPumpOperatingHours();
|
||||
void updateSystemStatus();
|
||||
void updateHeatingEnergy();
|
||||
void updateWaterHeatEnergy();
|
||||
void updateTotalHeatEnergy();
|
||||
void updateOutdoorTemperature();
|
||||
void updateReturnSetpointTemperature();
|
||||
void updateHotWaterSetpointTemperature();
|
||||
void updateSmartGrid();
|
||||
|
||||
signals:
|
||||
void initializationFinished();
|
||||
|
||||
void flowTemperatureChanged(float flowTemperature);
|
||||
void returnTemperatureChanged(float returnTemperature);
|
||||
void externalReturnTemperatureChanged(float externalReturnTemperature);
|
||||
void hotWaterTemperatureChanged(float hotWaterTemperature);
|
||||
void hotGasTemperatureChanged(float hotGasTemperature);
|
||||
void heatSourceInletTemperatureChanged(float heatSourceInletTemperature);
|
||||
void heatSourceOutletTemperatureChanged(float heatSourceOutletTemperature);
|
||||
void roomTemperature1Changed(float roomTemperature1);
|
||||
void roomTemperature2Changed(float roomTemperature2);
|
||||
void roomTemperature3Changed(float roomTemperature3);
|
||||
void solarCollectorTemperatureChanged(float solarCollectorTemperature);
|
||||
void solarStorageTankTemperatureChanged(float solarStorageTankTemperature);
|
||||
void externalEnergySourceTemperatureChanged(float externalEnergySourceTemperature);
|
||||
void supplyAirTemperatureChanged(float supplyAirTemperature);
|
||||
void externalAirTemperatureChanged(float externalAirTemperature);
|
||||
void rbeRoomActualTemperatureChanged(float rbeRoomActualTemperature);
|
||||
void rbeRoomSetpointTemperatureChanged(float rbeRoomSetpointTemperature);
|
||||
void heatingPumpOperatingHoursChanged(quint16 heatingPumpOperatingHours);
|
||||
void systemStatusChanged(SystemStatus systemStatus);
|
||||
void heatingEnergyChanged(float heatingEnergy);
|
||||
void waterHeatEnergyChanged(float waterHeatEnergy);
|
||||
void totalHeatEnergyChanged(float totalHeatEnergy);
|
||||
void outdoorTemperatureChanged(float outdoorTemperature);
|
||||
void returnSetpointTemperatureChanged(float returnSetpointTemperature);
|
||||
void hotWaterSetpointTemperatureChanged(float hotWaterSetpointTemperature);
|
||||
void smartGridChanged(SmartGridState smartGrid);
|
||||
|
||||
private:
|
||||
quint16 m_slaveId = 1;
|
||||
QVector<QModbusReply *> m_pendingInitReplies;
|
||||
|
||||
float m_flowTemperature = 0;
|
||||
float m_returnTemperature = 0;
|
||||
float m_externalReturnTemperature = 0;
|
||||
float m_hotWaterTemperature = 0;
|
||||
float m_hotGasTemperature = 0;
|
||||
float m_heatSourceInletTemperature = 0;
|
||||
float m_heatSourceOutletTemperature = 0;
|
||||
float m_roomTemperature1 = 0;
|
||||
float m_roomTemperature2 = 0;
|
||||
float m_roomTemperature3 = 0;
|
||||
float m_solarCollectorTemperature = 0;
|
||||
float m_solarStorageTankTemperature = 0;
|
||||
float m_externalEnergySourceTemperature = 0;
|
||||
float m_supplyAirTemperature = 0;
|
||||
float m_externalAirTemperature = 0;
|
||||
float m_rbeRoomActualTemperature = 0;
|
||||
float m_rbeRoomSetpointTemperature = 0;
|
||||
quint16 m_heatingPumpOperatingHours = 0;
|
||||
SystemStatus m_systemStatus = SystemStatusHeatingMode;
|
||||
float m_heatingEnergy = 0;
|
||||
float m_waterHeatEnergy = 0;
|
||||
float m_totalHeatEnergy = 0;
|
||||
float m_outdoorTemperature = 0;
|
||||
float m_returnSetpointTemperature = 0;
|
||||
float m_hotWaterSetpointTemperature = 0;
|
||||
SmartGridState m_smartGrid = SmartGridStateStandard;
|
||||
|
||||
void verifyInitFinished();
|
||||
|
||||
QModbusReply *readFlowTemperature();
|
||||
QModbusReply *readReturnTemperature();
|
||||
QModbusReply *readExternalReturnTemperature();
|
||||
QModbusReply *readHotWaterTemperature();
|
||||
QModbusReply *readHotGasTemperature();
|
||||
QModbusReply *readHeatSourceInletTemperature();
|
||||
QModbusReply *readHeatSourceOutletTemperature();
|
||||
QModbusReply *readRoomTemperature1();
|
||||
QModbusReply *readRoomTemperature2();
|
||||
QModbusReply *readRoomTemperature3();
|
||||
QModbusReply *readSolarCollectorTemperature();
|
||||
QModbusReply *readSolarStorageTankTemperature();
|
||||
QModbusReply *readExternalEnergySourceTemperature();
|
||||
QModbusReply *readSupplyAirTemperature();
|
||||
QModbusReply *readExternalAirTemperature();
|
||||
QModbusReply *readRbeRoomActualTemperature();
|
||||
QModbusReply *readRbeRoomSetpointTemperature();
|
||||
QModbusReply *readHeatingPumpOperatingHours();
|
||||
QModbusReply *readSystemStatus();
|
||||
QModbusReply *readHeatingEnergy();
|
||||
QModbusReply *readWaterHeatEnergy();
|
||||
QModbusReply *readTotalHeatEnergy();
|
||||
QModbusReply *readOutdoorTemperature();
|
||||
QModbusReply *readReturnSetpointTemperature();
|
||||
QModbusReply *readHotWaterSetpointTemperature();
|
||||
QModbusReply *readSmartGrid();
|
||||
|
||||
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, AlphaConnectModbusTcpConnection *alphaConnectModbusTcpConnection);
|
||||
|
||||
#endif // ALPHACONNECTMODBUSTCPCONNECTION_H
|
||||
|
|
@ -0,0 +1,401 @@
|
|||
{
|
||||
"endianness": "BigEndian",
|
||||
"enums": [
|
||||
{
|
||||
"name": "SystemStatus",
|
||||
"values": [
|
||||
{
|
||||
"key": "HeatingMode",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"key": "DomesticHotWater",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"key": "SwimmingPool",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"key": "EVUOff",
|
||||
"value": 3
|
||||
},
|
||||
{
|
||||
"key": "Defrost",
|
||||
"value": 4
|
||||
},
|
||||
{
|
||||
"key": "Off",
|
||||
"value": 5
|
||||
},
|
||||
{
|
||||
"key": "ExternalEnergySource",
|
||||
"value": 6
|
||||
},
|
||||
{
|
||||
"key": "CoolingMode",
|
||||
"value": 7
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SmartGridState",
|
||||
"values": [
|
||||
{
|
||||
"key": "Off",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"key": "Low",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"key": "Standard",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"key": "High",
|
||||
"value": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"registers": [
|
||||
{
|
||||
"id": "flowTemperature",
|
||||
"address": 1,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Flow",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "returnTemperature",
|
||||
"address": 2,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Return",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "externalReturnTemperature",
|
||||
"address": 3,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "External return",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "hotWaterTemperature",
|
||||
"address": 4,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Hot water temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "hotGasTemperature",
|
||||
"address": 8,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Hot gas temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "heatSourceInletTemperature",
|
||||
"address": 9,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Heat source inlet temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "heatSourceOutletTemperature",
|
||||
"address": 10,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Heat source outlet temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "roomTemperature1",
|
||||
"address": 11,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Room remote adjuster 1 temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "roomTemperature2",
|
||||
"address": 12,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Room remote adjuster 2 temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "roomTemperature3",
|
||||
"address": 13,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Room remote adjuster 3 temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "solarCollectorTemperature",
|
||||
"address": 14,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Solar collector temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "solarStorageTankTemperature",
|
||||
"address": 15,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Solar storage tank temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "externalEnergySourceTemperature",
|
||||
"address": 16,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "External energy source temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "supplyAirTemperature",
|
||||
"address": 17,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Supply air temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "externalAirTemperature",
|
||||
"address": 18,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "External air temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "rbeRoomActualTemperature",
|
||||
"address": 24,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "RBE actual room temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "rbeRoomSetpointTemperature",
|
||||
"address": 24,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "RBE room temperature setpoint",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "heatingPumpOperatingHours",
|
||||
"address": 33,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Heating pump operating hours",
|
||||
"defaultValue": "0",
|
||||
"unit": "h",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "systemStatus",
|
||||
"address": 37,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"enum": "SystemStatus",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "System status",
|
||||
"defaultValue": "SystemStatusHeatingMode",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "heatingEnergy",
|
||||
"address": 38,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "kWh",
|
||||
"description": "Heating energy",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "waterHeatEnergy",
|
||||
"address": 40,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "kWh",
|
||||
"description": "Water heat energy",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "totalHeatEnergy",
|
||||
"address": 44,
|
||||
"size": 2,
|
||||
"type": "uint32",
|
||||
"registerType": "inputRegister",
|
||||
"readSchedule": "update",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "kWh",
|
||||
"description": "Total energy",
|
||||
"access": "RO"
|
||||
},
|
||||
|
||||
{
|
||||
"id": "outdoorTemperature",
|
||||
"address": 0,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "holdingRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Outdoor temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RW"
|
||||
},
|
||||
{
|
||||
"id": "returnSetpointTemperature",
|
||||
"address": 1,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "holdingRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Return setpoint temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RW"
|
||||
},
|
||||
{
|
||||
"id": "hotWaterSetpointTemperature",
|
||||
"address": 5,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"registerType": "holdingRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Hot water setpoint temperature",
|
||||
"staticScaleFactor": -1,
|
||||
"defaultValue": "0",
|
||||
"unit": "°C",
|
||||
"access": "RW"
|
||||
},
|
||||
{
|
||||
"id": "smartGrid",
|
||||
"address": 14,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"enum": "SmartGridState",
|
||||
"registerType": "holdingRegister",
|
||||
"readSchedule": "update",
|
||||
"description": "Smart grid control",
|
||||
"defaultValue": "SmartGridStateStandard",
|
||||
"access": "RW"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
include(../plugins.pri)
|
||||
|
||||
QT += network serialbus
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginalphainnotec.cpp \
|
||||
alphaconnectmodbustcpconnection.cpp \
|
||||
../modbus/modbustcpmaster.cpp \
|
||||
../modbus/modbusdatautils.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginalphainnotec.h \
|
||||
alphaconnectmodbustcpconnection.h \
|
||||
../modbus/modbustcpmaster.h \
|
||||
../modbus/modbusdatautils.h
|
||||
|
|
@ -0,0 +1,474 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "integrationpluginalphainnotec.h"
|
||||
|
||||
#include "network/networkdevicediscovery.h"
|
||||
#include "hardwaremanager.h"
|
||||
#include "plugininfo.h"
|
||||
|
||||
IntegrationPluginAlphaInnotec::IntegrationPluginAlphaInnotec()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginAlphaInnotec::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
if (!hardwareManager()->networkDeviceDiscovery()->available()) {
|
||||
qCWarning(dcAlphaInnotec()) << "The network discovery is not available on this platform.";
|
||||
info->finish(Thing::ThingErrorUnsupportedFeature, QT_TR_NOOP("The network device discovery is not available."));
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover();
|
||||
connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){
|
||||
foreach (const NetworkDeviceInfo &networkDeviceInfo, discoveryReply->networkDeviceInfos()) {
|
||||
|
||||
qCDebug(dcAlphaInnotec()) << "Found" << networkDeviceInfo;
|
||||
|
||||
QString title;
|
||||
if (networkDeviceInfo.hostName().isEmpty()) {
|
||||
title = networkDeviceInfo.address().toString();
|
||||
} else {
|
||||
title = networkDeviceInfo.hostName() + " (" + networkDeviceInfo.address().toString() + ")";
|
||||
}
|
||||
|
||||
QString description;
|
||||
if (networkDeviceInfo.macAddressManufacturer().isEmpty()) {
|
||||
description = networkDeviceInfo.macAddress();
|
||||
} else {
|
||||
description = networkDeviceInfo.macAddress() + " (" + networkDeviceInfo.macAddressManufacturer() + ")";
|
||||
}
|
||||
|
||||
ThingDescriptor descriptor(alphaConnectThingClassId, title, description);
|
||||
ParamList params;
|
||||
params << Param(alphaConnectThingIpAddressParamTypeId, networkDeviceInfo.address().toString());
|
||||
params << Param(alphaConnectThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
|
||||
descriptor.setParams(params);
|
||||
|
||||
// Check if we already have set up this device
|
||||
Things existingThings = myThings().filterByParam(alphaConnectThingMacAddressParamTypeId, networkDeviceInfo.macAddress());
|
||||
if (existingThings.count() == 1) {
|
||||
qCDebug(dcAlphaInnotec()) << "This connection already exists in the system:" << networkDeviceInfo;
|
||||
descriptor.setThingId(existingThings.first()->id());
|
||||
}
|
||||
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginAlphaInnotec::startMonitoringAutoThings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginAlphaInnotec::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
qCDebug(dcAlphaInnotec()) << "Setup" << thing << thing->params();
|
||||
|
||||
if (thing->thingClassId() == alphaConnectThingClassId) {
|
||||
QHostAddress hostAddress = QHostAddress(thing->paramValue(alphaConnectThingIpAddressParamTypeId).toString());
|
||||
if (hostAddress.isNull()) {
|
||||
info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("No IP address given"));
|
||||
return;
|
||||
}
|
||||
|
||||
uint port = thing->paramValue(alphaConnectThingPortParamTypeId).toUInt();
|
||||
quint16 slaveId = thing->paramValue(alphaConnectThingSlaveIdParamTypeId).toUInt();
|
||||
|
||||
AlphaConnectModbusTcpConnection *alphaConnectTcpConnection = new AlphaConnectModbusTcpConnection(hostAddress, port, slaveId, this);
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::connectionStateChanged, this, [thing, alphaConnectTcpConnection](bool status){
|
||||
qCDebug(dcAlphaInnotec()) << "Connected changed to" << status << "for" << thing;
|
||||
if (status) {
|
||||
alphaConnectTcpConnection->update();
|
||||
}
|
||||
|
||||
thing->setStateValue(alphaConnectConnectedStateTypeId, status);
|
||||
});
|
||||
|
||||
|
||||
// Input registers
|
||||
// connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::meanTemperatureChanged, this, [thing](float meanTemperature){
|
||||
// qCDebug(dcAlphaInnotec()) << thing << "mean temperature changed" << meanTemperature << "°C";
|
||||
// thing->setStateValue(alphaConnectMeanTemperatureStateTypeId, meanTemperature);
|
||||
// });
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::flowTemperatureChanged, this, [thing](float flowTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "flow temperature changed" << flowTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectFlowTemperatureStateTypeId, flowTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::returnTemperatureChanged, this, [thing](float returnTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "return temperature changed" << returnTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectReturnTemperatureStateTypeId, returnTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::externalReturnTemperatureChanged, this, [thing](float externalReturnTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "external return temperature changed" << externalReturnTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectExternalReturnTemperatureStateTypeId, externalReturnTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::hotWaterTemperatureChanged, this, [thing](float hotWaterTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "hot water temperature changed" << hotWaterTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectHotWaterTemperatureStateTypeId, hotWaterTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::hotGasTemperatureChanged, this, [thing](float hotGasTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "hot gas temperature changed" << hotGasTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectHotGasTemperatureStateTypeId, hotGasTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatSourceInletTemperatureChanged, this, [thing](float heatSourceInletTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "heat source inlet temperature changed" << heatSourceInletTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectHeatSourceInletTemperatureStateTypeId, heatSourceInletTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatSourceOutletTemperatureChanged, this, [thing](float heatSourceOutletTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "heat source outlet temperature changed" << heatSourceOutletTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectHeatSourceOutletTemperatureStateTypeId, heatSourceOutletTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::roomTemperature1Changed, this, [thing](float roomTemperature1){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "room remote adjuster 1 temperature changed" << roomTemperature1 << "°C";
|
||||
thing->setStateValue(alphaConnectRoomTemperature1StateTypeId, roomTemperature1);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::roomTemperature2Changed, this, [thing](float roomTemperature2){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "room remote adjuster 2 temperature changed" << roomTemperature2 << "°C";
|
||||
thing->setStateValue(alphaConnectRoomTemperature2StateTypeId, roomTemperature2);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::roomTemperature3Changed, this, [thing](float roomTemperature3){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "room remote adjuster 3 temperature changed" << roomTemperature3 << "°C";
|
||||
thing->setStateValue(alphaConnectRoomTemperature2StateTypeId, roomTemperature3);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::solarCollectorTemperatureChanged, this, [thing](float solarCollectorTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "solar collector temperature changed" << solarCollectorTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectSolarCollectorTemperatureStateTypeId, solarCollectorTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::solarStorageTankTemperatureChanged, this, [thing](float solarStorageTankTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "solar storage tank temperature changed" << solarStorageTankTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectSolarCollectorTemperatureStateTypeId, solarStorageTankTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::externalEnergySourceTemperatureChanged, this, [thing](float externalEnergySourceTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "external energy source temperature changed" << externalEnergySourceTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectExternalEnergySourceTemperatureStateTypeId, externalEnergySourceTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::supplyAirTemperatureChanged, this, [thing](float supplyAirTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "supply air temperature changed" << supplyAirTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectSupplyAirTemperatureStateTypeId, supplyAirTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::externalAirTemperatureChanged, this, [thing](float externalAirTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "external air temperature changed" << externalAirTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectExternalAirTemperatureStateTypeId, externalAirTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatingPumpOperatingHoursChanged, this, [thing](quint16 heatingPumpOperatingHours){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "heating pump operating hours changed" << heatingPumpOperatingHours;
|
||||
thing->setStateValue(alphaConnectHeatingPumpOperatingHoursStateTypeId, heatingPumpOperatingHours);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::systemStatusChanged, this, [thing](AlphaConnectModbusTcpConnection::SystemStatus systemStatus){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "system status changed" << systemStatus;
|
||||
switch (systemStatus) {
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusHeatingMode:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Heating mode");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusDomesticHotWater:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Domestic hot water");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusSwimmingPool:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Swimming pool");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusEVUOff:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "EUV off");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusDefrost:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Defrost");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusOff:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Off");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusExternalEnergySource:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "External energy source");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SystemStatusCoolingMode:
|
||||
thing->setStateValue(alphaConnectSystemStatusStateTypeId, "Cooling mode");
|
||||
break;
|
||||
}
|
||||
|
||||
// Set heating and cooling states according to the system state
|
||||
thing->setStateValue(alphaConnectHeatingOnStateTypeId, systemStatus == AlphaConnectModbusTcpConnection::SystemStatusHeatingMode);
|
||||
thing->setStateValue(alphaConnectCoolingOnStateTypeId, systemStatus == AlphaConnectModbusTcpConnection::SystemStatusCoolingMode);
|
||||
});
|
||||
|
||||
// Energy
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::totalHeatEnergyChanged, this, [thing](float totalHeatEnergy){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "total heating energy changed" << totalHeatEnergy << "kWh";
|
||||
thing->setStateValue(alphaConnectTotalEnergyStateTypeId, totalHeatEnergy);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::heatingEnergyChanged, this, [thing](float heatingEnergy){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "heating energy changed" << heatingEnergy << "kWh";
|
||||
thing->setStateValue(alphaConnectHeatingEnergyStateTypeId, heatingEnergy);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::waterHeatEnergyChanged, this, [thing](float waterHeatEnergy){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "water heat energy changed" << waterHeatEnergy << "kWh";
|
||||
thing->setStateValue(alphaConnectHotWaterEnergyStateTypeId, waterHeatEnergy);
|
||||
});
|
||||
|
||||
// connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::swimmingPoolHeatEnergyChanged, this, [thing](float swimmingPoolHeatEnergy){
|
||||
// qCDebug(dcAlphaInnotec()) << thing << "swimming pool heat energy changed" << swimmingPoolHeatEnergy << "kWh";
|
||||
// thing->setStateValue(alphaConnectSwimmingPoolEnergyStateTypeId, swimmingPoolHeatEnergy);
|
||||
// });
|
||||
|
||||
// Holding registers
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::outdoorTemperatureChanged, this, [thing](float outdoorTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "outdoor temperature changed" << outdoorTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectOutdoorTemperatureStateTypeId, outdoorTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::returnSetpointTemperatureChanged, this, [thing](float returnSetpointTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "return setpoint temperature changed" << returnSetpointTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectReturnSetpointTemperatureStateTypeId, returnSetpointTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::hotWaterSetpointTemperatureChanged, this, [thing](float hotWaterSetpointTemperature){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "hot water setpoint temperature changed" << hotWaterSetpointTemperature << "°C";
|
||||
thing->setStateValue(alphaConnectHotWaterSetpointTemperatureStateTypeId, hotWaterSetpointTemperature);
|
||||
});
|
||||
|
||||
connect(alphaConnectTcpConnection, &AlphaConnectModbusTcpConnection::smartGridChanged, this, [thing](AlphaConnectModbusTcpConnection::SmartGridState smartGridState){
|
||||
qCDebug(dcAlphaInnotec()) << thing << "smart grid state changed" << smartGridState;
|
||||
switch (smartGridState) {
|
||||
case AlphaConnectModbusTcpConnection::SmartGridStateOff:
|
||||
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Off");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SmartGridStateLow:
|
||||
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Low");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SmartGridStateStandard:
|
||||
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "Standard");
|
||||
break;
|
||||
case AlphaConnectModbusTcpConnection::SmartGridStateHigh:
|
||||
thing->setStateValue(alphaConnectSgReadyModeStateTypeId, "High");
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
m_alpaConnectTcpThings.insert(thing, alphaConnectTcpConnection);
|
||||
alphaConnectTcpConnection->connectDevice();
|
||||
|
||||
// FIXME: make async and check if this is really an alpha connect
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginAlphaInnotec::postSetupThing(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == alphaConnectThingClassId) {
|
||||
if (!m_pluginTimer) {
|
||||
qCDebug(dcAlphaInnotec()) << "Starting plugin timer...";
|
||||
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
|
||||
connect(m_pluginTimer, &PluginTimer::timeout, this, [this] {
|
||||
foreach (AlphaConnectModbusTcpConnection *connection, m_alpaConnectTcpThings) {
|
||||
if (connection->connected()) {
|
||||
connection->update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
m_pluginTimer->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginAlphaInnotec::thingRemoved(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == alphaConnectThingClassId && m_alpaConnectTcpThings.contains(thing)) {
|
||||
AlphaConnectModbusTcpConnection *connection = m_alpaConnectTcpThings.take(thing);
|
||||
delete connection;
|
||||
}
|
||||
|
||||
if (myThings().isEmpty() && m_pluginTimer) {
|
||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer);
|
||||
m_pluginTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginAlphaInnotec::executeAction(ThingActionInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
AlphaConnectModbusTcpConnection *connection = m_alpaConnectTcpThings.value(thing);
|
||||
|
||||
if (!connection->connected()) {
|
||||
qCWarning(dcAlphaInnotec()) << "Could not execute action. The modbus connection is currently not available.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == alphaConnectThingClassId) {
|
||||
/* if (info->action().actionTypeId() == alphaConnectOutdoorTemperatureActionTypeId) {
|
||||
double outdoorTemperature = info->action().paramValue(alphaConnectOutdoorTemperatureActionOutdoorTemperatureParamTypeId).toDouble();
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
|
||||
QModbusReply *reply = connection->setOutdoorTemperature(outdoorTemperature);
|
||||
if (!reply) {
|
||||
qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, info, [info, reply, outdoorTemperature]{
|
||||
if (reply->error() != QModbusDevice::NoError) {
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
qCWarning(dcAlphaInnotec()) << "Set outdoor temperature finished with error" << reply->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
|
||||
info->thing()->setStateValue(alphaConnectOutdoorTemperatureStateTypeId, outdoorTemperature);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
|
||||
qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
|
||||
emit reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
} else */
|
||||
if (info->action().actionTypeId() == alphaConnectHotWaterSetpointTemperatureActionTypeId) {
|
||||
double temperature = info->action().paramValue(alphaConnectHotWaterSetpointTemperatureActionHotWaterSetpointTemperatureParamTypeId).toDouble();
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
|
||||
QModbusReply *reply = connection->setHotWaterSetpointTemperature(temperature);
|
||||
if (!reply) {
|
||||
qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, info, [info, reply, temperature]{
|
||||
if (reply->error() != QModbusDevice::NoError) {
|
||||
qCWarning(dcAlphaInnotec()) << "Set hot water setpoint temperature finished with error" << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
|
||||
info->thing()->setStateValue(alphaConnectHotWaterSetpointTemperatureStateTypeId, temperature);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
|
||||
qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
|
||||
emit reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
} else if (info->action().actionTypeId() == alphaConnectReturnSetpointTemperatureActionTypeId) {
|
||||
double temperature = info->action().paramValue(alphaConnectReturnSetpointTemperatureActionReturnSetpointTemperatureParamTypeId).toDouble();
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
|
||||
QModbusReply *reply = connection->setReturnSetpointTemperature(temperature);
|
||||
if (!reply) {
|
||||
qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, info, [info, reply, temperature]{
|
||||
if (reply->error() != QModbusDevice::NoError) {
|
||||
qCWarning(dcAlphaInnotec()) << "Set return setpoint temperature finished with error" << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
|
||||
info->thing()->setStateValue(alphaConnectReturnSetpointTemperatureStateTypeId, temperature);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
|
||||
qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
|
||||
emit reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
} else if (info->action().actionTypeId() == alphaConnectSgReadyModeActionTypeId) {
|
||||
QString sgReadyModeString = info->action().paramValue(alphaConnectSgReadyModeActionSgReadyModeParamTypeId).toString();
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action" << info->action().actionTypeId().toString() << info->action().params();
|
||||
AlphaConnectModbusTcpConnection::SmartGridState sgReadyState;
|
||||
if (sgReadyModeString == "Off") {
|
||||
sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateOff;
|
||||
} else if (sgReadyModeString == "Low") {
|
||||
sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateLow;
|
||||
} else if (sgReadyModeString == "High") {
|
||||
sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateHigh;
|
||||
} else {
|
||||
sgReadyState = AlphaConnectModbusTcpConnection::SmartGridStateStandard;
|
||||
}
|
||||
|
||||
QModbusReply *reply = connection->setSmartGrid(sgReadyState);
|
||||
if (!reply) {
|
||||
qCWarning(dcAlphaInnotec()) << "Execute action failed because the reply could not be created.";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
connect(reply, &QModbusReply::finished, info, [info, reply, sgReadyModeString]{
|
||||
if (reply->error() != QModbusDevice::NoError) {
|
||||
qCWarning(dcAlphaInnotec()) << "Set SG ready mode finished with error" << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcAlphaInnotec()) << "Execute action finished successfully" << info->action().actionTypeId().toString() << info->action().params();
|
||||
info->thing()->setStateValue(alphaConnectSgReadyModeStateTypeId, sgReadyModeString);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
|
||||
connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){
|
||||
qCWarning(dcAlphaInnotec()) << "Modbus reply error occurred while execute action" << error << reply->errorString();
|
||||
emit reply->finished(); // To make sure it will be deleted
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef INTEGRATIONPLUGINALPHAINNOTEC_H
|
||||
#define INTEGRATIONPLUGINALPHAINNOTEC_H
|
||||
|
||||
#include "plugintimer.h"
|
||||
#include "alphaconnectmodbustcpconnection.h"
|
||||
#include "integrations/integrationplugin.h"
|
||||
|
||||
class IntegrationPluginAlphaInnotec: public IntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginalphainnotec.json")
|
||||
Q_INTERFACES(IntegrationPlugin)
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginAlphaInnotec();
|
||||
|
||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||
void startMonitoringAutoThings() override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
private:
|
||||
PluginTimer *m_pluginTimer = nullptr;
|
||||
QHash<Thing *, AlphaConnectModbusTcpConnection *> m_alpaConnectTcpThings;
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINALPHAINNOTEC_H
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
{
|
||||
"name": "AlphaInnotec",
|
||||
"displayName": "alpha innotec",
|
||||
"id": "b3225a18-e9b0-443e-8c88-802d3132f94d",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "alphaInnotec",
|
||||
"displayName": "alpha Innotec",
|
||||
"id": "2c2101ae-7bb8-4012-97ba-cedf4cecd924",
|
||||
"thingClasses": [
|
||||
{
|
||||
"name": "alphaConnect",
|
||||
"displayName": "alpha connect",
|
||||
"id": "c5437b68-cfd2-4ec8-bad6-006fb5e8a8da",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"interfaces": ["smartgridheatpump", "connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "64a18910-9111-4eaf-986d-f7b64b03b99a",
|
||||
"name": "ipAddress",
|
||||
"displayName": "IP address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": "127.0.0.1"
|
||||
},
|
||||
{
|
||||
"id": "f791c219-98a5-41ee-8e5f-1bfb5136dc9c",
|
||||
"name":"macAddress",
|
||||
"displayName": "MAC address",
|
||||
"type": "QString",
|
||||
"inputType": "MacAddress",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "b92025c1-8978-4d47-bd3c-4df749dbfd0f",
|
||||
"name":"port",
|
||||
"displayName": "Port",
|
||||
"type": "int",
|
||||
"defaultValue": 502
|
||||
},
|
||||
{
|
||||
"id": "1d9517ca-680c-49e2-a8d1-320743c27559",
|
||||
"name":"slaveId",
|
||||
"displayName": "Modbus slave ID",
|
||||
"type": "int",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "01ce0d61-3813-4c1b-a18b-555913d689a2",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "07465fbb-6949-4bd1-90d5-acf2d80c161d",
|
||||
"name": "heatingOn",
|
||||
"displayName": "Heating on",
|
||||
"displayNameEvent": "Heating turned on/off",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "8b407c1d-b84f-48d4-9961-b29bc58fff0e",
|
||||
"name": "coolingOn",
|
||||
"displayName": "Cooling on",
|
||||
"displayNameEvent": "Cooling turned on/off",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "fb448191-69d7-4f2e-87bf-6e4fb61e403f",
|
||||
"name": "flowTemperature",
|
||||
"displayName": "Flow temperature",
|
||||
"displayNameEvent": "Flow temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d",
|
||||
"name": "returnTemperature",
|
||||
"displayName": "Return temperature",
|
||||
"displayNameEvent": "Return temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "b6702fc5-889b-48b6-9257-64c5ee6e5e95",
|
||||
"name": "externalReturnTemperature",
|
||||
"displayName": "External return temperature",
|
||||
"displayNameEvent": "External return temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "da7e6bc9-95fd-4c90-931f-5b1cd69d864a",
|
||||
"name": "hotWaterTemperature",
|
||||
"displayName": "Hot water temperature",
|
||||
"displayNameEvent": "Hot water temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "bea6658e-64bf-4476-b75d-38c34a5fed85",
|
||||
"name": "hotGasTemperature",
|
||||
"displayName": "Hot gas temperature",
|
||||
"displayNameEvent": "Hot gas temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "e9facc5d-f41c-4256-85aa-b0f777431975",
|
||||
"name": "heatSourceInletTemperature",
|
||||
"displayName": "Heat source inlet temperature",
|
||||
"displayNameEvent": "Heat source inlet temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "48424285-4bc4-4110-8089-0486292d7371",
|
||||
"name": "heatSourceOutletTemperature",
|
||||
"displayName": "Heat source outlet temperature",
|
||||
"displayNameEvent": "Heat source outlet temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "52f8a581-7b9c-4c15-8aaa-c083763e7820",
|
||||
"name": "roomTemperature1",
|
||||
"displayName": "Room remote adjuster 1 temperature",
|
||||
"displayNameEvent": "Room remote adjuster 1 temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "91b57690-5daa-4766-86ae-f205fa0c805a",
|
||||
"name": "roomTemperature2",
|
||||
"displayName": "Room remote adjuster 2 temperature",
|
||||
"displayNameEvent": "Room remote adjuster 2 temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "a8c7e706-57ba-4572-b6e6-5eec91065ea8",
|
||||
"name": "roomTemperature3",
|
||||
"displayName": "Room remote adjuster 3 temperature",
|
||||
"displayNameEvent": "Room remote adjuster 3 temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "d4484305-eb0f-418b-bb15-f71b08e6fce1",
|
||||
"name": "solarCollectorTemperature",
|
||||
"displayName": "Solar collector temperature",
|
||||
"displayNameEvent": "Solar collector temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "75089369-c224-4fe5-91d1-9bdc5578f0a5",
|
||||
"name": "solarStorageTankTemperature",
|
||||
"displayName": "Solar storage tank temperature",
|
||||
"displayNameEvent": "Solar storage tank temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "519d7d45-1f3d-4118-ade9-3d7508451005",
|
||||
"name": "externalEnergySourceTemperature",
|
||||
"displayName": "External energy source temperature",
|
||||
"displayNameEvent": "External energy source temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "90d88164-3083-47c7-a396-b338bd9ea54c",
|
||||
"name": "supplyAirTemperature",
|
||||
"displayName": "Supply air temperature",
|
||||
"displayNameEvent": "Supply air temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "92594f19-8e4c-485b-bfd5-5371a0454267",
|
||||
"name": "externalAirTemperature",
|
||||
"displayName": "External air temperature",
|
||||
"displayNameEvent": "External air temperature changed",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "5a21a131-f3a0-4ebd-9b2e-12eb25c84853",
|
||||
"name": "systemStatus",
|
||||
"displayName": "System status",
|
||||
"displayNameEvent": "System status changed",
|
||||
"type": "QString",
|
||||
"possibleValues": [
|
||||
"Heating mode",
|
||||
"Domestic hot water",
|
||||
"Swimming pool",
|
||||
"EUV off",
|
||||
"Defrost",
|
||||
"Off",
|
||||
"External energy source",
|
||||
"Cooling mode"
|
||||
],
|
||||
"defaultValue": "Heating mode",
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "ef378ce6-f112-4022-8535-78cbd6ccfeeb",
|
||||
"name": "heatingPumpOperatingHours",
|
||||
"displayName": "Heating pump operating hours",
|
||||
"displayNameEvent": "Heating pump operating hours changed",
|
||||
"unit": "Hours",
|
||||
"type": "uint",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "d0c8f168-49b5-47ca-9988-c9922be38dd5",
|
||||
"name": "outdoorTemperature",
|
||||
"displayName": "Outdoor temperature",
|
||||
"displayNameEvent": "Outdoor temperature changed",
|
||||
"displayNameAction": "Set outdoor temperature",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "1ee6b189-ceff-4912-a577-2e3320307c3f",
|
||||
"name": "returnSetpointTemperature",
|
||||
"displayName": "Return temperature setpoint",
|
||||
"displayNameEvent": "Return temperature setpoint changed",
|
||||
"displayNameAction": "Set return temperature setpoint",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"writable": true,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "a7f1a688-51d3-4f9e-a323-86117c5542a8",
|
||||
"name": "hotWaterSetpointTemperature",
|
||||
"displayName": "Hot water temperature setpoint",
|
||||
"displayNameEvent": "Hot water temperature setpoint changed",
|
||||
"displayNameAction": "Set hot water temperature setpoint",
|
||||
"unit": "DegreeCelsius",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"writable": true,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "8cc9761f-b30e-4f54-aee7-b64190df57e1",
|
||||
"name": "sgReadyMode",
|
||||
"displayName": "Smart grid mode",
|
||||
"displayNameEvent": "Smart grid mode changed",
|
||||
"displayNameAction": "Set smart grid mode",
|
||||
"type": "QString",
|
||||
"possibleValues": [
|
||||
"Off",
|
||||
"Low",
|
||||
"Standard",
|
||||
"High"
|
||||
],
|
||||
"writable": true,
|
||||
"defaultValue": "Standard",
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "c7948cf6-fd1a-44fa-a91b-98f2474ecc62",
|
||||
"name": "totalEnergy",
|
||||
"displayName": "Total energy",
|
||||
"displayNameEvent": "Total energy changed",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "24367fba-2883-40da-9b92-5d4db3c71c2f",
|
||||
"name": "heatingEnergy",
|
||||
"displayName": "Heating energy",
|
||||
"displayNameEvent": "Heating energy changed",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
},
|
||||
{
|
||||
"id": "be2430c3-54ef-441e-b684-9aabc1d984d6",
|
||||
"name": "hotWaterEnergy",
|
||||
"displayName": "Hot water energy",
|
||||
"displayNameEvent": "Hot water energy changed",
|
||||
"type": "double",
|
||||
"unit": "KiloWattHour",
|
||||
"defaultValue": 0,
|
||||
"suggestLogging": true
|
||||
}
|
||||
],
|
||||
"actionTypes": [ ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"title": "alpha innotec",
|
||||
"tagline": "Integrate alpha innotec heat pumps into nymea.",
|
||||
"icon": "alpha-innotec.png",
|
||||
"stability": "community",
|
||||
"offline": true,
|
||||
"technologies": [
|
||||
"network"
|
||||
],
|
||||
"categories": [
|
||||
"heating"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,431 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>AlphaInnotec</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="106"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="109"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: connected, ID: {01ce0d61-3813-4c1b-a18b-555913d689a2})
|
||||
----------
|
||||
The name of the StateType ({01ce0d61-3813-4c1b-a18b-555913d689a2}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="112"/>
|
||||
<source>Connected changed</source>
|
||||
<extracomment>The name of the EventType ({01ce0d61-3813-4c1b-a18b-555913d689a2}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="115"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="118"/>
|
||||
<source>Cooling on</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: coolingOn, ID: {8b407c1d-b84f-48d4-9961-b29bc58fff0e})
|
||||
----------
|
||||
The name of the StateType ({8b407c1d-b84f-48d4-9961-b29bc58fff0e}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="121"/>
|
||||
<source>Cooling turned on/off</source>
|
||||
<extracomment>The name of the EventType ({8b407c1d-b84f-48d4-9961-b29bc58fff0e}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="124"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="127"/>
|
||||
<source>External air temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: externalAirTemperature, ID: {92594f19-8e4c-485b-bfd5-5371a0454267})
|
||||
----------
|
||||
The name of the StateType ({92594f19-8e4c-485b-bfd5-5371a0454267}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="130"/>
|
||||
<source>External air temperature changed</source>
|
||||
<extracomment>The name of the EventType ({92594f19-8e4c-485b-bfd5-5371a0454267}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="133"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="136"/>
|
||||
<source>External energy source temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: externalEnergySourceTemperature, ID: {519d7d45-1f3d-4118-ade9-3d7508451005})
|
||||
----------
|
||||
The name of the StateType ({519d7d45-1f3d-4118-ade9-3d7508451005}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="139"/>
|
||||
<source>External energy source temperature changed</source>
|
||||
<extracomment>The name of the EventType ({519d7d45-1f3d-4118-ade9-3d7508451005}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="142"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="145"/>
|
||||
<source>External return temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: externalReturnTemperature, ID: {b6702fc5-889b-48b6-9257-64c5ee6e5e95})
|
||||
----------
|
||||
The name of the StateType ({b6702fc5-889b-48b6-9257-64c5ee6e5e95}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="148"/>
|
||||
<source>External return temperature changed</source>
|
||||
<extracomment>The name of the EventType ({b6702fc5-889b-48b6-9257-64c5ee6e5e95}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="151"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="154"/>
|
||||
<source>Flow temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: flowTemperature, ID: {fb448191-69d7-4f2e-87bf-6e4fb61e403f})
|
||||
----------
|
||||
The name of the StateType ({fb448191-69d7-4f2e-87bf-6e4fb61e403f}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="157"/>
|
||||
<source>Flow temperature changed</source>
|
||||
<extracomment>The name of the EventType ({fb448191-69d7-4f2e-87bf-6e4fb61e403f}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="160"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="163"/>
|
||||
<source>Heat source inlet temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: heatSourceInletTemperature, ID: {e9facc5d-f41c-4256-85aa-b0f777431975})
|
||||
----------
|
||||
The name of the StateType ({e9facc5d-f41c-4256-85aa-b0f777431975}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="166"/>
|
||||
<source>Heat source inlet temperature changed</source>
|
||||
<extracomment>The name of the EventType ({e9facc5d-f41c-4256-85aa-b0f777431975}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="169"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="172"/>
|
||||
<source>Heat source outlet temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: heatSourceOutletTemperature, ID: {48424285-4bc4-4110-8089-0486292d7371})
|
||||
----------
|
||||
The name of the StateType ({48424285-4bc4-4110-8089-0486292d7371}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="175"/>
|
||||
<source>Heat source outlet temperature changed</source>
|
||||
<extracomment>The name of the EventType ({48424285-4bc4-4110-8089-0486292d7371}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="178"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="181"/>
|
||||
<source>Heating on</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: heatingOn, ID: {07465fbb-6949-4bd1-90d5-acf2d80c161d})
|
||||
----------
|
||||
The name of the StateType ({07465fbb-6949-4bd1-90d5-acf2d80c161d}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="184"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="187"/>
|
||||
<source>Heating pump operating hours</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: heatingPumpOperatingHours, ID: {ef378ce6-f112-4022-8535-78cbd6ccfeeb})
|
||||
----------
|
||||
The name of the StateType ({ef378ce6-f112-4022-8535-78cbd6ccfeeb}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="190"/>
|
||||
<source>Heating pump operating hours changed</source>
|
||||
<extracomment>The name of the EventType ({ef378ce6-f112-4022-8535-78cbd6ccfeeb}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="193"/>
|
||||
<source>Heating turned on/off</source>
|
||||
<extracomment>The name of the EventType ({07465fbb-6949-4bd1-90d5-acf2d80c161d}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="196"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="199"/>
|
||||
<source>Hot gas temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: hotGasTemperature, ID: {bea6658e-64bf-4476-b75d-38c34a5fed85})
|
||||
----------
|
||||
The name of the StateType ({bea6658e-64bf-4476-b75d-38c34a5fed85}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="202"/>
|
||||
<source>Hot gas temperature changed</source>
|
||||
<extracomment>The name of the EventType ({bea6658e-64bf-4476-b75d-38c34a5fed85}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="205"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="208"/>
|
||||
<source>Hot water temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: hotWaterTemperature, ID: {da7e6bc9-95fd-4c90-931f-5b1cd69d864a})
|
||||
----------
|
||||
The name of the StateType ({da7e6bc9-95fd-4c90-931f-5b1cd69d864a}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="211"/>
|
||||
<source>Hot water temperature changed</source>
|
||||
<extracomment>The name of the EventType ({da7e6bc9-95fd-4c90-931f-5b1cd69d864a}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="214"/>
|
||||
<source>IP address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {64a18910-9111-4eaf-986d-f7b64b03b99a})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="217"/>
|
||||
<source>MAC address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {f791c219-98a5-41ee-8e5f-1bfb5136dc9c})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="220"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="223"/>
|
||||
<source>Mean temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: meanTemperature, ID: {956051a6-8677-4b25-b899-71aa3590d4e5})
|
||||
----------
|
||||
The name of the StateType ({956051a6-8677-4b25-b899-71aa3590d4e5}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="226"/>
|
||||
<source>Mean temperature changed</source>
|
||||
<extracomment>The name of the EventType ({956051a6-8677-4b25-b899-71aa3590d4e5}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="229"/>
|
||||
<source>Modbus slave ID</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {1d9517ca-680c-49e2-a8d1-320743c27559})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="232"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="235"/>
|
||||
<source>Outdoor temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: outdoorTemperature, ID: {d0c8f168-49b5-47ca-9988-c9922be38dd5})
|
||||
----------
|
||||
The name of the StateType ({d0c8f168-49b5-47ca-9988-c9922be38dd5}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="238"/>
|
||||
<source>Outdoor temperature changed</source>
|
||||
<extracomment>The name of the EventType ({d0c8f168-49b5-47ca-9988-c9922be38dd5}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="241"/>
|
||||
<source>Port</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, Type: thing, ID: {b92025c1-8978-4d47-bd3c-4df749dbfd0f})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="244"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="247"/>
|
||||
<source>Return temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: returnTemperature, ID: {6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d})
|
||||
----------
|
||||
The name of the StateType ({6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="250"/>
|
||||
<source>Return temperature changed</source>
|
||||
<extracomment>The name of the EventType ({6f96706e-67a3-43d3-bf74-e2e3e5fd0d6d}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="253"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="256"/>
|
||||
<source>Room remote adjuster 1 temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: roomTemperature1, ID: {52f8a581-7b9c-4c15-8aaa-c083763e7820})
|
||||
----------
|
||||
The name of the StateType ({52f8a581-7b9c-4c15-8aaa-c083763e7820}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="259"/>
|
||||
<source>Room remote adjuster 1 temperature changed</source>
|
||||
<extracomment>The name of the EventType ({52f8a581-7b9c-4c15-8aaa-c083763e7820}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="262"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="265"/>
|
||||
<source>Room remote adjuster 2 temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: roomTemperature2, ID: {91b57690-5daa-4766-86ae-f205fa0c805a})
|
||||
----------
|
||||
The name of the StateType ({91b57690-5daa-4766-86ae-f205fa0c805a}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="268"/>
|
||||
<source>Room remote adjuster 2 temperature changed</source>
|
||||
<extracomment>The name of the EventType ({91b57690-5daa-4766-86ae-f205fa0c805a}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="271"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="274"/>
|
||||
<source>Room remote adjuster 3 temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: roomTemperature3, ID: {a8c7e706-57ba-4572-b6e6-5eec91065ea8})
|
||||
----------
|
||||
The name of the StateType ({a8c7e706-57ba-4572-b6e6-5eec91065ea8}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="277"/>
|
||||
<source>Room remote adjuster 3 temperature changed</source>
|
||||
<extracomment>The name of the EventType ({a8c7e706-57ba-4572-b6e6-5eec91065ea8}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="280"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="283"/>
|
||||
<source>Room temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: temperature, ID: {0b978a61-4340-443a-8ea6-69217a593508})
|
||||
----------
|
||||
The name of the StateType ({0b978a61-4340-443a-8ea6-69217a593508}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="286"/>
|
||||
<source>Room temperature changed</source>
|
||||
<extracomment>The name of the EventType ({0b978a61-4340-443a-8ea6-69217a593508}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="289"/>
|
||||
<source>Set target room temperature</source>
|
||||
<extracomment>The name of the ActionType ({2e8f44c5-c4e3-4539-b85b-45898bbbf6c2}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="292"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="295"/>
|
||||
<source>Solar collector temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: solarCollectorTemperature, ID: {d4484305-eb0f-418b-bb15-f71b08e6fce1})
|
||||
----------
|
||||
The name of the StateType ({d4484305-eb0f-418b-bb15-f71b08e6fce1}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="298"/>
|
||||
<source>Solar collector temperature changed</source>
|
||||
<extracomment>The name of the EventType ({d4484305-eb0f-418b-bb15-f71b08e6fce1}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="301"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="304"/>
|
||||
<source>Solar storage tank temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: solarStorageTankTemperature, ID: {75089369-c224-4fe5-91d1-9bdc5578f0a5})
|
||||
----------
|
||||
The name of the StateType ({75089369-c224-4fe5-91d1-9bdc5578f0a5}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="307"/>
|
||||
<source>Solar storage tank temperature changed</source>
|
||||
<extracomment>The name of the EventType ({75089369-c224-4fe5-91d1-9bdc5578f0a5}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="310"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="313"/>
|
||||
<source>Supply air temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: supplyAirTemperature, ID: {90d88164-3083-47c7-a396-b338bd9ea54c})
|
||||
----------
|
||||
The name of the StateType ({90d88164-3083-47c7-a396-b338bd9ea54c}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="316"/>
|
||||
<source>Supply air temperature changed</source>
|
||||
<extracomment>The name of the EventType ({90d88164-3083-47c7-a396-b338bd9ea54c}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="319"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="322"/>
|
||||
<source>System status</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, EventType: systemStatus, ID: {5a21a131-f3a0-4ebd-9b2e-12eb25c84853})
|
||||
----------
|
||||
The name of the StateType ({5a21a131-f3a0-4ebd-9b2e-12eb25c84853}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="325"/>
|
||||
<source>System status changed</source>
|
||||
<extracomment>The name of the EventType ({5a21a131-f3a0-4ebd-9b2e-12eb25c84853}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="328"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="331"/>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="334"/>
|
||||
<source>Target room temperature</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: alphaConnect, ActionType: targetTemperature, ID: {2e8f44c5-c4e3-4539-b85b-45898bbbf6c2})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: alphaConnect, EventType: targetTemperature, ID: {2e8f44c5-c4e3-4539-b85b-45898bbbf6c2})
|
||||
----------
|
||||
The name of the StateType ({2e8f44c5-c4e3-4539-b85b-45898bbbf6c2}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="337"/>
|
||||
<source>Target room temperature changed</source>
|
||||
<extracomment>The name of the EventType ({2e8f44c5-c4e3-4539-b85b-45898bbbf6c2}) of ThingClass alphaConnect</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="340"/>
|
||||
<source>alpha Innotec</source>
|
||||
<extracomment>The name of the vendor ({2c2101ae-7bb8-4012-97ba-cedf4cecd924})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="343"/>
|
||||
<source>alpha connect</source>
|
||||
<extracomment>The name of the ThingClass ({c5437b68-cfd2-4ec8-bad6-006fb5e8a8da})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-modbus-Desktop-Debug/alphainnotec/plugininfo.h" line="346"/>
|
||||
<source>alpha innotec</source>
|
||||
<extracomment>The name of the plugin AlphaInnotec ({b3225a18-e9b0-443e-8c88-802d3132f94d})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IntegrationPluginAlphaInnotec</name>
|
||||
<message>
|
||||
<location filename="../integrationpluginalphainnotec.cpp" line="46"/>
|
||||
<source>The network device discovery is not available.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginalphainnotec.cpp" line="103"/>
|
||||
<source>No IP address given</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
@ -46,6 +46,21 @@ Description: The main libraries and header files for developing with nymea sunsp
|
|||
.
|
||||
This package will install the development files for nymea sunspec.
|
||||
|
||||
Package: nymea-plugin-alphainnotec
|
||||
Architecture: any
|
||||
Section: libs
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
nymea-plugins-modbus-translations
|
||||
Description: nymea.io plugin for alpha innotec heat pumps
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
server works like a translator for devices, things and services and
|
||||
allows them to interact.
|
||||
With the powerful rule engine you are able to connect any device available
|
||||
in the system and create individual scenes and behaviors for your environment.
|
||||
.
|
||||
This package will install the nymea.io plugin for alpha innotec heat pumps
|
||||
|
||||
|
||||
Package: nymea-plugin-drexelundweiss
|
||||
Architecture: any
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginalphainnotec.so
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "modbusdatautils.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
ModbusDataUtils::ModbusDataUtils()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
quint16 ModbusDataUtils::convertToUInt16(const QVector<quint16> ®isters)
|
||||
{
|
||||
Q_ASSERT_X(registers.count() == 1, "ModbusDataUtils", "invalid raw data size for converting value to quint16");
|
||||
return registers.at(0);
|
||||
}
|
||||
|
||||
qint16 ModbusDataUtils::convertToInt16(const QVector<quint16> ®isters)
|
||||
{
|
||||
Q_ASSERT_X(registers.count() == 1, "ModbusDataUtils", "invalid raw data size for converting value to qint16");
|
||||
return static_cast<qint16>(registers.at(0));
|
||||
}
|
||||
|
||||
quint32 ModbusDataUtils::convertToUInt32(const QVector<quint16> ®isters, ByteOrder byteOrder)
|
||||
{
|
||||
Q_ASSERT_X(registers.count() == 2, "ModbusDataUtils", "invalid raw data size for converting value to quint32");
|
||||
QByteArray data;
|
||||
QDataStream inputStream(&data, QIODevice::WriteOnly);
|
||||
if (byteOrder == ByteOrderBigEndian) {
|
||||
inputStream << registers.at(0);
|
||||
inputStream << registers.at(1);
|
||||
} else {
|
||||
inputStream << registers.at(1);
|
||||
inputStream << registers.at(0);
|
||||
}
|
||||
|
||||
QDataStream outputStream(&data, QIODevice::ReadOnly);
|
||||
quint32 result = 0;
|
||||
outputStream >> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
qint32 ModbusDataUtils::convertToInt32(const QVector<quint16> ®isters, ByteOrder byteOrder)
|
||||
{
|
||||
Q_ASSERT_X(registers.count() == 2, "ModbusDataUtils", "invalid raw data size for converting value to quint32");
|
||||
QByteArray data;
|
||||
QDataStream inputStream(&data, QIODevice::WriteOnly);
|
||||
if (byteOrder == ByteOrderBigEndian) {
|
||||
inputStream << registers.at(0);
|
||||
inputStream << registers.at(1);
|
||||
} else {
|
||||
inputStream << registers.at(1);
|
||||
inputStream << registers.at(0);
|
||||
}
|
||||
|
||||
QDataStream outputStream(&data, QIODevice::ReadOnly);
|
||||
qint32 result = 0;
|
||||
outputStream >> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
quint64 ModbusDataUtils::convertToUInt64(const QVector<quint16> ®isters, ByteOrder byteOrder)
|
||||
{
|
||||
Q_ASSERT_X(registers.count() == 4, "ModbusDataUtils", "invalid raw data size for converting value to quint64");
|
||||
QByteArray data;
|
||||
QDataStream inputStream(&data, QIODevice::WriteOnly);
|
||||
if (byteOrder == ByteOrderBigEndian) {
|
||||
inputStream << registers.at(0);
|
||||
inputStream << registers.at(1);
|
||||
inputStream << registers.at(2);
|
||||
inputStream << registers.at(3);
|
||||
} else {
|
||||
inputStream << registers.at(3);
|
||||
inputStream << registers.at(2);
|
||||
inputStream << registers.at(1);
|
||||
inputStream << registers.at(0);
|
||||
}
|
||||
|
||||
QDataStream outputStream(&data, QIODevice::ReadOnly);
|
||||
quint64 result = 0;
|
||||
outputStream >> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
qint64 ModbusDataUtils::convertToInt64(const QVector<quint16> ®isters, ByteOrder byteOrder)
|
||||
{
|
||||
Q_ASSERT_X(registers.count() == 4, "ModbusDataUtils", "invalid raw data size for converting value to qint64");
|
||||
QByteArray data;
|
||||
QDataStream inputStream(&data, QIODevice::WriteOnly);
|
||||
if (byteOrder == ByteOrderBigEndian) {
|
||||
inputStream << registers.at(0);
|
||||
inputStream << registers.at(1);
|
||||
inputStream << registers.at(2);
|
||||
inputStream << registers.at(3);
|
||||
} else {
|
||||
inputStream << registers.at(3);
|
||||
inputStream << registers.at(2);
|
||||
inputStream << registers.at(1);
|
||||
inputStream << registers.at(0);
|
||||
}
|
||||
|
||||
QDataStream outputStream(&data, QIODevice::ReadOnly);
|
||||
qint64 result = 0;
|
||||
outputStream >> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
QString ModbusDataUtils::convertToString(const QVector<quint16> ®isters)
|
||||
{
|
||||
QByteArray bytes;
|
||||
QDataStream stream(&bytes, QIODevice::WriteOnly);
|
||||
for (int i = 0; i < registers.count(); i++) {
|
||||
stream << registers.at(i);
|
||||
}
|
||||
|
||||
return QString::fromUtf8(bytes).trimmed();
|
||||
}
|
||||
|
||||
float ModbusDataUtils::convertToFloat32(const QVector<quint16> ®isters, ByteOrder byteOrder)
|
||||
{
|
||||
Q_ASSERT_X(registers.count() == 2, "ModbusDataUtils", "invalid raw data size for converting value to float32");
|
||||
quint32 rawValue = ModbusDataUtils::convertToUInt32(registers, byteOrder);
|
||||
float value = 0;
|
||||
memcpy(&value, &rawValue, sizeof(quint32));
|
||||
return value;
|
||||
}
|
||||
|
||||
double ModbusDataUtils::convertToFloat64(const QVector<quint16> ®isters, ByteOrder byteOrder)
|
||||
{
|
||||
|
||||
Q_ASSERT_X(registers.count() == 4, "ModbusDataUtils", "invalid raw data size for converting value to float64");
|
||||
quint64 rawValue = ModbusDataUtils::convertToUInt64(registers, byteOrder);
|
||||
double value = 0;
|
||||
memcpy(&value, &rawValue, sizeof(quint64));
|
||||
return value;
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromUInt16(quint16 value)
|
||||
{
|
||||
return QVector<quint16>() << value;
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromInt16(qint16 value)
|
||||
{
|
||||
return ModbusDataUtils::convertFromUInt16(static_cast<quint16>(value));
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromUInt32(quint32 value, ByteOrder byteOrder)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream inputStream(&data, QIODevice::WriteOnly);
|
||||
inputStream << value;
|
||||
|
||||
QDataStream outputStream(&data, QIODevice::ReadOnly);
|
||||
QVector<quint16> values;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
quint16 registerValue = 0;
|
||||
outputStream >> registerValue;
|
||||
if (byteOrder == ByteOrderBigEndian) {
|
||||
values.append(registerValue);
|
||||
} else {
|
||||
values.prepend(registerValue);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromInt32(qint32 value, ByteOrder byteOrder)
|
||||
{
|
||||
return ModbusDataUtils::convertFromUInt32(static_cast<quint32>(value), byteOrder);
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromUInt64(quint64 value, ByteOrder byteOrder)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream inputStream(&data, QIODevice::WriteOnly);
|
||||
inputStream << value;
|
||||
|
||||
QDataStream outputStream(&data, QIODevice::ReadOnly);
|
||||
QVector<quint16> values;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quint16 registerValue = 0;
|
||||
outputStream >> registerValue;
|
||||
if (byteOrder == ByteOrderBigEndian) {
|
||||
values.append(registerValue);
|
||||
} else {
|
||||
values.prepend(registerValue);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromInt64(qint64 value, ByteOrder byteOrder)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream inputStream(&data, QIODevice::WriteOnly);
|
||||
inputStream << value;
|
||||
|
||||
QDataStream outputStream(&data, QIODevice::ReadOnly);
|
||||
QVector<quint16> values;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quint16 registerValue = 0;
|
||||
outputStream >> registerValue;
|
||||
if (byteOrder == ByteOrderBigEndian) {
|
||||
values.append(registerValue);
|
||||
} else {
|
||||
values.prepend(registerValue);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromString(const QString &value, quint16 stringLength)
|
||||
{
|
||||
Q_ASSERT_X(value.length() <= stringLength, "ModbusDataUtils", "cannot convert a string which is bigger than the desired register vector.");
|
||||
QByteArray data = value.toLatin1() + QByteArray('\0', stringLength - value.count());
|
||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||
QVector<quint16> values;
|
||||
for (int i = 0; i < stringLength; i++) {
|
||||
quint16 registerValue = 0;
|
||||
stream >> registerValue;
|
||||
values.append(registerValue);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromFloat32(float value, ByteOrder byteOrder)
|
||||
{
|
||||
quint32 rawValue = 0;
|
||||
memcpy(&rawValue, &value, sizeof(float));
|
||||
return ModbusDataUtils::convertFromUInt32(rawValue, byteOrder);
|
||||
}
|
||||
|
||||
QVector<quint16> ModbusDataUtils::convertFromFloat64(double value, ByteOrder byteOrder)
|
||||
{
|
||||
quint64 rawValue = 0;
|
||||
memcpy(&rawValue, &value, sizeof(double));
|
||||
return ModbusDataUtils::convertFromUInt64(rawValue, byteOrder);
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2021, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef MODBUSDATAUTILS_H
|
||||
#define MODBUSDATAUTILS_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QObject>
|
||||
|
||||
class ModbusDataUtils
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum Access {
|
||||
AccessReadOnly,
|
||||
AccessWriteOnly,
|
||||
AccessReadWrite
|
||||
};
|
||||
Q_ENUM(Access)
|
||||
|
||||
enum ByteOrder {
|
||||
ByteOrderLittleEndian,
|
||||
ByteOrderBigEndian
|
||||
};
|
||||
Q_ENUM(ByteOrder)
|
||||
|
||||
enum DataType {
|
||||
UInt8,
|
||||
UInt16,
|
||||
Uint32,
|
||||
Uint64,
|
||||
Int8,
|
||||
Int16,
|
||||
Int32,
|
||||
Int64,
|
||||
Float,
|
||||
Float64,
|
||||
String,
|
||||
Bool
|
||||
};
|
||||
Q_ENUM(DataType)
|
||||
|
||||
typedef struct ModbusRegister {
|
||||
quint16 address;
|
||||
quint16 size;
|
||||
DataType dataType;
|
||||
Access access;
|
||||
QString description;
|
||||
QString unit;
|
||||
QVector<quint16> rawData;
|
||||
} ModbusRegister;
|
||||
|
||||
typedef QVector<ModbusRegister> ModbusRegisters;
|
||||
|
||||
explicit ModbusDataUtils();
|
||||
|
||||
// Convert to
|
||||
static quint16 convertToUInt16(const QVector<quint16> ®isters);
|
||||
static qint16 convertToInt16(const QVector<quint16> ®isters);
|
||||
static quint32 convertToUInt32(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static qint32 convertToInt32(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static quint64 convertToUInt64(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static qint64 convertToInt64(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QString convertToString(const QVector<quint16> ®isters);
|
||||
static float convertToFloat32(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static double convertToFloat64(const QVector<quint16> ®isters, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
|
||||
// Convert from
|
||||
static QVector<quint16> convertFromUInt16(quint16 value);
|
||||
static QVector<quint16> convertFromInt16(qint16 value);
|
||||
static QVector<quint16> convertFromUInt32(quint32 value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromInt32(qint32 value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromUInt64(quint64 value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromInt64(qint64 value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromString(const QString &value, quint16 stringLength);
|
||||
static QVector<quint16> convertFromFloat32(float value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
static QVector<quint16> convertFromFloat64(double value, ByteOrder byteOrder = ByteOrderLittleEndian);
|
||||
};
|
||||
|
||||
#endif // MODBUSDATAUTILS_H
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
# Generate a modbus read class
|
||||
|
||||
In order to make the plugin development for modbus TCP devices much easier and faster, a small tool has been developed to generate a modbus TCP master based class providing get and set methods for the registers and property changed signals.
|
||||
|
||||
The workflow looks like this:
|
||||
|
||||
* Write the `registers.json` file containing all register information you are interested to.
|
||||
* Run the script and provide the class name, output directory and the path to the JSON file
|
||||
* Include the generated class in your plugin, connect the `<propertyName>Changed()` signal and update the thing state within the plugin.
|
||||
|
||||
|
||||
The class will provide 2 main methods for fetching information from the modbus device:
|
||||
|
||||
* `initialize()` will read all registers with `"readSchedule": "init"` and emits the signal `initializationFinished()` once all replies returned.
|
||||
* `update()` can be used to update all registers with `"readSchedule": "update"`. The class will then fetch each register and update the specified value internally. If the value has changed, the `<propertyName>Changed()` signal will be emitted.
|
||||
|
||||
The reulting class will inhert from the `ModbusTCPMaster` class, providing easy access to all possible modbus operations and inform about the connected state.
|
||||
|
||||
|
||||
# JSON format
|
||||
|
||||
The basic structure of the modbus register JSON looks like following example:
|
||||
|
||||
```
|
||||
{
|
||||
"endianness": "BigEndian",
|
||||
"enums": [
|
||||
{
|
||||
"name": "NameOfEnum",
|
||||
"values": [
|
||||
{
|
||||
"key": "EnumValue1",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"key": "EnumValue2",
|
||||
"value": 1
|
||||
},
|
||||
....
|
||||
]
|
||||
}
|
||||
],
|
||||
"registers": [
|
||||
{
|
||||
"id": "registerPropertyName",
|
||||
"address": 4,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "init",
|
||||
"description": "Description of the register",
|
||||
"unit": "V",
|
||||
"defaultValue": "0",
|
||||
"access": "RO"
|
||||
},
|
||||
{
|
||||
"id": "registerWithEnumValues",
|
||||
"address": 5,
|
||||
"size": 1,
|
||||
"type": "uint16",
|
||||
"readSchedule": "update",
|
||||
"enum": "NameOfEnum",
|
||||
"defaultValue": "NameOfEnumEnumValue1",
|
||||
"description": "Description of the enum register like states",
|
||||
"access": "RO"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Endianness
|
||||
|
||||
When converting multiple registers to one data type (i.e. 2 registers uint16 values to one uint32), the order of the registers are important to align with the endiness of the data receiving.
|
||||
|
||||
There are 2 possibilities:
|
||||
|
||||
* `BigEndian`: default if not specified: register bytes come in following order `[0, 1, 2, 3]`: `ABCD`
|
||||
* `LittleEndian`: register bytes come in following order `[0, 1, 2, 3]`: `CDAB`
|
||||
|
||||
## Enums
|
||||
|
||||
Many modbus devices provide inforation using `Enums`, indicating a special state trough a defined list of values. If a register implements an enum, you can define it in the `enums` section. The `name` property defines the name of the enum, and the script will generate a c++ enum definition from this section. Each enum value will then be generated using `<EnumName><EnumValueName> = <value>`.
|
||||
|
||||
If a register represets an enum, you simply add the property `"enum": "NameOfEnum"` in the register map and the property will be defined using the resulting enum type. All convertion between enum and resulting modbus register value will be done automatically.
|
||||
|
||||
## Registers
|
||||
|
||||
Earch register will be defined as a property in the resulting class modbus TCP class providing easy access to the register data.
|
||||
|
||||
* `id`: Mandatory. The id defines the name of the property used in the resulting class.
|
||||
* `address`: Mandatory. The modbus address of the register.
|
||||
* `size`: Mandatory. The amount of registers to read for the property.
|
||||
* `type`: Mandatory. The data type of this property. Available data types are:
|
||||
* `uint16` : will be converted to `quint16`
|
||||
* `int16` : will be converted to `qint16`
|
||||
* `uint32` : will be converted to `quint32`
|
||||
* `int32` : will be converted to `qint32`
|
||||
* `uint64` : will be converted to `quint64`
|
||||
* `int64` : will be converted to `qint64`
|
||||
* `float`: will be converted to `float`
|
||||
* `float64`: will be converted to `double`
|
||||
* `string` : will be converted to `QString`
|
||||
* `readSchedule`: Optional. Defines when the register needs to be fetched. If no read schedule has been defined, the class will provide only the update methods, but will not read the value during `initialize()` or `update()` calls. Possible values are:
|
||||
* `init`: The register will be fetched during initialization. Once all `init `registers have been fetched, the `initializationFinished()` signal will be emitted.
|
||||
* `update`: The register will be feched each time the `update()` method will be called.
|
||||
* `enum`: Optional: If the given data type represents an enum value, this propery can be set to the name of the used enum from the `enum` definition. The class will take care internally about the data convertion from and to the enum values.
|
||||
* `description`: Mandatory. A clear description of the register.
|
||||
* `unit`: Optional. Represents the unit of this register value.
|
||||
* `registerType`: Optional. Represents the type of the register and how to read/write it. Default is `holdingRegister`. Possible values are:
|
||||
* `holdingRegister`
|
||||
* `inputRegister`
|
||||
* `coils`
|
||||
* `discreteInputs`
|
||||
* `access`: Mandatory. Describes the access to this register. Possible valies are:
|
||||
* `RO`: Read only access. Only the get method and the changed singal will be defined.
|
||||
* `RW`: Read and write access. Also a set mehtod will be defined.
|
||||
* `WO`: Write only. Only the set method will be defined.
|
||||
* `scaleFactor`: Optional. The name of the scale factor register to convert this value to float. `floatValue = intValue * 10^scaleFactor value`. The scale factor value is normally a `int16` value, i.e. -10 or 10
|
||||
* `staticScaleFactor`: Optional. Use this static scale factor to convert this register value to float. `floatValue = registerValue * 10^staticScaleFactor`. The scale factor value is normally a `int16` value, i.e. -10 or 10
|
||||
* `defaultValue`: Optional. The value for initializing the property.
|
||||
|
||||
# Example
|
||||
|
||||
Change into your plugin sub directory.
|
||||
Assuming you wrote the registers.json file you can run now following command to generate your modbus class:
|
||||
|
||||
`$ python3 ../modbus/tools/generate-connection.py -j registers.json -o . -c MyModbusConnection`
|
||||
|
||||
You the result will be a header and a source file called:
|
||||
|
||||
* `mymodbusconnection.h`
|
||||
* `mymodbusconnection.cpp`
|
||||
|
||||
You can include this class in your project and provide one connection per thing.
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,686 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2021 nymea GmbH <developer@nymea.io>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
# To lazy to type all those register plugins, let's make live much easier and generate code from a json register definition
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import argparse
|
||||
import datetime
|
||||
|
||||
def convertToAlphaNumeric(text):
|
||||
finalText = ''
|
||||
for character in text:
|
||||
if character.isalnum():
|
||||
finalText += character
|
||||
else:
|
||||
finalText += ' '
|
||||
return finalText
|
||||
|
||||
|
||||
def splitCamelCase(text):
|
||||
return re.sub('([A-Z][a-z]+)', r' \1', re.sub('([A-Z]+)', r' \1', text)).split()
|
||||
|
||||
|
||||
def convertToCamelCase(text, capitalize = False):
|
||||
s = convertToAlphaNumeric(text)
|
||||
s = s.replace("-", " ").replace("_", " ")
|
||||
words = s.split()
|
||||
#print('--> words', words)
|
||||
finalWords = []
|
||||
|
||||
for i in range(len(words)):
|
||||
camelCaseSplit = splitCamelCase(words[i])
|
||||
if len(camelCaseSplit) == 0:
|
||||
finalWords.append(words[i])
|
||||
else:
|
||||
#print('--> camel split words', camelCaseSplit)
|
||||
for j in range(len(camelCaseSplit)):
|
||||
finalWords.append(camelCaseSplit[j])
|
||||
|
||||
if len(finalWords) == 0:
|
||||
return text
|
||||
|
||||
finalText = ''
|
||||
if capitalize:
|
||||
finalText = finalWords[0].capitalize() + ''.join(i.capitalize() for i in finalWords[1:])
|
||||
else:
|
||||
finalText = finalWords[0].lower() + ''.join(i.capitalize() for i in finalWords[1:])
|
||||
#print('Convert camel case:', text, '-->', finalText)
|
||||
return finalText
|
||||
|
||||
|
||||
def loadJsonFile(filePath):
|
||||
print('--> Loading JSON file', filePath)
|
||||
jsonFile = open(filePath, 'r')
|
||||
return json.load(jsonFile)
|
||||
|
||||
|
||||
def writeLine(fileDescriptor, line = ''):
|
||||
fileDescriptor.write(line + '\n')
|
||||
|
||||
|
||||
def writeLicenseHeader(fileDescriptor):
|
||||
writeLine(fileDescriptor, '/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *')
|
||||
writeLine(fileDescriptor, '*')
|
||||
writeLine(fileDescriptor, '* Copyright 2013 - %s, nymea GmbH' % datetime.datetime.now().year)
|
||||
writeLine(fileDescriptor, '* Contact: contact@nymea.io')
|
||||
writeLine(fileDescriptor, '*')
|
||||
writeLine(fileDescriptor, '* This fileDescriptor is part of nymea.')
|
||||
writeLine(fileDescriptor, '* This project including source code and documentation is protected by')
|
||||
writeLine(fileDescriptor, '* copyright law, and remains the property of nymea GmbH. All rights, including')
|
||||
writeLine(fileDescriptor, '* reproduction, publication, editing and translation, are reserved. The use of')
|
||||
writeLine(fileDescriptor, '* this project is subject to the terms of a license agreement to be concluded')
|
||||
writeLine(fileDescriptor, '* with nymea GmbH in accordance with the terms of use of nymea GmbH, available')
|
||||
writeLine(fileDescriptor, '* under https://nymea.io/license')
|
||||
writeLine(fileDescriptor, '*')
|
||||
writeLine(fileDescriptor, '* GNU Lesser General Public License Usage')
|
||||
writeLine(fileDescriptor, '* Alternatively, this project may be redistributed and/or modified under the')
|
||||
writeLine(fileDescriptor, '* terms of the GNU Lesser General Public License as published by the Free')
|
||||
writeLine(fileDescriptor, '* Software Foundation; version 3. This project is distributed in the hope that')
|
||||
writeLine(fileDescriptor, '* it will be useful, but WITHOUT ANY WARRANTY; without even the implied')
|
||||
writeLine(fileDescriptor, '* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU')
|
||||
writeLine(fileDescriptor, '* Lesser General Public License for more details.')
|
||||
writeLine(fileDescriptor, '*')
|
||||
writeLine(fileDescriptor, '* You should have received a copy of the GNU Lesser General Public License')
|
||||
writeLine(fileDescriptor, '* along with this project. If not, see <https://www.gnu.org/licenses/>.')
|
||||
writeLine(fileDescriptor, '*')
|
||||
writeLine(fileDescriptor, '* For any further details and any questions please contact us under')
|
||||
writeLine(fileDescriptor, '* contact@nymea.io or see our FAQ/Licensing Information on')
|
||||
writeLine(fileDescriptor, '* https://nymea.io/license/faq')
|
||||
writeLine(fileDescriptor, '*')
|
||||
writeLine(fileDescriptor, '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */')
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
def writeEnumDefinition(fileDescriptor, enumDefinition):
|
||||
print('Writing enum', enumDefinition)
|
||||
enumName = enumDefinition['name']
|
||||
enumValues = enumDefinition['values']
|
||||
writeLine(fileDescriptor, ' enum %s {' % enumName)
|
||||
for i in range(len(enumValues)):
|
||||
enumData = enumValues[i]
|
||||
line = (' %s%s = %s' % (enumName, enumData['key'], enumData['value']))
|
||||
if i < (len(enumValues) - 1):
|
||||
line += ','
|
||||
|
||||
writeLine(fileDescriptor, line)
|
||||
|
||||
writeLine(fileDescriptor, ' };')
|
||||
writeLine(fileDescriptor, ' Q_ENUM(%s)' % enumName)
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
def getCppDataType(registerDefinition, rawType = False):
|
||||
if not rawType:
|
||||
if 'enum' in registerDefinition:
|
||||
return registerDefinition['enum']
|
||||
|
||||
if 'scaleFactor' in registerDefinition or 'staticScaleFactor' in registerDefinition:
|
||||
return 'float'
|
||||
|
||||
if registerDefinition['type'] == 'uint16':
|
||||
return 'quint16'
|
||||
|
||||
if registerDefinition['type'] == 'int16':
|
||||
return 'qint16'
|
||||
|
||||
if registerDefinition['type'] == 'uint32':
|
||||
return 'quint32'
|
||||
|
||||
if registerDefinition['type'] == 'int32':
|
||||
return 'qint32'
|
||||
|
||||
if registerDefinition['type'] == 'uint64':
|
||||
return 'quint64'
|
||||
|
||||
if registerDefinition['type'] == 'int64':
|
||||
return 'qint64'
|
||||
|
||||
if registerDefinition['type'] == 'float':
|
||||
return 'float'
|
||||
|
||||
if registerDefinition['type'] == 'float64':
|
||||
return 'double'
|
||||
|
||||
if registerDefinition['type'] == 'string':
|
||||
return 'QString'
|
||||
|
||||
|
||||
def getConversionToValueMethod(registerDefinition):
|
||||
# Handle enums
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition, True)
|
||||
|
||||
if 'enum' in registerDefinition:
|
||||
enumName = registerDefinition['enum']
|
||||
if registerDefinition['type'] == 'uint16':
|
||||
return ('ModbusDataUtils::convertFromUInt16(static_cast<%s>(%s))' % (propertyTyp, propertyName))
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('ModbusDataUtils::convertFromInt16(static_cast<%s>(%s))' % (propertyTyp, propertyName))
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('ModbusDataUtils::convertFromUInt32(static_cast<%s>(%s), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, endianness))
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, endianness))
|
||||
|
||||
# Handle scale factors
|
||||
if 'scaleFactor' in registerDefinition:
|
||||
scaleFactorProperty = 'm_%s' % registerDefinition['scaleFactor']
|
||||
if registerDefinition['type'] == 'uint16':
|
||||
return ('ModbusDataUtils::convertFromUInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactorProperty))
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('ModbusDataUtils::convertFromInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactorProperty))
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('ModbusDataUtils::convertFromUInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactorProperty, endianness))
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactorProperty, endianness))
|
||||
|
||||
elif 'staticScaleFactor' in registerDefinition:
|
||||
scaleFactor = registerDefinition['staticScaleFactor']
|
||||
if registerDefinition['type'] == 'uint16':
|
||||
return ('ModbusDataUtils::convertFromUInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactor))
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('ModbusDataUtils::convertFromInt16(static_cast<%s>(%s * 1.0 / pow(10, %s)))' % (propertyTyp, propertyName, scaleFactor))
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('ModbusDataUtils::convertFromUInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactor, endianness))
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('ModbusDataUtils::convertFromInt32(static_cast<%s>(%s * 1.0 / pow(10, %s)), ModbusDataUtils::ByteOrder%s)' % (propertyTyp, propertyName, scaleFactor, endianness))
|
||||
|
||||
# Handle default types
|
||||
elif registerDefinition['type'] == 'uint16':
|
||||
return ('ModbusDataUtils::convertFromUInt16(%s)' % propertyName)
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('ModbusDataUtils::convertFromInt16(%s)' % propertyName)
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('ModbusDataUtils::convertFromUInt32(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('ModbusDataUtils::convertFromInt32(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
|
||||
elif registerDefinition['type'] == 'uint64':
|
||||
return ('ModbusDataUtils::convertFromUInt64(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
|
||||
elif registerDefinition['type'] == 'int64':
|
||||
return ('ModbusDataUtils::convertFromInt64(%s, ModbusDataUtils::ByteOrder%s)' % (propertyName, endianness))
|
||||
elif registerDefinition['type'] == 'float':
|
||||
return ('ModbusDataUtils::convertFromFloat32(%s, ModbusDataUtils::ByteOrder%s)' % propertyName, endianness)
|
||||
elif registerDefinition['type'] == 'float64':
|
||||
return ('ModbusDataUtils::convertFromFloat64(%s, ModbusDataUtils::ByteOrder%s)' % propertyName, endianness)
|
||||
elif registerDefinition['type'] == 'string':
|
||||
return ('ModbusDataUtils::convertFromString(%s)' % propertyName)
|
||||
|
||||
|
||||
def getValueConversionMethod(registerDefinition):
|
||||
# Handle enums
|
||||
if 'enum' in registerDefinition:
|
||||
enumName = registerDefinition['enum']
|
||||
if registerDefinition['type'] == 'uint16':
|
||||
return ('static_cast<%s>(ModbusDataUtils::convertToUInt16(unit.values()))' % (enumName))
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('static_cast<%s>(ModbusDataUtils::convertToInt16(unit.values()))' % (enumName))
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('static_cast<%s>(ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('static_cast<%s>(ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s))' % (enumName, endianness))
|
||||
|
||||
# Handle scale factors
|
||||
if 'scaleFactor' in registerDefinition:
|
||||
scaleFactorProperty = 'm_%s' % registerDefinition['scaleFactor']
|
||||
if registerDefinition['type'] == 'uint16':
|
||||
return ('ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('ModbusDataUtils::convertToInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactorProperty))
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactorProperty))
|
||||
|
||||
elif 'staticScaleFactor' in registerDefinition:
|
||||
scaleFactor = registerDefinition['staticScaleFactor']
|
||||
if registerDefinition['type'] == 'uint16':
|
||||
return ('ModbusDataUtils::convertToUInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactor))
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('ModbusDataUtils::convertToInt16(unit.values()) * 1.0 * pow(10, %s)' % (scaleFactor))
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s) * 1.0 * pow(10, %s)' % (endianness, scaleFactor))
|
||||
|
||||
# Handle default types
|
||||
elif registerDefinition['type'] == 'uint16':
|
||||
return ('ModbusDataUtils::convertToUInt16(unit.values())')
|
||||
elif registerDefinition['type'] == 'int16':
|
||||
return ('ModbusDataUtils::convertToInt16(unit.values())')
|
||||
elif registerDefinition['type'] == 'uint32':
|
||||
return ('ModbusDataUtils::convertToUInt32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
|
||||
elif registerDefinition['type'] == 'int32':
|
||||
return ('ModbusDataUtils::convertToInt32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
|
||||
elif registerDefinition['type'] == 'uint64':
|
||||
return ('ModbusDataUtils::convertToUInt64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
|
||||
elif registerDefinition['type'] == 'int64':
|
||||
return ('ModbusDataUtils::convertToInt64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
|
||||
elif registerDefinition['type'] == 'float':
|
||||
return ('ModbusDataUtils::convertToFloat32(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
|
||||
elif registerDefinition['type'] == 'float64':
|
||||
return ('ModbusDataUtils::convertToFloat64(unit.values(), ModbusDataUtils::ByteOrder%s)' % endianness)
|
||||
elif registerDefinition['type'] == 'string':
|
||||
return ('ModbusDataUtils::convertToString(unit.values())')
|
||||
|
||||
|
||||
def writePropertyGetSetMethodDeclarations(fileDescriptor, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
if 'unit' in registerDefinition and registerDefinition['unit'] != '':
|
||||
writeLine(fileDescriptor, ' /* %s [%s] - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size']))
|
||||
else:
|
||||
writeLine(fileDescriptor, ' /* %s - Address: %s, Size: %s */' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
|
||||
|
||||
writeLine(fileDescriptor, ' %s %s() const;' % (propertyTyp, propertyName))
|
||||
|
||||
# Check if we require a set method
|
||||
if registerDefinition['access'] == 'RW' or registerDefinition['access'] == 'WO':
|
||||
writeLine(fileDescriptor, ' QModbusReply *set%s(%s %s);' % (propertyName[0].upper() + propertyName[1:], propertyTyp, propertyName))
|
||||
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
def writePropertyGetSetMethodImplementations(fileDescriptor, className, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
# Get
|
||||
if 'enum' in registerDefinition:
|
||||
writeLine(fileDescriptor, '%s::%s %s::%s() const' % (className, propertyTyp, className, propertyName))
|
||||
else:
|
||||
writeLine(fileDescriptor, '%s %s::%s() const' % (propertyTyp, className, propertyName))
|
||||
|
||||
writeLine(fileDescriptor, '{')
|
||||
writeLine(fileDescriptor, ' return m_%s;' % propertyName)
|
||||
writeLine(fileDescriptor, '}')
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
# Check if we require a set method
|
||||
if registerDefinition['access'] == 'RW' or registerDefinition['access'] == 'WO':
|
||||
writeLine(fileDescriptor, 'QModbusReply *%s::set%s(%s %s)' % (className, propertyName[0].upper() + propertyName[1:], propertyTyp, propertyName))
|
||||
writeLine(fileDescriptor, '{')
|
||||
|
||||
writeLine(fileDescriptor, ' QVector<quint16> values = %s;' % getConversionToValueMethod(registerDefinition))
|
||||
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Write \\"%s\\" register:" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
|
||||
if registerDefinition['registerType'] == 'holdingRegister':
|
||||
writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, values.count());' % (registerDefinition['address']))
|
||||
|
||||
# TODO: other write methods
|
||||
|
||||
writeLine(fileDescriptor, ' request.setValues(values);')
|
||||
writeLine(fileDescriptor, ' return sendWriteRequest(request, m_slaveId);')
|
||||
writeLine(fileDescriptor, '}')
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
|
||||
def writePropertyUpdateMethodDeclarations(fileDescriptor, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
|
||||
continue
|
||||
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
writeLine(fileDescriptor, ' void update%s();' % (propertyName[0].upper() + propertyName[1:]))
|
||||
|
||||
|
||||
def writePropertyUpdateMethodImplementations(fileDescriptor, className, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
|
||||
continue
|
||||
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
writeLine(fileDescriptor, 'void %s::update%s()' % (className, propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, '{')
|
||||
writeLine(fileDescriptor, ' // Update registers from %s' % registerDefinition['description'])
|
||||
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read \\"%s\\" register:" << %s << "size:" << %s;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
|
||||
writeLine(fileDescriptor, ' QModbusReply *reply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, ' if (reply) {')
|
||||
writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
|
||||
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);')
|
||||
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){')
|
||||
writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {')
|
||||
writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();')
|
||||
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size']))
|
||||
|
||||
# FIXME: introduce bool and check register type for parsing
|
||||
writeLine(fileDescriptor, ' %s received%s = %s;' % (propertyTyp, propertyName[0].upper() + propertyName[1:], getValueConversionMethod(registerDefinition)))
|
||||
writeLine(fileDescriptor, ' if (m_%s != received%s) {' % (propertyName, propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, ' m_%s = received%s;' % (propertyName, propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, ' emit %sChanged(m_%s);' % (propertyName, propertyName))
|
||||
writeLine(fileDescriptor, ' }')
|
||||
writeLine(fileDescriptor, ' }')
|
||||
writeLine(fileDescriptor, ' });')
|
||||
writeLine(fileDescriptor)
|
||||
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){')
|
||||
writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description']))
|
||||
writeLine(fileDescriptor, ' emit reply->finished(); // To make sure it will be deleted')
|
||||
writeLine(fileDescriptor, ' });')
|
||||
writeLine(fileDescriptor, ' } else {')
|
||||
writeLine(fileDescriptor, ' delete reply; // Broadcast reply returns immediatly')
|
||||
writeLine(fileDescriptor, ' }')
|
||||
writeLine(fileDescriptor, ' } else {')
|
||||
writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << errorString();' % (className, registerDefinition['description']))
|
||||
writeLine(fileDescriptor, ' }')
|
||||
writeLine(fileDescriptor, '}')
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
def writeInternalPropertyReadMethodDeclarations(fileDescriptor, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
writeLine(fileDescriptor, ' QModbusReply *read%s();' % (propertyName[0].upper() + propertyName[1:]))
|
||||
|
||||
|
||||
def writeInternalPropertyReadMethodImplementations(fileDescriptor, className, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
writeLine(fileDescriptor, 'QModbusReply *%s::read%s()' % (className, propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, '{')
|
||||
|
||||
# Build request depending on the register type
|
||||
if registerDefinition['registerType'] == 'inputRegister':
|
||||
writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
|
||||
elif registerDefinition['registerType'] == 'discreteInputs':
|
||||
writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::DiscreteInputs, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
|
||||
elif registerDefinition['registerType'] == 'coils':
|
||||
writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
|
||||
else:
|
||||
#Default to holdingRegister
|
||||
writeLine(fileDescriptor, ' QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, %s, %s);' % (registerDefinition['address'], registerDefinition['size']))
|
||||
|
||||
writeLine(fileDescriptor, ' return sendReadRequest(request, m_slaveId);')
|
||||
writeLine(fileDescriptor, '}')
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
def writePropertyChangedSignals(fileDescriptor, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
if propertyTyp == 'QString':
|
||||
writeLine(fileDescriptor, ' void %sChanged(const %s &%s);' % (propertyName, propertyTyp, propertyName))
|
||||
else:
|
||||
writeLine(fileDescriptor, ' void %sChanged(%s %s);' % (propertyName, propertyTyp, propertyName))
|
||||
|
||||
|
||||
def writePrivatePropertyMembers(fileDescriptor, registerDefinitions):
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
if 'defaultValue' in registerDefinition:
|
||||
writeLine(fileDescriptor, ' %s m_%s = %s;' % (propertyTyp, propertyName, registerDefinition['defaultValue']))
|
||||
else:
|
||||
writeLine(fileDescriptor, ' %s m_%s;' % (propertyTyp, propertyName))
|
||||
|
||||
|
||||
def writeInitializeMethod(fileDescriptor, className, registerDefinitions):
|
||||
writeLine(fileDescriptor, 'void %s::initialize()' % (className))
|
||||
writeLine(fileDescriptor, '{')
|
||||
|
||||
# First check if there are any init registers
|
||||
initRequired = False
|
||||
for registerDefinition in registerDefinitions:
|
||||
if registerDefinition['readSchedule'] == 'init':
|
||||
initRequired = True
|
||||
break
|
||||
|
||||
if initRequired:
|
||||
writeLine(fileDescriptor, ' QModbusReply *reply = nullptr;')
|
||||
writeLine(fileDescriptor)
|
||||
writeLine(fileDescriptor, ' if (!m_pendingInitReplies.isEmpty()) {')
|
||||
writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to initialize but there are still some init replies pending.";' % className)
|
||||
writeLine(fileDescriptor, ' return;')
|
||||
writeLine(fileDescriptor, ' }')
|
||||
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
|
||||
if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init':
|
||||
writeLine(fileDescriptor)
|
||||
writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description'])
|
||||
writeLine(fileDescriptor, ' reply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, ' if (reply) {')
|
||||
writeLine(fileDescriptor, ' if (!reply->isFinished()) {')
|
||||
writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);')
|
||||
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);')
|
||||
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){')
|
||||
writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {')
|
||||
writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();')
|
||||
writeLine(fileDescriptor, ' %s received%s = %s;' % (propertyTyp, propertyName[0].upper() + propertyName[1:], getValueConversionMethod(registerDefinition)))
|
||||
writeLine(fileDescriptor, ' if (m_%s != received%s) {' % (propertyName, propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, ' m_%s = received%s;' % (propertyName, propertyName[0].upper() + propertyName[1:]))
|
||||
writeLine(fileDescriptor, ' emit %sChanged(m_%s);' % (propertyName, propertyName))
|
||||
writeLine(fileDescriptor, ' }')
|
||||
writeLine(fileDescriptor, ' }')
|
||||
writeLine(fileDescriptor)
|
||||
writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);')
|
||||
writeLine(fileDescriptor, ' verifyInitFinished();')
|
||||
writeLine(fileDescriptor, ' });')
|
||||
writeLine(fileDescriptor)
|
||||
writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){')
|
||||
writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description']))
|
||||
writeLine(fileDescriptor, ' emit reply->finished(); // To make sure it will be deleted')
|
||||
writeLine(fileDescriptor, ' });')
|
||||
writeLine(fileDescriptor, ' } else {')
|
||||
writeLine(fileDescriptor, ' delete reply; // Broadcast reply returns immediatly')
|
||||
writeLine(fileDescriptor, ' }')
|
||||
writeLine(fileDescriptor, ' } else {')
|
||||
writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << errorString();' % (className, registerDefinition['description']))
|
||||
writeLine(fileDescriptor, ' }')
|
||||
|
||||
|
||||
else:
|
||||
writeLine(fileDescriptor, ' // No init registers defined. Nothing to be done and we are finished.')
|
||||
writeLine(fileDescriptor, ' emit initializationFinished();')
|
||||
|
||||
writeLine(fileDescriptor, '}')
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
def writeUpdateMethod(fileDescriptor, className, registerDefinitions):
|
||||
writeLine(fileDescriptor, 'void %s::update()' % (className))
|
||||
writeLine(fileDescriptor, '{')
|
||||
for registerDefinition in registerDefinitions:
|
||||
propertyName = registerDefinition['id']
|
||||
if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update':
|
||||
writeLine(fileDescriptor, ' update%s();' % (propertyName[0].upper() + propertyName[1:]))
|
||||
|
||||
writeLine(fileDescriptor, '}')
|
||||
writeLine(fileDescriptor)
|
||||
|
||||
|
||||
############################################################################################
|
||||
# Main
|
||||
############################################################################################
|
||||
|
||||
parser = argparse.ArgumentParser(description='Generate modbus tcp connection class from JSON register definitions file.')
|
||||
parser.add_argument('-j', '--json', metavar='<file>', help='The JSON file containing the register definitions.')
|
||||
parser.add_argument('-o', '--output-directory', metavar='<directory>', help='The output directory for the resulting class.')
|
||||
parser.add_argument('-c', '--class-name', metavar='<name>', help='The name of the resulting class.')
|
||||
args = parser.parse_args()
|
||||
|
||||
registerJson = loadJsonFile(args.json)
|
||||
scriptPath = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
outputDirectory = os.path.realpath(args.output_directory)
|
||||
className = args.class_name
|
||||
|
||||
headerFileName = className.lower() + '.h'
|
||||
sourceFileName = className.lower() + '.cpp'
|
||||
|
||||
headerFilePath = os.path.join(outputDirectory, headerFileName)
|
||||
sourceFilePath = os.path.join(outputDirectory, sourceFileName)
|
||||
|
||||
print('Scrip path: %s' % scriptPath)
|
||||
print('Output directory: %s' % outputDirectory)
|
||||
print('Class name: %s' % className)
|
||||
print('Header file: %s' % headerFileName)
|
||||
print('Source file: %s' % sourceFileName)
|
||||
print('Header file path: %s' % headerFilePath)
|
||||
print('Source file path: %s' % sourceFilePath)
|
||||
|
||||
endianness = 'BigEndian'
|
||||
if 'endianness' in registerJson:
|
||||
endianness = registerJson['endianness']
|
||||
|
||||
|
||||
#############################################################################
|
||||
# Write header file
|
||||
#############################################################################
|
||||
|
||||
headerFile = open(headerFilePath, 'w')
|
||||
|
||||
writeLicenseHeader(headerFile)
|
||||
writeLine(headerFile, '#ifndef %s_H' % className.upper())
|
||||
writeLine(headerFile, '#define %s_H' % className.upper())
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, '#include <QObject>')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, '#include "../modbus/modbusdatautils.h"')
|
||||
writeLine(headerFile, '#include "../modbus/modbustcpmaster.h"')
|
||||
|
||||
writeLine(headerFile)
|
||||
|
||||
# Begin of class
|
||||
writeLine(headerFile, 'class %s : public ModbusTCPMaster' % className)
|
||||
writeLine(headerFile, '{')
|
||||
writeLine(headerFile, ' Q_OBJECT')
|
||||
|
||||
# Public members
|
||||
writeLine(headerFile, 'public:')
|
||||
|
||||
# Enum declarations
|
||||
for enumDefinition in registerJson['enums']:
|
||||
writeEnumDefinition(headerFile, enumDefinition)
|
||||
|
||||
# Constructor
|
||||
writeLine(headerFile, ' explicit %s(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr);' % className)
|
||||
writeLine(headerFile, ' ~%s() = default;' % className)
|
||||
writeLine(headerFile)
|
||||
|
||||
# Write registers get method declarations
|
||||
writePropertyGetSetMethodDeclarations(headerFile, registerJson['registers'])
|
||||
|
||||
# Write init and update method declarations
|
||||
writeLine(headerFile, ' virtual void initialize();')
|
||||
writeLine(headerFile, ' virtual void update();')
|
||||
writeLine(headerFile)
|
||||
|
||||
writePropertyUpdateMethodDeclarations(headerFile, registerJson['registers'])
|
||||
writeLine(headerFile)
|
||||
|
||||
# Write registers value changed signals
|
||||
writeLine(headerFile, 'signals:')
|
||||
writeLine(headerFile, ' void initializationFinished();')
|
||||
writeLine(headerFile)
|
||||
writePropertyChangedSignals(headerFile, registerJson['registers'])
|
||||
writeLine(headerFile)
|
||||
|
||||
# Private members
|
||||
writeLine(headerFile, 'private:')
|
||||
writeLine(headerFile, ' quint16 m_slaveId = 1;')
|
||||
writeLine(headerFile, ' QVector<QModbusReply *> m_pendingInitReplies;')
|
||||
writeLine(headerFile)
|
||||
writePrivatePropertyMembers(headerFile, registerJson['registers'])
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, ' void verifyInitFinished();')
|
||||
writeLine(headerFile)
|
||||
writeInternalPropertyReadMethodDeclarations(headerFile, registerJson['registers'])
|
||||
writeLine(headerFile)
|
||||
|
||||
# End of class
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, '};')
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, 'QDebug operator<<(QDebug debug, %s *%s);' % (className, className[0].lower() + className[1:]))
|
||||
writeLine(headerFile)
|
||||
writeLine(headerFile, '#endif // %s_H' % className.upper())
|
||||
|
||||
headerFile.close()
|
||||
|
||||
|
||||
|
||||
#############################################################################
|
||||
# Write source file
|
||||
#############################################################################
|
||||
|
||||
sourceFile = open(sourceFilePath, 'w')
|
||||
writeLicenseHeader(sourceFile)
|
||||
writeLine(sourceFile)
|
||||
writeLine(sourceFile, '#include "%s"' % headerFileName)
|
||||
writeLine(sourceFile, '#include "loggingcategories.h"')
|
||||
writeLine(sourceFile)
|
||||
writeLine(sourceFile, 'NYMEA_LOGGING_CATEGORY(dc%s, "%s")' % (className, className))
|
||||
writeLine(sourceFile)
|
||||
|
||||
# Constructor
|
||||
writeLine(sourceFile, '%s::%s(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :' % (className, className))
|
||||
writeLine(sourceFile, ' ModbusTCPMaster(hostAddress, port, parent),')
|
||||
writeLine(sourceFile, ' m_slaveId(slaveId)')
|
||||
writeLine(sourceFile, '{')
|
||||
writeLine(sourceFile, ' ')
|
||||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
# Property get methods
|
||||
writePropertyGetSetMethodImplementations(sourceFile, className, registerJson['registers'])
|
||||
|
||||
# Write init and update method implementation
|
||||
writeInitializeMethod(sourceFile, className, registerJson['registers'])
|
||||
writeUpdateMethod(sourceFile, className, registerJson['registers'])
|
||||
|
||||
# Write update methods
|
||||
writePropertyUpdateMethodImplementations(sourceFile, className, registerJson['registers'])
|
||||
|
||||
# Write property read method implementations
|
||||
writeInternalPropertyReadMethodImplementations(sourceFile, className, registerJson['registers'])
|
||||
|
||||
writeLine(sourceFile, 'void %s::verifyInitFinished()' % (className))
|
||||
writeLine(sourceFile, '{')
|
||||
writeLine(sourceFile, ' if (m_pendingInitReplies.isEmpty()) {')
|
||||
writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s" << hostAddress().toString();' % (className, className))
|
||||
writeLine(sourceFile, ' emit initializationFinished();')
|
||||
writeLine(sourceFile, ' }')
|
||||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
# Write the debug print
|
||||
debugObjectParamName = className[0].lower() + className[1:]
|
||||
writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName))
|
||||
writeLine(sourceFile, '{')
|
||||
writeLine(sourceFile, ' debug.nospace().noquote() << "%s(" << %s->hostAddress().toString() << ":" << %s->port() << ")" << "\\n";' % (className, debugObjectParamName, debugObjectParamName))
|
||||
for registerDefinition in registerJson['registers']:
|
||||
propertyName = registerDefinition['id']
|
||||
propertyTyp = getCppDataType(registerDefinition)
|
||||
line = ('" - %s:" << %s->%s()' % (registerDefinition['description'], debugObjectParamName, propertyName))
|
||||
if 'unit' in registerDefinition and registerDefinition['unit'] != '':
|
||||
line += (' << " [%s]"' % registerDefinition['unit'])
|
||||
writeLine(sourceFile, ' debug.nospace().noquote() << %s << "\\n";' % (line))
|
||||
|
||||
writeLine(sourceFile, ' return debug.quote().space();')
|
||||
writeLine(sourceFile, '}')
|
||||
writeLine(sourceFile)
|
||||
|
||||
sourceFile.close()
|
||||
|
|
@ -5,6 +5,7 @@ CONFIG += ordered
|
|||
SUBDIRS += libnymea-sunspec
|
||||
|
||||
PLUGIN_DIRS = \
|
||||
alphainnotec \
|
||||
drexelundweiss \
|
||||
energymeters \
|
||||
modbuscommander \
|
||||
|
|
|
|||
Loading…
Reference in New Issue