]> git.basschouten.com Git - openhab-addons.git/blob
0c61596a9ba31044b389dde18da76eaee3d62fbc
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.DecimalType;
27 import org.openhab.core.library.types.StringType;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.types.State;
30 import org.openhab.core.types.UnDefType;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 /**
35  * The {@link InverterHandler} is responsible for handling commands, which are
36  * sent to an inverter and publishing the received values to OpenHAB.
37  *
38  * @author Nagy Attila Gabor - Initial contribution
39  */
40 @NonNullByDefault
41 public class InverterHandler extends AbstractSunSpecHandler {
42
43     /**
44      * Parser used to convert incoming raw messages into model blocks
45      */
46     private final InverterModelParser parser = new InverterModelParser();
47
48     /**
49      * Logger instance
50      */
51     private final Logger logger = LoggerFactory.getLogger(InverterHandler.class);
52
53     public InverterHandler(Thing thing) {
54         super(thing);
55     }
56
57     /**
58      * This method is called each time new data has been polled from the modbus slave
59      * The register array is first parsed, then each of the channels are updated
60      * to the new values
61      *
62      * @param registers byte array read from the modbus slave
63      */
64     @Override
65     protected void handlePolledData(ModbusRegisterArray registers) {
66         logger.trace("Model block received, size: {}", registers.size());
67
68         InverterModelBlock block = parser.parse(registers);
69
70         // Device information group
71         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_CABINET_TEMPERATURE),
72                 getScaled(block.temperatureCabinet, block.temperatureSF, CELSIUS));
73
74         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_HEATSINK_TEMPERATURE),
75                 getScaled(block.temperatureHeatsink, Optional.of(block.temperatureSF), CELSIUS));
76
77         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_TRANSFORMER_TEMPERATURE),
78                 getScaled(block.temperatureTransformer, Optional.of(block.temperatureSF), CELSIUS));
79
80         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_OTHER_TEMPERATURE),
81                 getScaled(block.temperatureOther, Optional.of(block.temperatureSF), CELSIUS));
82
83         InverterStatus status = InverterStatus.getByCode(block.status);
84         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_STATUS),
85                 status == null ? UnDefType.UNDEF : new StringType(status.name()));
86
87         updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_STATUS_VENDOR),
88                 block.statusVendor.<State> map(DecimalType::new).orElse(UnDefType.UNDEF));
89
90         // AC General group
91         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_CURRENT),
92                 getScaled(block.acCurrentTotal, block.acCurrentSF, AMPERE));
93
94         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_POWER), getScaled(block.acPower, block.acPowerSF, WATT));
95
96         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_FREQUENCY),
97                 getScaled(block.acFrequency, block.acFrequencySF, HERTZ));
98
99         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_APPARENT_POWER),
100                 getScaled(block.acApparentPower, block.acApparentPowerSF, VOLT_AMPERE));
101
102         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_REACTIVE_POWER),
103                 getScaled(block.acReactivePower, block.acReactivePowerSF, VAR));
104
105         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_POWER_FACTOR),
106                 getScaled(block.acPowerFactor, block.acPowerFactorSF, PERCENT));
107
108         updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_LIFETIME_ENERGY),
109                 getScaled(block.acEnergyLifetime, block.acEnergyLifetimeSF, WATT_HOUR));
110
111         // DC General group
112         updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_CURRENT),
113                 getScaled(block.dcCurrent, block.dcCurrentSF, AMPERE));
114         updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_VOLTAGE),
115                 getScaled(block.dcVoltage, block.dcVoltageSF, VOLT));
116         updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_POWER), getScaled(block.dcPower, block.dcPowerSF, WATT));
117
118         // AC Phase specific groups
119         // All types of inverters
120         updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_PHASE_CURRENT),
121                 getScaled(block.acCurrentPhaseA, block.acCurrentSF, AMPERE));
122         updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_VOLTAGE_TO_NEXT),
123                 getScaled(block.acVoltageAB, block.acVoltageSF, VOLT));
124         updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_VOLTAGE_TO_N),
125                 getScaled(block.acVoltageAtoN, block.acVoltageSF, VOLT));
126
127         // Split phase and three phase
128         if ((thing.getThingTypeUID().equals(THING_TYPE_INVERTER_SPLIT_PHASE)
129                 || thing.getThingTypeUID().equals(THING_TYPE_INVERTER_THREE_PHASE))
130                 && block.phaseConfiguration >= INVERTER_SPLIT_PHASE) {
131             updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_PHASE_CURRENT),
132                     getScaled(block.acCurrentPhaseB, block.acCurrentSF, AMPERE));
133             updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_VOLTAGE_TO_NEXT),
134                     getScaled(block.acVoltageBC, block.acVoltageSF, VOLT));
135             updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_VOLTAGE_TO_N),
136                     getScaled(block.acVoltageBtoN, block.acVoltageSF, VOLT));
137         }
138
139         // Three phase only
140         if (thing.getThingTypeUID().equals(THING_TYPE_INVERTER_THREE_PHASE)
141                 && block.phaseConfiguration >= INVERTER_THREE_PHASE) {
142             updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_PHASE_CURRENT),
143                     getScaled(block.acCurrentPhaseC, block.acCurrentSF, AMPERE));
144             updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_VOLTAGE_TO_NEXT),
145                     getScaled(block.acVoltageCA, block.acVoltageSF, VOLT));
146             updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_VOLTAGE_TO_N),
147                     getScaled(block.acVoltageCtoN, block.acVoltageSF, VOLT));
148         }
149
150         resetCommunicationError();
151     }
152 }