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) {
92 logger.debug("Updating: {} to {}", channelUID, command);
94 handler.updateDevice(requireNonNull(instanceKey), channelUID.getId(), (State) command);
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());
127 public void handleRemoval() {
129 final EchonetLiteBridgeHandler bridgeHandler = bridgeHandler();
130 if (null == bridgeHandler) {
131 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
132 "@text/offline.conf-error.null-bridge-handler");
136 bridgeHandler.removeDevice(requireNonNull(instanceKey));
139 public void onInitialised(String identifier, InstanceKey instanceKey, Map<String, String> channelIdAndType) {
140 logger.debug("Initialised Channels: {}", channelIdAndType);
142 final List<String> toAddChannelFor = new ArrayList<>();
144 for (String channelId : channelIdAndType.keySet()) {
145 if (null == thing.getChannel(channelId)) {
146 toAddChannelFor.add(channelId);
150 logger.debug("Adding Channels: {}", toAddChannelFor);
152 if (!toAddChannelFor.isEmpty()) {
153 final ThingBuilder thingBuilder = editThing();
155 for (String channelId : toAddChannelFor) {
156 final Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), channelId))
157 .withAcceptedItemType(channelIdAndType.get(channelId))
158 .withType(new ChannelTypeUID(thing.getThingTypeUID().getBindingId(), channelId)).build();
159 thingBuilder.withChannel(channel);
161 logger.debug("Added Channel: {}", channel);
164 updateThing(thingBuilder.build());
167 updateStatus(ThingStatus.ONLINE);
170 public void onUpdated(final String channelId, final State value) {
171 stateByChannelId.put(channelId, value);
173 if (ThingStatus.ONLINE != getThing().getStatus()) {
174 updateStatus(ThingStatus.ONLINE);
176 updateState(channelId, value);
179 public void onRemoved() {
180 updateStatus(ThingStatus.REMOVED);
183 public void onOffline() {
184 if (ThingStatus.OFFLINE != getThing().getStatus()) {
185 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);