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.lirc.internal.handler;
15 import java.io.IOException;
16 import java.net.UnknownHostException;
18 import java.util.concurrent.CopyOnWriteArraySet;
19 import java.util.concurrent.ScheduledFuture;
20 import java.util.concurrent.TimeUnit;
22 import org.openhab.binding.lirc.internal.LIRCMessageListener;
23 import org.openhab.binding.lirc.internal.config.LIRCBridgeConfiguration;
24 import org.openhab.binding.lirc.internal.connector.LIRCConnector;
25 import org.openhab.binding.lirc.internal.connector.LIRCEventListener;
26 import org.openhab.binding.lirc.internal.messages.LIRCButtonEvent;
27 import org.openhab.binding.lirc.internal.messages.LIRCResponse;
28 import org.openhab.core.thing.Bridge;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.binding.BaseBridgeHandler;
33 import org.openhab.core.types.Command;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * The {@link LIRCBridgeHandler} is responsible for handling commands, which are
39 * sent to one of the channels.
41 * @author Andrew Nagle - Initial contribution
43 public class LIRCBridgeHandler extends BaseBridgeHandler {
45 private final Logger logger = LoggerFactory.getLogger(LIRCBridgeHandler.class);
47 private LIRCBridgeConfiguration configuration;
48 private ScheduledFuture<?> connectorTask;
49 private LIRCConnector connector;
50 private EventListener eventListener = new EventListener();
51 private Set<LIRCMessageListener> deviceStatusListeners = new CopyOnWriteArraySet<>();
53 public LIRCBridgeHandler(Bridge bridge) {
58 public void handleCommand(ChannelUID channelUID, Command command) {
59 logger.debug("Bridge commands not supported.");
63 public void initialize() {
64 logger.debug("Initializing the LIRC Bridge handler");
65 configuration = getConfigAs(LIRCBridgeConfiguration.class);
66 if (connectorTask == null || connectorTask.isCancelled()) {
67 connectorTask = scheduler.scheduleWithFixedDelay(new Runnable() {
70 logger.debug("Checking LIRC connection, thing status = {}", thing.getStatus());
71 if (thing.getStatus() != ThingStatus.ONLINE) {
75 }, 0, 60, TimeUnit.SECONDS);
80 public void dispose() {
81 logger.debug("Disposing bridge handler.");
82 if (connectorTask != null && !connectorTask.isCancelled()) {
83 logger.debug("Cancelling task.");
84 connectorTask.cancel(true);
87 if (connector != null) {
88 logger.debug("Stopping connector");
89 connector.removeEventListener(eventListener);
90 connector.disconnect();
92 for (LIRCMessageListener deviceStatusListener : deviceStatusListeners) {
93 unregisterMessageListener(deviceStatusListener);
96 logger.debug("Bridge handler disposed.");
99 private void connect() {
100 logger.debug("Connecting to LIRC");
103 if (connector != null) {
104 connector.disconnect();
106 if (configuration.getHost() != null && connector == null) {
107 connector = new LIRCConnector();
109 if (connector != null) {
110 connector.connect(configuration);
111 connector.addEventListener(eventListener);
112 updateStatus(ThingStatus.ONLINE);
113 startDeviceDiscovery();
115 } catch (UnknownHostException e) {
116 logger.error("Connection to LIRC failed: unknown host");
117 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Unknown Host");
118 } catch (IOException e) {
119 logger.error("Connection to LIRC failed", e);
120 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
125 * Initiates discovery of remotes
127 public void startDeviceDiscovery() {
128 if (connector != null) {
129 connector.startRemoteDiscovery();
134 * Registers a message listener
136 * @param listener message listener to add
137 * @return true if listener as added successfully; false otherwise
139 public boolean registerMessageListener(LIRCMessageListener listener) {
140 if (listener == null) {
141 throw new IllegalArgumentException("The listener parameter may not be null.");
143 return deviceStatusListeners.add(listener);
147 * Unregisters a message listener
149 * @param listener message listener to remove
150 * @return true if listener as removed successfully; false otherwise
152 public boolean unregisterMessageListener(LIRCMessageListener listener) {
153 if (listener == null) {
154 throw new IllegalArgumentException("The listener parameter may not be null.");
156 return deviceStatusListeners.remove(listener);
160 * Transmits the button press for the specified remote.
162 * @param remote Name of the remote
163 * @param button Button to press
165 public void transmit(String remote, String button) {
166 connector.transmit(remote, button);
169 private class EventListener implements LIRCEventListener {
172 public void messageReceived(LIRCResponse response) {
173 for (LIRCMessageListener deviceStatusListener : deviceStatusListeners) {
175 deviceStatusListener.onMessageReceived(getThing().getUID(), response);
176 } catch (Exception e) {
177 logger.error("An exception occurred while calling the DeviceStatusListener", e);
183 public void buttonPressed(LIRCButtonEvent buttonEvent) {
184 for (LIRCMessageListener deviceStatusListener : deviceStatusListeners) {
186 deviceStatusListener.onButtonPressed(getThing().getUID(), buttonEvent);
187 } catch (Exception e) {
188 logger.error("An exception occurred while calling the DeviceStatusListener", e);
194 public void errorOccured(String error) {
195 logger.error("Error occured: {}", error);
196 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error);