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.echonetlite.internal;
15 import static java.util.Objects.requireNonNull;
16 import static org.openhab.binding.echonetlite.internal.EchonetLiteBindingConstants.PROPERTY_NAME_INSTANCE_KEY;
18 import java.net.InetSocketAddress;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.core.thing.Bridge;
27 import org.openhab.core.thing.Channel;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.binding.BaseThingHandler;
33 import org.openhab.core.thing.binding.builder.ChannelBuilder;
34 import org.openhab.core.thing.binding.builder.ThingBuilder;
35 import org.openhab.core.thing.type.ChannelTypeUID;
36 import org.openhab.core.types.Command;
37 import org.openhab.core.types.RefreshType;
38 import org.openhab.core.types.State;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * The {@link EchonetLiteHandler} is responsible for handling commands, which are
44 * sent to one of the channels.
46 * @author Michael Barker - Initial contribution
49 public class EchonetLiteHandler extends BaseThingHandler implements EchonetDeviceListener {
50 private final Logger logger = LoggerFactory.getLogger(EchonetLiteHandler.class);
52 private @Nullable InstanceKey instanceKey;
53 private final Map<String, State> stateByChannelId = new HashMap<>();
55 public EchonetLiteHandler(final Thing thing) {
60 private EchonetLiteBridgeHandler bridgeHandler() {
62 final Bridge bridge = getBridge();
68 final EchonetLiteBridgeHandler handler = (EchonetLiteBridgeHandler) bridge.getHandler();
73 public void handleCommand(ChannelUID channelUID, Command command) {
75 final EchonetLiteBridgeHandler handler = bridgeHandler();
76 if (null == handler) {
77 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
78 "@text/offline.conf-error.null-bridge-handler");
82 if (command instanceof RefreshType) {
83 logger.debug("Refreshing: {}", channelUID);
85 final State currentState = stateByChannelId.get(channelUID.getId());
86 if (null == currentState) {
87 handler.refreshDevice(requireNonNull(instanceKey), channelUID.getId());
89 updateState(channelUID, currentState);
91 } else if (command instanceof State stateCommand) {
92 logger.debug("Updating: {} to {}", channelUID, command);
94 handler.updateDevice(requireNonNull(instanceKey), channelUID.getId(), stateCommand);
99 public void initialize() {
100 final EchonetDeviceConfig config = getConfigAs(EchonetDeviceConfig.class);
102 logger.debug("Initialising: {}", config);
104 updateStatus(ThingStatus.UNKNOWN);
107 final EchonetLiteBridgeHandler bridgeHandler = bridgeHandler();
108 if (null == bridgeHandler) {
109 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
110 "@text/offline.conf-error.null-bridge-handler");
115 final InetSocketAddress address = new InetSocketAddress(requireNonNull(config.hostname), config.port);
116 final InstanceKey instanceKey = new InstanceKey(address,
117 EchonetClass.resolve(config.groupCode, config.classCode), config.instance);
118 this.instanceKey = instanceKey;
120 updateProperty(PROPERTY_NAME_INSTANCE_KEY, instanceKey.representationProperty());
121 bridgeHandler.newDevice(instanceKey, config.pollIntervalMs, config.retryTimeoutMs, this);
122 } catch (Exception e) {
123 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
128 public void handleRemoval() {
130 final EchonetLiteBridgeHandler bridgeHandler = bridgeHandler();
131 if (null == bridgeHandler) {
132 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
133 "@text/offline.conf-error.null-bridge-handler");
137 bridgeHandler.removeDevice(requireNonNull(instanceKey));
141 public void onInitialised(String identifier, InstanceKey instanceKey, Map<String, String> channelIdAndType) {
142 logger.debug("Initialised Channels: {}", channelIdAndType);
144 final List<String> toAddChannelFor = new ArrayList<>();
146 for (String channelId : channelIdAndType.keySet()) {
147 if (null == thing.getChannel(channelId)) {
148 toAddChannelFor.add(channelId);
152 logger.debug("Adding Channels: {}", toAddChannelFor);
154 if (!toAddChannelFor.isEmpty()) {
155 final ThingBuilder thingBuilder = editThing();
157 for (String channelId : toAddChannelFor) {
158 final Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), channelId))
159 .withAcceptedItemType(channelIdAndType.get(channelId))
160 .withType(new ChannelTypeUID(thing.getThingTypeUID().getBindingId(), channelId)).build();
161 thingBuilder.withChannel(channel);
163 logger.debug("Added Channel: {}", channel);
166 updateThing(thingBuilder.build());
169 updateStatus(ThingStatus.ONLINE);
173 public void onUpdated(final String channelId, final State value) {
174 stateByChannelId.put(channelId, value);
176 if (ThingStatus.ONLINE != getThing().getStatus()) {
177 updateStatus(ThingStatus.ONLINE);
179 updateState(channelId, value);
183 public void onRemoved() {
184 updateStatus(ThingStatus.REMOVED);
188 public void onOffline() {
189 if (ThingStatus.OFFLINE != getThing().getStatus()) {
190 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);