]> git.basschouten.com Git - openhab-addons.git/blob
2cb0ff0e63bfe766bcf07ab40f2f68422a289426
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.lirc.internal.handler;
14
15 import java.io.IOException;
16 import java.net.UnknownHostException;
17 import java.util.Set;
18 import java.util.concurrent.CopyOnWriteArraySet;
19 import java.util.concurrent.ScheduledFuture;
20 import java.util.concurrent.TimeUnit;
21
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;
36
37 /**
38  * The {@link LIRCBridgeHandler} is responsible for handling commands, which are
39  * sent to one of the channels.
40  *
41  * @author Andrew Nagle - Initial contribution
42  */
43 public class LIRCBridgeHandler extends BaseBridgeHandler {
44
45     private final Logger logger = LoggerFactory.getLogger(LIRCBridgeHandler.class);
46
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<>();
52
53     public LIRCBridgeHandler(Bridge bridge) {
54         super(bridge);
55     }
56
57     @Override
58     public void handleCommand(ChannelUID channelUID, Command command) {
59         logger.debug("Bridge commands not supported.");
60     }
61
62     @Override
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() {
68                 @Override
69                 public void run() {
70                     logger.debug("Checking LIRC connection, thing status = {}", thing.getStatus());
71                     if (thing.getStatus() != ThingStatus.ONLINE) {
72                         connect();
73                     }
74                 }
75             }, 0, 60, TimeUnit.SECONDS);
76         }
77     }
78
79     @Override
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);
85             connectorTask = null;
86         }
87         if (connector != null) {
88             logger.debug("Stopping connector");
89             connector.removeEventListener(eventListener);
90             connector.disconnect();
91         }
92         for (LIRCMessageListener deviceStatusListener : deviceStatusListeners) {
93             unregisterMessageListener(deviceStatusListener);
94         }
95         super.dispose();
96         logger.debug("Bridge handler disposed.");
97     }
98
99     private void connect() {
100         logger.debug("Connecting to LIRC");
101
102         try {
103             if (connector != null) {
104                 connector.disconnect();
105             }
106             if (configuration.getHost() != null && connector == null) {
107                 connector = new LIRCConnector();
108             }
109             if (connector != null) {
110                 connector.connect(configuration);
111                 connector.addEventListener(eventListener);
112                 updateStatus(ThingStatus.ONLINE);
113                 startDeviceDiscovery();
114             }
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());
121         }
122     }
123
124     /**
125      * Initiates discovery of remotes
126      */
127     public void startDeviceDiscovery() {
128         if (connector != null) {
129             connector.startRemoteDiscovery();
130         }
131     }
132
133     /**
134      * Registers a message listener
135      *
136      * @param listener message listener to add
137      * @return true if listener as added successfully; false otherwise
138      */
139     public boolean registerMessageListener(LIRCMessageListener listener) {
140         if (listener == null) {
141             throw new IllegalArgumentException("The listener parameter may not be null.");
142         }
143         return deviceStatusListeners.add(listener);
144     }
145
146     /**
147      * Unregisters a message listener
148      *
149      * @param listener message listener to remove
150      * @return true if listener as removed successfully; false otherwise
151      */
152     public boolean unregisterMessageListener(LIRCMessageListener listener) {
153         if (listener == null) {
154             throw new IllegalArgumentException("The listener parameter may not be null.");
155         }
156         return deviceStatusListeners.remove(listener);
157     }
158
159     /**
160      * Transmits the button press for the specified remote.
161      *
162      * @param remote Name of the remote
163      * @param button Button to press
164      */
165     public void transmit(String remote, String button) {
166         connector.transmit(remote, button);
167     }
168
169     private class EventListener implements LIRCEventListener {
170
171         @Override
172         public void messageReceived(LIRCResponse response) {
173             for (LIRCMessageListener deviceStatusListener : deviceStatusListeners) {
174                 try {
175                     deviceStatusListener.onMessageReceived(getThing().getUID(), response);
176                 } catch (Exception e) {
177                     logger.error("An exception occurred while calling the DeviceStatusListener", e);
178                 }
179             }
180         }
181
182         @Override
183         public void buttonPressed(LIRCButtonEvent buttonEvent) {
184             for (LIRCMessageListener deviceStatusListener : deviceStatusListeners) {
185                 try {
186                     deviceStatusListener.onButtonPressed(getThing().getUID(), buttonEvent);
187                 } catch (Exception e) {
188                     logger.error("An exception occurred while calling the DeviceStatusListener", e);
189                 }
190             }
191         }
192
193         @Override
194         public void errorOccured(String error) {
195             logger.error("Error occured: {}", error);
196             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error);
197         }
198     }
199 }