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.lutron.internal;
15 import static org.openhab.binding.lutron.internal.LutronBindingConstants.*;
17 import java.util.Collections;
18 import java.util.HashMap;
21 import java.util.stream.Collectors;
22 import java.util.stream.Stream;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.eclipse.jetty.client.HttpClient;
27 import org.openhab.binding.lutron.internal.discovery.LutronDeviceDiscoveryService;
28 import org.openhab.binding.lutron.internal.grxprg.GrafikEyeHandler;
29 import org.openhab.binding.lutron.internal.grxprg.PrgBridgeHandler;
30 import org.openhab.binding.lutron.internal.grxprg.PrgConstants;
31 import org.openhab.binding.lutron.internal.handler.BlindHandler;
32 import org.openhab.binding.lutron.internal.handler.CcoHandler;
33 import org.openhab.binding.lutron.internal.handler.DimmerHandler;
34 import org.openhab.binding.lutron.internal.handler.FanHandler;
35 import org.openhab.binding.lutron.internal.handler.GrafikEyeKeypadHandler;
36 import org.openhab.binding.lutron.internal.handler.GreenModeHandler;
37 import org.openhab.binding.lutron.internal.handler.IPBridgeHandler;
38 import org.openhab.binding.lutron.internal.handler.IntlKeypadHandler;
39 import org.openhab.binding.lutron.internal.handler.KeypadHandler;
40 import org.openhab.binding.lutron.internal.handler.LeapBridgeHandler;
41 import org.openhab.binding.lutron.internal.handler.MaintainedCcoHandler;
42 import org.openhab.binding.lutron.internal.handler.OGroupHandler;
43 import org.openhab.binding.lutron.internal.handler.OccupancySensorHandler;
44 import org.openhab.binding.lutron.internal.handler.PalladiomKeypadHandler;
45 import org.openhab.binding.lutron.internal.handler.PicoKeypadHandler;
46 import org.openhab.binding.lutron.internal.handler.PulsedCcoHandler;
47 import org.openhab.binding.lutron.internal.handler.QSIOHandler;
48 import org.openhab.binding.lutron.internal.handler.ShadeHandler;
49 import org.openhab.binding.lutron.internal.handler.SwitchHandler;
50 import org.openhab.binding.lutron.internal.handler.SysvarHandler;
51 import org.openhab.binding.lutron.internal.handler.TabletopKeypadHandler;
52 import org.openhab.binding.lutron.internal.handler.TimeclockHandler;
53 import org.openhab.binding.lutron.internal.handler.VcrxHandler;
54 import org.openhab.binding.lutron.internal.handler.VirtualKeypadHandler;
55 import org.openhab.binding.lutron.internal.handler.WciHandler;
56 import org.openhab.binding.lutron.internal.hw.HwConstants;
57 import org.openhab.binding.lutron.internal.hw.HwDimmerHandler;
58 import org.openhab.binding.lutron.internal.hw.HwSerialBridgeHandler;
59 import org.openhab.binding.lutron.internal.radiora.RadioRAConstants;
60 import org.openhab.binding.lutron.internal.radiora.handler.PhantomButtonHandler;
61 import org.openhab.binding.lutron.internal.radiora.handler.RS232Handler;
62 import org.openhab.core.config.discovery.DiscoveryService;
63 import org.openhab.core.io.net.http.HttpClientFactory;
64 import org.openhab.core.io.transport.serial.SerialPortManager;
65 import org.openhab.core.thing.Bridge;
66 import org.openhab.core.thing.Thing;
67 import org.openhab.core.thing.ThingTypeUID;
68 import org.openhab.core.thing.ThingUID;
69 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
70 import org.openhab.core.thing.binding.ThingHandler;
71 import org.openhab.core.thing.binding.ThingHandlerFactory;
72 import org.osgi.framework.ServiceRegistration;
73 import org.osgi.service.component.annotations.Activate;
74 import org.osgi.service.component.annotations.Component;
75 import org.osgi.service.component.annotations.Reference;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
80 * The {@link LutronHandlerFactory} is responsible for creating things and thing
83 * @author Allan Tong - Initial contribution
84 * @author Bob Adair - Added bridge discovery service registration/removal
88 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.lutron")
89 public class LutronHandlerFactory extends BaseThingHandlerFactory {
91 // Used by LutronDeviceDiscoveryService to discover these types
92 public static final Set<ThingTypeUID> DISCOVERABLE_DEVICE_TYPES_UIDS = Collections
93 .unmodifiableSet(Stream
94 .of(THING_TYPE_DIMMER, THING_TYPE_SWITCH, THING_TYPE_OCCUPANCYSENSOR, THING_TYPE_KEYPAD,
95 THING_TYPE_TTKEYPAD, THING_TYPE_INTLKEYPAD, THING_TYPE_PICO, THING_TYPE_VIRTUALKEYPAD,
96 THING_TYPE_VCRX, THING_TYPE_CCO, THING_TYPE_SHADE, THING_TYPE_TIMECLOCK,
97 THING_TYPE_GREENMODE, THING_TYPE_QSIO, THING_TYPE_GRAFIKEYEKEYPAD, THING_TYPE_BLIND,
98 THING_TYPE_PALLADIOMKEYPAD, THING_TYPE_WCI, THING_TYPE_OGROUP, THING_TYPE_FAN)
99 .collect(Collectors.toSet()));
101 // Used by the HwDiscoveryService
102 public static final Set<ThingTypeUID> HW_DISCOVERABLE_DEVICE_TYPES_UIDS = Collections
103 .unmodifiableSet(Collections.singleton(HwConstants.THING_TYPE_HWDIMMER));
105 // Other types that can be initiated but not discovered
106 private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
107 .unmodifiableSet(Stream
108 .of(THING_TYPE_IPBRIDGE, THING_TYPE_LEAPBRIDGE, PrgConstants.THING_TYPE_PRGBRIDGE,
109 PrgConstants.THING_TYPE_GRAFIKEYE, RadioRAConstants.THING_TYPE_RS232,
110 RadioRAConstants.THING_TYPE_DIMMER, RadioRAConstants.THING_TYPE_SWITCH,
111 RadioRAConstants.THING_TYPE_PHANTOM, HwConstants.THING_TYPE_HWSERIALBRIDGE,
112 THING_TYPE_CCO_PULSED, THING_TYPE_CCO_MAINTAINED, THING_TYPE_SYSVAR)
113 .collect(Collectors.toSet()));
115 private final Logger logger = LoggerFactory.getLogger(LutronHandlerFactory.class);
117 private final SerialPortManager serialPortManager;
118 private final HttpClient httpClient;
121 public LutronHandlerFactory(final @Reference SerialPortManager serialPortManager,
122 @Reference HttpClientFactory httpClientFactory) {
123 this.serialPortManager = serialPortManager;
124 this.httpClient = httpClientFactory.getCommonHttpClient();
128 public boolean supportsThingType(ThingTypeUID thingTypeUID) {
129 return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)
130 || DISCOVERABLE_DEVICE_TYPES_UIDS.contains(thingTypeUID)
131 || HW_DISCOVERABLE_DEVICE_TYPES_UIDS.contains(thingTypeUID);
134 private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegMap = new HashMap<>();
135 // Marked as Nullable only to fix incorrect redundant null check complaints after adding null annotations
138 protected @Nullable ThingHandler createHandler(Thing thing) {
139 ThingTypeUID thingTypeUID = thing.getThingTypeUID();
141 if (thingTypeUID.equals(THING_TYPE_IPBRIDGE)) {
142 IPBridgeHandler bridgeHandler = new IPBridgeHandler((Bridge) thing);
143 registerDiscoveryService(bridgeHandler);
144 return bridgeHandler;
145 } else if (thingTypeUID.equals(THING_TYPE_LEAPBRIDGE)) {
146 LeapBridgeHandler bridgeHandler = new LeapBridgeHandler((Bridge) thing);
147 return bridgeHandler;
148 } else if (thingTypeUID.equals(THING_TYPE_DIMMER)) {
149 return new DimmerHandler(thing);
150 } else if (thingTypeUID.equals(THING_TYPE_SHADE)) {
151 return new ShadeHandler(thing);
152 } else if (thingTypeUID.equals(THING_TYPE_SWITCH)) {
153 return new SwitchHandler(thing);
154 } else if (thingTypeUID.equals(THING_TYPE_CCO)) {
155 return new CcoHandler(thing);
156 } else if (thingTypeUID.equals(THING_TYPE_CCO_PULSED)) {
157 return new PulsedCcoHandler(thing);
158 } else if (thingTypeUID.equals(THING_TYPE_CCO_MAINTAINED)) {
159 return new MaintainedCcoHandler(thing);
160 } else if (thingTypeUID.equals(THING_TYPE_OCCUPANCYSENSOR)) {
161 return new OccupancySensorHandler(thing);
162 } else if (thingTypeUID.equals(THING_TYPE_KEYPAD)) {
163 return new KeypadHandler(thing);
164 } else if (thingTypeUID.equals(THING_TYPE_TTKEYPAD)) {
165 return new TabletopKeypadHandler(thing);
166 } else if (thingTypeUID.equals(THING_TYPE_INTLKEYPAD)) {
167 return new IntlKeypadHandler(thing);
168 } else if (thingTypeUID.equals(THING_TYPE_PICO)) {
169 return new PicoKeypadHandler(thing);
170 } else if (thingTypeUID.equals(THING_TYPE_GRAFIKEYEKEYPAD)) {
171 return new GrafikEyeKeypadHandler(thing);
172 } else if (thingTypeUID.equals(THING_TYPE_PALLADIOMKEYPAD)) {
173 return new PalladiomKeypadHandler(thing);
174 } else if (thingTypeUID.equals(THING_TYPE_VIRTUALKEYPAD)) {
175 return new VirtualKeypadHandler(thing);
176 } else if (thingTypeUID.equals(THING_TYPE_VCRX)) {
177 return new VcrxHandler(thing);
178 } else if (thingTypeUID.equals(THING_TYPE_WCI)) {
179 return new WciHandler(thing);
180 } else if (thingTypeUID.equals(THING_TYPE_TIMECLOCK)) {
181 return new TimeclockHandler(thing);
182 } else if (thingTypeUID.equals(THING_TYPE_GREENMODE)) {
183 return new GreenModeHandler(thing);
184 } else if (thingTypeUID.equals(THING_TYPE_QSIO)) {
185 return new QSIOHandler(thing);
186 } else if (thingTypeUID.equals(THING_TYPE_BLIND)) {
187 return new BlindHandler(thing);
188 } else if (thingTypeUID.equals(THING_TYPE_SYSVAR)) {
189 return new SysvarHandler(thing);
190 } else if (thingTypeUID.equals(THING_TYPE_OGROUP)) {
191 return new OGroupHandler(thing);
192 } else if (thingTypeUID.equals(THING_TYPE_FAN)) {
193 return new FanHandler(thing);
194 } else if (thingTypeUID.equals(PrgConstants.THING_TYPE_PRGBRIDGE)) {
195 return new PrgBridgeHandler((Bridge) thing);
196 } else if (thingTypeUID.equals(PrgConstants.THING_TYPE_GRAFIKEYE)) {
197 return new GrafikEyeHandler(thing);
198 } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_RS232)) {
199 return new RS232Handler((Bridge) thing, serialPortManager);
200 } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_DIMMER)) {
201 return new org.openhab.binding.lutron.internal.radiora.handler.DimmerHandler(thing);
202 } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_SWITCH)) {
203 return new org.openhab.binding.lutron.internal.radiora.handler.SwitchHandler(thing);
204 } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_PHANTOM)) {
205 return new PhantomButtonHandler(thing);
206 } else if (thingTypeUID.equals(HwConstants.THING_TYPE_HWSERIALBRIDGE)) {
207 return new HwSerialBridgeHandler((Bridge) thing, serialPortManager);
208 } else if (thingTypeUID.equals(HwConstants.THING_TYPE_HWDIMMER)) {
209 return new HwDimmerHandler(thing);
216 protected synchronized void removeHandler(ThingHandler thingHandler) {
217 if (thingHandler instanceof IPBridgeHandler) {
218 ServiceRegistration<?> serviceReg = discoveryServiceRegMap.remove(thingHandler.getThing().getUID());
219 if (serviceReg != null) {
220 logger.debug("Unregistering device discovery service.");
221 serviceReg.unregister();
227 * Register a discovery service for an IP bridge handler.
229 * @param bridgeHandler IP bridge handler for which to register the discovery service
231 private synchronized void registerDiscoveryService(IPBridgeHandler bridgeHandler) {
232 logger.debug("Registering XML device discovery service.");
233 LutronDeviceDiscoveryService discoveryService = new LutronDeviceDiscoveryService(bridgeHandler, httpClient);
234 bridgeHandler.setDiscoveryService(discoveryService);
235 discoveryServiceRegMap.put(bridgeHandler.getThing().getUID(),
236 bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, null));