2 * Copyright (c) 2010-2023 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.anel.internal.state;
15 import java.util.Collections;
16 import java.util.HashMap;
18 import java.util.function.Function;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.anel.internal.IAnelConstants;
23 import org.openhab.core.library.types.DecimalType;
24 import org.openhab.core.library.types.OnOffType;
25 import org.openhab.core.library.types.QuantityType;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.library.unit.SIUnits;
28 import org.openhab.core.types.State;
29 import org.openhab.core.types.UnDefType;
32 * Get updates for {@link AnelState}s.
34 * @author Patrick Koenemann - Initial contribution
37 public class AnelStateUpdater {
39 public @Nullable State getChannelUpdate(String channelId, @Nullable AnelState state) {
44 final int index = IAnelConstants.getIndexFromChannel(channelId);
46 if (IAnelConstants.CHANNEL_RELAY_NAME.contains(channelId)) {
47 return getStringState(state.relayName[index]);
49 if (IAnelConstants.CHANNEL_RELAY_STATE.contains(channelId)) {
50 return getSwitchState(state.relayState[index]);
52 if (IAnelConstants.CHANNEL_RELAY_LOCKED.contains(channelId)) {
53 return getSwitchState(state.relayLocked[index]);
56 if (IAnelConstants.CHANNEL_IO_NAME.contains(channelId)) {
57 return getStringState(state.ioName[index]);
59 if (IAnelConstants.CHANNEL_IO_STATE.contains(channelId)) {
60 return getSwitchState(state.ioState[index]);
62 if (IAnelConstants.CHANNEL_IO_MODE.contains(channelId)) {
63 return getSwitchState(state.ioState[index]);
66 if (IAnelConstants.CHANNEL_NAME.equals(channelId)) {
67 return getStringState(state.name);
69 if (IAnelConstants.CHANNEL_TEMPERATURE.equals(channelId)) {
70 return getTemperatureState(state.temperature);
73 if (IAnelConstants.CHANNEL_SENSOR_TEMPERATURE.equals(channelId)) {
74 return getTemperatureState(state.sensorTemperature);
76 if (IAnelConstants.CHANNEL_SENSOR_HUMIDITY.equals(channelId)) {
77 return getDecimalState(state.sensorHumidity);
79 if (IAnelConstants.CHANNEL_SENSOR_BRIGHTNESS.equals(channelId)) {
80 return getDecimalState(state.sensorBrightness);
86 public Map<String, State> getChannelUpdates(@Nullable AnelState oldState, AnelState newState) {
87 if (oldState != null && newState.status.equals(oldState.status)) {
88 return Collections.emptyMap(); // definitely no change!
91 final Map<String, State> updates = new HashMap<>();
93 // name and device temperature
94 final State newName = getNewStringState(oldState == null ? null : oldState.name, newState.name);
95 if (newName != null) {
96 updates.put(IAnelConstants.CHANNEL_NAME, newName);
98 final State newTemperature = getNewTemperatureState(oldState == null ? null : oldState.temperature,
99 newState.temperature);
100 if (newTemperature != null) {
101 updates.put(IAnelConstants.CHANNEL_TEMPERATURE, newTemperature);
105 for (int i = 0; i < 8; i++) {
106 final State newRelayName = getNewStringState(oldState == null ? null : oldState.relayName[i],
107 newState.relayName[i]);
108 if (newRelayName != null) {
109 updates.put(IAnelConstants.CHANNEL_RELAY_NAME.get(i), newRelayName);
112 final State newRelayState = getNewSwitchState(oldState == null ? null : oldState.relayState[i],
113 newState.relayState[i]);
114 if (newRelayState != null) {
115 updates.put(IAnelConstants.CHANNEL_RELAY_STATE.get(i), newRelayState);
118 final State newRelayLocked = getNewSwitchState(oldState == null ? null : oldState.relayLocked[i],
119 newState.relayLocked[i]);
120 if (newRelayLocked != null) {
121 updates.put(IAnelConstants.CHANNEL_RELAY_LOCKED.get(i), newRelayLocked);
126 for (int i = 0; i < 8; i++) {
127 final State newIOName = getNewStringState(oldState == null ? null : oldState.ioName[i], newState.ioName[i]);
128 if (newIOName != null) {
129 updates.put(IAnelConstants.CHANNEL_IO_NAME.get(i), newIOName);
132 final State newIOIsInput = getNewSwitchState(oldState == null ? null : oldState.ioIsInput[i],
133 newState.ioIsInput[i]);
134 if (newIOIsInput != null) {
135 updates.put(IAnelConstants.CHANNEL_IO_MODE.get(i), newIOIsInput);
138 final State newIOState = getNewSwitchState(oldState == null ? null : oldState.ioState[i],
139 newState.ioState[i]);
140 if (newIOState != null) {
141 updates.put(IAnelConstants.CHANNEL_IO_STATE.get(i), newIOState);
146 final State newSensorTemperature = getNewTemperatureState(oldState == null ? null : oldState.sensorTemperature,
147 newState.sensorTemperature);
148 if (newSensorTemperature != null) {
149 updates.put(IAnelConstants.CHANNEL_SENSOR_TEMPERATURE, newSensorTemperature);
151 final State newSensorHumidity = getNewDecimalState(oldState == null ? null : oldState.sensorHumidity,
152 newState.sensorHumidity);
153 if (newSensorHumidity != null) {
154 updates.put(IAnelConstants.CHANNEL_SENSOR_HUMIDITY, newSensorHumidity);
156 final State newSensorBrightness = getNewDecimalState(oldState == null ? null : oldState.sensorBrightness,
157 newState.sensorBrightness);
158 if (newSensorBrightness != null) {
159 updates.put(IAnelConstants.CHANNEL_SENSOR_BRIGHTNESS, newSensorBrightness);
165 private @Nullable State getStringState(@Nullable String value) {
166 return value == null ? null : new StringType(value);
169 private @Nullable State getDecimalState(@Nullable String value) {
170 return value == null ? null : new DecimalType(value);
173 private @Nullable State getTemperatureState(@Nullable String value) {
174 if (value == null || value.trim().isEmpty()) {
177 final float floatValue = Float.parseFloat(value);
178 return QuantityType.valueOf(floatValue, SIUnits.CELSIUS);
181 private @Nullable State getSwitchState(@Nullable Boolean value) {
182 return value == null ? null : OnOffType.from(value.booleanValue());
185 private @Nullable State getNewStringState(@Nullable String oldValue, @Nullable String newValue) {
186 return getNewState(oldValue, newValue, StringType::new);
189 private @Nullable State getNewDecimalState(@Nullable String oldValue, @Nullable String newValue) {
190 return getNewState(oldValue, newValue, DecimalType::new);
193 private @Nullable State getNewTemperatureState(@Nullable String oldValue, @Nullable String newValue) {
194 return getNewState(oldValue, newValue, value -> QuantityType.valueOf(Float.parseFloat(value), SIUnits.CELSIUS));
197 private @Nullable State getNewSwitchState(@Nullable Boolean oldValue, @Nullable Boolean newValue) {
198 return getNewState(oldValue, newValue, value -> OnOffType.from(value.booleanValue()));
201 private <T> @Nullable State getNewState(@Nullable T oldValue, @Nullable T newValue,
202 Function<T, State> createState) {
203 if (oldValue == null) {
204 if (newValue == null) {
205 return null; // no change
207 return createState.apply(newValue); // from null to some value
209 } else if (newValue == null) {
210 return UnDefType.NULL; // from some value to null
211 } else if (oldValue.equals(newValue)) {
212 return null; // no change
214 return createState.apply(newValue); // from some value to another value