2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.modbus.sunspec.internal.handler;
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.*;
19 import java.util.Optional;
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;
35 * The {@link InverterHandler} is responsible for handling commands, which are
36 * sent to an inverter and publishing the received values to OpenHAB.
38 * @author Nagy Attila Gabor - Initial contribution
41 public class InverterHandler extends AbstractSunSpecHandler {
44 * Parser used to convert incoming raw messages into model blocks
46 private final InverterModelParser parser = new InverterModelParser();
51 private final Logger logger = LoggerFactory.getLogger(InverterHandler.class);
53 public InverterHandler(Thing thing) {
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
62 * @param registers byte array read from the modbus slave
65 protected void handlePolledData(ModbusRegisterArray registers) {
66 logger.trace("Model block received, size: {}", registers.size());
68 InverterModelBlock block = parser.parse(registers);
70 // Device information group
71 updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_CABINET_TEMPERATURE),
72 getScaled(block.temperatureCabinet, block.temperatureSF, CELSIUS));
74 updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_HEATSINK_TEMPERATURE),
75 getScaled(block.temperatureHeatsink, Optional.of(block.temperatureSF), CELSIUS));
77 updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_TRANSFORMER_TEMPERATURE),
78 getScaled(block.temperatureTransformer, Optional.of(block.temperatureSF), CELSIUS));
80 updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_OTHER_TEMPERATURE),
81 getScaled(block.temperatureOther, Optional.of(block.temperatureSF), CELSIUS));
83 InverterStatus status = InverterStatus.getByCode(block.status);
84 updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_STATUS),
85 status == null ? UnDefType.UNDEF : new StringType(status.name()));
87 updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_STATUS_VENDOR),
88 block.statusVendor.<State> map(DecimalType::new).orElse(UnDefType.UNDEF));
91 updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_CURRENT),
92 getScaled(block.acCurrentTotal, block.acCurrentSF, AMPERE));
94 updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_POWER), getScaled(block.acPower, block.acPowerSF, WATT));
96 updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_FREQUENCY),
97 getScaled(block.acFrequency, block.acFrequencySF, HERTZ));
99 updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_APPARENT_POWER),
100 getScaled(block.acApparentPower, block.acApparentPowerSF, VOLT_AMPERE));
102 updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_REACTIVE_POWER),
103 getScaled(block.acReactivePower, block.acReactivePowerSF, VAR));
105 updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_POWER_FACTOR),
106 getScaled(block.acPowerFactor, block.acPowerFactorSF, PERCENT));
108 updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_LIFETIME_ENERGY),
109 getScaled(block.acEnergyLifetime, block.acEnergyLifetimeSF, WATT_HOUR));
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));
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));
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));
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));
150 resetCommunicationError();