]> git.basschouten.com Git - openhab-addons.git/blob
e352cbbcf37a5706eddb79147af2fc8721689781
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.modbus.sunspec.internal.handler;
14
15 import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.*;
16 import static org.openhab.core.library.unit.SIUnits.CELSIUS;
17 import static org.openhab.core.library.unit.Units.*;
18
19 import java.util.Optional;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.modbus.sunspec.internal.InverterStatus;
23 import org.openhab.binding.modbus.sunspec.internal.dto.InverterModelBlock;
24 import org.openhab.binding.modbus.sunspec.internal.parser.InverterModelParser;
25 import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.thing.Thing;
28 import org.openhab.core.types.UnDefType;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * The {@link InverterHandler} is responsible for handling commands, which are
34  * sent to an inverter and publishing the received values to OpenHAB.
35  *
36  * @author Nagy Attila Gabor - Initial contribution
37  */
38 @NonNullByDefault
39 public class InverterHandler extends AbstractSunSpecHandler {
40
41     /**
42      * Parser used to convert incoming raw messages into model blocks
43      */
44     private final InverterModelParser parser = new InverterModelParser();
45
46     /**
47      * Logger instance
48      */
49     private final Logger logger = LoggerFactory.getLogger(InverterHandler.class);
50
51     public InverterHandler(Thing thing) {
52         super(thing);
53     }
54
55     /**
56      * This method is called each time new data has been polled from the modbus slave
57      * The register array is first parsed, then each of the channels are updated
58      * to the new values
59      *
60      * @param registers byte array read from the modbus slave
61      */
62     @Override
63     protected void handlePolledData(ModbusRegisterArray registers) {
64         logger.trace("Model block received, size: {}", registers.size());
65
66         InverterModelBlock block = parser.parse(registers);
67
68         // Device information group
69         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_CABINET_TEMPERATURE),
70                 getScaled(block.temperatureCabinet, block.temperatureSF, CELSIUS));
71
72         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_HEATSINK_TEMPERATURE),
73                 getScaled(block.temperatureHeatsink, Optional.of(block.temperatureSF), CELSIUS));
74
75         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_TRANSFORMER_TEMPERATURE),
76                 getScaled(block.temperatureTransformer, Optional.of(block.temperatureSF), CELSIUS));
77
78         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_OTHER_TEMPERATURE),
79                 getScaled(block.temperatureOther, Optional.of(block.temperatureSF), CELSIUS));
80
81         InverterStatus status = InverterStatus.getByCode(block.status);
82         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_STATUS),
83                 status == null ? UnDefType.UNDEF : new StringType(status.name()));
84
85         // AC General group
86         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_CURRENT),
87                 getScaled(block.acCurrentTotal, block.acCurrentSF, AMPERE));
88
89         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_POWER), getScaled(block.acPower, block.acPowerSF, WATT));
90
91         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_FREQUENCY),
92                 getScaled(block.acFrequency, block.acFrequencySF, HERTZ));
93
94         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_APPARENT_POWER),
95                 getScaled(block.acApparentPower, block.acApparentPowerSF, WATT)); // TODO: VA currently not supported,
96                                                                                   // see:
97                                                                                   // https://github.com/openhab/openhab-core/pull/1347
98
99         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_REACTIVE_POWER),
100                 getScaled(block.acReactivePower, block.acReactivePowerSF, WATT)); // TODO: var currently not supported,
101                                                                                   // see:
102                                                                                   // https://github.com/openhab/openhab-core/pull/1347
103
104         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_POWER_FACTOR),
105                 getScaled(block.acPowerFactor, block.acPowerFactorSF, PERCENT));
106
107         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_LIFETIME_ENERGY),
108                 getScaled(block.acEnergyLifetime, block.acEnergyLifetimeSF, WATT_HOUR));
109
110         // DC General group
111         updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_CURRENT),
112                 getScaled(block.dcCurrent, block.dcCurrentSF, AMPERE));
113         updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_VOLTAGE),
114                 getScaled(block.dcVoltage, block.dcVoltageSF, VOLT));
115         updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_POWER), getScaled(block.dcPower, block.dcPowerSF, WATT));
116
117         // AC Phase specific groups
118         // All types of inverters
119         updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_PHASE_CURRENT),
120                 getScaled(block.acCurrentPhaseA, block.acCurrentSF, AMPERE));
121         updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_VOLTAGE_TO_NEXT),
122                 getScaled(block.acVoltageAB, block.acVoltageSF, VOLT));
123         updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_VOLTAGE_TO_N),
124                 getScaled(block.acVoltageAtoN, block.acVoltageSF, VOLT));
125
126         // Split phase and three phase
127         if ((thing.getThingTypeUID().equals(THING_TYPE_INVERTER_SPLIT_PHASE)
128                 || thing.getThingTypeUID().equals(THING_TYPE_INVERTER_THREE_PHASE))
129                 && block.phaseConfiguration >= INVERTER_SPLIT_PHASE) {
130             updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_PHASE_CURRENT),
131                     getScaled(block.acCurrentPhaseB, block.acCurrentSF, AMPERE));
132             updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_VOLTAGE_TO_NEXT),
133                     getScaled(block.acVoltageBC, block.acVoltageSF, VOLT));
134             updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_VOLTAGE_TO_N),
135                     getScaled(block.acVoltageBtoN, block.acVoltageSF, VOLT));
136         }
137
138         // Three phase only
139         if (thing.getThingTypeUID().equals(THING_TYPE_INVERTER_THREE_PHASE)
140                 && block.phaseConfiguration >= INVERTER_THREE_PHASE) {
141             updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_PHASE_CURRENT),
142                     getScaled(block.acCurrentPhaseC, block.acCurrentSF, AMPERE));
143             updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_VOLTAGE_TO_NEXT),
144                     getScaled(block.acVoltageCA, block.acVoltageSF, VOLT));
145             updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_VOLTAGE_TO_N),
146                     getScaled(block.acVoltageCtoN, block.acVoltageSF, VOLT));
147         }
148
149         resetCommunicationError();
150     }
151 }