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.wolfsmartset.internal.handler;
15 import static org.openhab.binding.wolfsmartset.internal.WolfSmartsetBindingConstants.*;
17 import java.time.Instant;
19 import java.util.concurrent.ConcurrentHashMap;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.wolfsmartset.internal.config.WolfSmartsetUnitConfiguration;
24 import org.openhab.binding.wolfsmartset.internal.dto.GetParameterValuesDTO;
25 import org.openhab.binding.wolfsmartset.internal.dto.MenuItemTabViewDTO;
26 import org.openhab.binding.wolfsmartset.internal.dto.ParameterDescriptorDTO;
27 import org.openhab.binding.wolfsmartset.internal.dto.SubMenuEntryDTO;
28 import org.openhab.core.thing.Channel;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingStatusDetail;
33 import org.openhab.core.thing.ThingStatusInfo;
34 import org.openhab.core.thing.binding.BaseThingHandler;
35 import org.openhab.core.thing.binding.builder.ChannelBuilder;
36 import org.openhab.core.thing.binding.builder.ThingBuilder;
37 import org.openhab.core.thing.type.ChannelTypeUID;
38 import org.openhab.core.types.Command;
39 import org.openhab.core.types.RefreshType;
40 import org.openhab.core.types.State;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 * The {@link WolfSmartsetUnitThingHandler} is responsible for updating the channels associated
46 * with a WolfSmartset unit.
48 * @author Bo Biene - Initial contribution
51 public class WolfSmartsetUnitThingHandler extends BaseThingHandler {
53 public static final String CAPABILITY_ADC = "adc";
54 public static final String CAPABILITY_CO2 = "co2";
55 public static final String CAPABILITY_DRY_CONTACT = "dryContact";
56 public static final String CAPABILITY_HUMIDITY = "humidity";
57 public static final String CAPABILITY_OCCUPANCY = "occupancy";
58 public static final String CAPABILITY_TEMPERATURE = "temperature";
59 public static final String CAPABILITY_UNKNOWN = "unknown";
61 private final Logger logger = LoggerFactory.getLogger(WolfSmartsetUnitThingHandler.class);
63 private @NonNullByDefault({}) String unitId;
64 private @Nullable Instant lastRefreshTime;
66 private Map<String, State> stateCache = new ConcurrentHashMap<>();
67 private Map<Long, ParameterDescriptorDTO> paramDescriptionMap = new ConcurrentHashMap<>();
68 private @Nullable SubMenuEntryDTO submenu;
69 private @Nullable MenuItemTabViewDTO tabmenu;
71 public WolfSmartsetUnitThingHandler(Thing thing) {
76 public void initialize() {
77 unitId = getConfigAs(WolfSmartsetUnitConfiguration.class).unitId;
78 logger.debug("UnitThing: Initializing unit '{}'", unitId);
80 var bridgeHandler = getBridge();
81 if (bridgeHandler != null) {
82 bridgeStatusChanged(bridgeHandler.getStatusInfo());
87 public void dispose() {
88 logger.debug("UnitThing: Disposing unit '{}'", unitId);
92 public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
93 if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
94 if (this.submenu != null && this.tabmenu != null) {
95 updateStatus(ThingStatus.ONLINE);
97 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING);
101 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
106 public void handleCommand(ChannelUID channelUID, Command command) {
107 if (command instanceof RefreshType) {
108 State state = stateCache.get(channelUID.getId());
110 updateState(channelUID.getId(), state);
116 * Get the {@link SubMenuEntryDTO} for this unit
118 * @return the {@link SubMenuEntryDTO} for this unit
120 public @Nullable SubMenuEntryDTO getSubMenu() {
125 * Get the {@link MenuItemTabViewDTO} for this unit
127 * @return the {@link MenuItemTabViewDTO} for this unit
129 public @Nullable MenuItemTabViewDTO getTabMenu() {
134 * Get the {@link Instant} of the last valid call of updateValues
136 * @return the getInstallationDate of the last valid call of updateValues
138 public @Nullable Instant getLastRefreshTime() {
139 return this.lastRefreshTime;
143 * Update the configuration of this unit and create / update the related channels
145 * @param submenu the {@link SubMenuEntryDTO} for this unit
146 * @param tabmenu the {@link MenuItemTabViewDTO} for this unit
148 public void updateConfiguration(SubMenuEntryDTO submenu, MenuItemTabViewDTO tabmenu) {
149 this.submenu = submenu;
150 this.tabmenu = tabmenu;
151 var bridgeHandler = getBridge();
152 if (bridgeHandler != null) {
153 bridgeStatusChanged(bridgeHandler.getStatusInfo());
155 lastRefreshTime = null;
157 ThingBuilder thingBuilder = editThing();
158 var thingId = thing.getUID();
160 paramDescriptionMap.clear();
161 for (var param : tabmenu.parameterDescriptors) {
162 paramDescriptionMap.put(param.valueId, param);
163 var channelId = new ChannelUID(thingId, param.parameterId.toString()); // "bindingId:type:thingId:1")
164 if (thing.getChannel(channelId) == null) {
165 logger.debug("UnitThing: Create channel '{}'", channelId);
166 Channel channel = ChannelBuilder.create(channelId, getItemType(param.controlType)).withLabel(param.name)
167 .withType(getChannelType(param)).build();
168 thingBuilder.withChannel(channel);
172 updateThing(thingBuilder.build());
174 for (var param : tabmenu.parameterDescriptors) {
175 var channelId = new ChannelUID(thingId, param.parameterId.toString());
176 setState(channelId, WolfSmartsetUtils.undefOrString(param.value));
181 * Update the values of the channels
183 * @param values {@link GetParameterValuesDTO} representing the new values
185 public void updateValues(@Nullable GetParameterValuesDTO values) {
186 var thingId = thing.getUID();
187 if (values != null && values.getValues() != null && !values.getValues().isEmpty()) {
188 if (!values.getIsNewJobCreated()) {
189 lastRefreshTime = Instant.now();
192 for (var value : values.getValues()) {
193 var param = paramDescriptionMap.get(value.getValueId());
195 var channelId = new ChannelUID(thingId, param.parameterId.toString());
196 setState(channelId, WolfSmartsetUtils.undefOrString(value.getValue()));
203 * Stores the state for the channel in stateCache and calls updateState of this Thing
205 * @param channelId {@link ChannelUID} the id of the channel to update
206 * @param state {@link State} the new state for the channel
208 private void setState(ChannelUID channelId, State state) {
209 stateCache.put(channelId.getId(), state);
210 updateState(channelId, state);
213 private ChannelTypeUID getChannelType(ParameterDescriptorDTO parmeter) {
214 if (parmeter.unit == null || parmeter.unit.isBlank()) {
215 if (parmeter.controlType == null) {
216 return new ChannelTypeUID(BINDING_ID, CH_STRING);
218 switch (parmeter.controlType) {
223 return new ChannelTypeUID(BINDING_ID, CH_NUMBER);
225 return new ChannelTypeUID(BINDING_ID, CH_CONTACT);
228 return new ChannelTypeUID(BINDING_ID, CH_DATETIME);
230 return new ChannelTypeUID(BINDING_ID, CH_STRING);
234 switch (parmeter.unit) {
236 return new ChannelTypeUID(BINDING_ID, CH_PRESSURE);
239 return new ChannelTypeUID(BINDING_ID, CH_NUMBER);
241 return new ChannelTypeUID(BINDING_ID, CH_TEMPERATURE);
243 return new ChannelTypeUID(BINDING_ID, CH_STRING);
248 private String getItemType(Integer controlType) {
249 switch (controlType) {
265 private void clearSavedState() {