2 * Copyright (c) 2010-2020 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.lametrictime.internal;
15 import static org.openhab.binding.lametrictime.internal.LaMetricTimeBindingConstants.*;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Hashtable;
22 import java.util.stream.Collectors;
23 import java.util.stream.Stream;
25 import javax.ws.rs.client.ClientBuilder;
27 import org.openhab.binding.lametrictime.internal.discovery.LaMetricTimeAppDiscoveryService;
28 import org.openhab.binding.lametrictime.internal.handler.ClockAppHandler;
29 import org.openhab.binding.lametrictime.internal.handler.CountdownAppHandler;
30 import org.openhab.binding.lametrictime.internal.handler.LaMetricTimeHandler;
31 import org.openhab.binding.lametrictime.internal.handler.RadioAppHandler;
32 import org.openhab.binding.lametrictime.internal.handler.StopwatchAppHandler;
33 import org.openhab.binding.lametrictime.internal.handler.WeatherAppHandler;
34 import org.openhab.core.config.discovery.DiscoveryService;
35 import org.openhab.core.thing.Bridge;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingTypeUID;
38 import org.openhab.core.thing.ThingUID;
39 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
40 import org.openhab.core.thing.binding.ThingHandler;
41 import org.openhab.core.thing.binding.ThingHandlerFactory;
42 import org.osgi.framework.ServiceRegistration;
43 import org.osgi.service.component.annotations.Component;
44 import org.osgi.service.component.annotations.Reference;
45 import org.osgi.service.component.annotations.ReferenceCardinality;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
50 * The {@link LaMetricTimeHandlerFactory} is responsible for creating things and thing
53 * @author Gregory Moyer - Initial contribution
55 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.lametrictime")
56 public class LaMetricTimeHandlerFactory extends BaseThingHandlerFactory {
58 private static final Set<ThingTypeUID> SUPPORTED_THING_TYPE_UIDS = Collections.unmodifiableSet(
59 Stream.of(THING_TYPE_DEVICE, THING_TYPE_CLOCK_APP, THING_TYPE_COUNTDOWN_APP, THING_TYPE_RADIO_APP,
60 THING_TYPE_STOPWATCH_APP, THING_TYPE_WEATHER_APP).collect(Collectors.toSet()));
62 // TODO: Those constants are Jersey specific - once we move away from Jersey,
63 // this can be removed and the client builder creation simplified.
64 public static final String READ_TIMEOUT_JERSEY = "jersey.config.client.readTimeout";
65 public static final String CONNECT_TIMEOUT_JERSEY = "jersey.config.client.connectTimeout";
67 public static final String READ_TIMEOUT = "http.receive.timeout";
68 public static final String CONNECT_TIMEOUT = "http.connection.timeout";
70 private static final int EVENT_STREAM_CONNECT_TIMEOUT = 10000;
71 private static final int EVENT_STREAM_READ_TIMEOUT = 10000;
73 private final Logger logger = LoggerFactory.getLogger(LaMetricTimeHandlerFactory.class);
75 private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceReg = new HashMap<>();
77 @Reference(cardinality = ReferenceCardinality.OPTIONAL)
78 private ClientBuilder injectedClientBuilder;
80 private ClientBuilder clientBuilder;
82 private StateDescriptionOptionsProvider stateDescriptionProvider;
85 public boolean supportsThingType(ThingTypeUID thingTypeUID) {
86 return SUPPORTED_THING_TYPE_UIDS.contains(thingTypeUID);
90 protected ThingHandler createHandler(Thing thing) {
91 ThingTypeUID thingTypeUID = thing.getThingTypeUID();
93 if (THING_TYPE_DEVICE.equals(thingTypeUID)) {
94 logger.debug("Creating handler for LaMetric Time device {}", thing);
96 LaMetricTimeHandler deviceHandler = new LaMetricTimeHandler((Bridge) thing, stateDescriptionProvider,
98 registerAppDiscoveryService(deviceHandler);
100 return deviceHandler;
101 } else if (THING_TYPE_CLOCK_APP.equals(thingTypeUID)) {
102 logger.debug("Creating handler for LaMetric Time clock app {}", thing);
103 return new ClockAppHandler(thing);
104 } else if (THING_TYPE_COUNTDOWN_APP.equals(thingTypeUID)) {
105 logger.debug("Creating handler for LaMetric Time countdown app {}", thing);
106 return new CountdownAppHandler(thing);
107 } else if (THING_TYPE_RADIO_APP.equals(thingTypeUID)) {
108 logger.debug("Creating handler for LaMetric Time radio app {}", thing);
109 return new RadioAppHandler(thing);
110 } else if (THING_TYPE_STOPWATCH_APP.equals(thingTypeUID)) {
111 logger.debug("Creating handler for LaMetric Time stopwatch app {}", thing);
112 return new StopwatchAppHandler(thing);
113 } else if (THING_TYPE_WEATHER_APP.equals(thingTypeUID)) {
114 logger.debug("Creating handler for LaMetric Time weather app {}", thing);
115 return new WeatherAppHandler(thing);
122 protected void removeHandler(final ThingHandler thingHandler) {
123 if (!(thingHandler instanceof LaMetricTimeHandler)) {
127 unregisterAppDiscoveryService((LaMetricTimeHandler) thingHandler);
131 * Register the given device handler to participate in discovery of new apps.
133 * @param deviceHandler the device handler to register (must not be <code>null</code>)
135 private synchronized void registerAppDiscoveryService(final LaMetricTimeHandler deviceHandler) {
136 logger.debug("Registering app discovery service");
137 LaMetricTimeAppDiscoveryService discoveryService = new LaMetricTimeAppDiscoveryService(deviceHandler);
138 discoveryServiceReg.put(deviceHandler.getThing().getUID(),
139 bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
143 * Unregister the given device handler from participating in discovery of new apps.
145 * @param deviceHandler the device handler to unregister (must not be <code>null</code>)
147 private synchronized void unregisterAppDiscoveryService(final LaMetricTimeHandler deviceHandler) {
148 ThingUID thingUID = deviceHandler.getThing().getUID();
149 ServiceRegistration<?> serviceReg = discoveryServiceReg.remove(thingUID);
150 if (serviceReg != null) {
151 logger.debug("Unregistering app discovery service");
152 serviceReg.unregister();
157 protected void setDynamicStateDescriptionProvider(StateDescriptionOptionsProvider provider) {
158 this.stateDescriptionProvider = provider;
161 protected void unsetDynamicStateDescriptionProvider(StateDescriptionOptionsProvider provider) {
162 this.stateDescriptionProvider = null;
165 private synchronized ClientBuilder getClientBuilder() {
166 if (clientBuilder == null) {
168 clientBuilder = ClientBuilder.newBuilder();
169 clientBuilder.property(CONNECT_TIMEOUT_JERSEY, EVENT_STREAM_CONNECT_TIMEOUT);
170 clientBuilder.property(READ_TIMEOUT_JERSEY, EVENT_STREAM_READ_TIMEOUT);
171 } catch (Exception e) {
172 // we seem to have no Jersey, so let's hope for an injected builder by CXF
173 if (this.injectedClientBuilder != null) {
174 clientBuilder = injectedClientBuilder;
175 clientBuilder.property(CONNECT_TIMEOUT, EVENT_STREAM_CONNECT_TIMEOUT);
176 clientBuilder.property(READ_TIMEOUT, EVENT_STREAM_READ_TIMEOUT);
178 throw new IllegalStateException("No JAX RS Client Builder available.");
182 return clientBuilder;