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.gpstracker.internal;
15 import static org.openhab.binding.gpstracker.internal.GPSTrackerBindingConstants.CONFIG_PID;
18 import java.util.Collection;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Locale;
25 import javax.servlet.ServletException;
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.openhab.binding.gpstracker.internal.config.ConfigHelper;
30 import org.openhab.binding.gpstracker.internal.discovery.TrackerDiscoveryService;
31 import org.openhab.binding.gpstracker.internal.handler.TrackerHandler;
32 import org.openhab.binding.gpstracker.internal.message.NotificationBroker;
33 import org.openhab.binding.gpstracker.internal.provider.TrackerRegistry;
34 import org.openhab.binding.gpstracker.internal.provider.gpslogger.GPSLoggerCallbackServlet;
35 import org.openhab.binding.gpstracker.internal.provider.owntracks.OwnTracksCallbackServlet;
36 import org.openhab.core.config.core.ConfigOptionProvider;
37 import org.openhab.core.config.core.ParameterOption;
38 import org.openhab.core.i18n.LocationProvider;
39 import org.openhab.core.i18n.UnitProvider;
40 import org.openhab.core.thing.Thing;
41 import org.openhab.core.thing.ThingTypeUID;
42 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
43 import org.openhab.core.thing.binding.ThingHandler;
44 import org.openhab.core.thing.binding.ThingHandlerFactory;
45 import org.osgi.service.component.ComponentContext;
46 import org.osgi.service.component.annotations.Activate;
47 import org.osgi.service.component.annotations.Component;
48 import org.osgi.service.component.annotations.Reference;
49 import org.osgi.service.http.HttpService;
50 import org.osgi.service.http.NamespaceException;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
57 * @author Gabor Bicskei - Initial contribution
59 @Component(configurationPid = CONFIG_PID, service = { ThingHandlerFactory.class, ConfigOptionProvider.class })
61 public class GPSTrackerHandlerFactory extends BaseThingHandlerFactory implements TrackerRegistry, ConfigOptionProvider {
65 private static final String URI_STR = "profile:gpstracker:trigger-geofence";
70 private final Logger logger = LoggerFactory.getLogger(GPSTrackerHandlerFactory.class);
73 * Discovery service instance
75 private final TrackerDiscoveryService discoveryService;
80 private final UnitProvider unitProvider;
85 private final LocationProvider locationProvider;
88 * HTTP service reference
90 private final HttpService httpService;
93 * Endpoint called by tracker applications
95 private @NonNullByDefault({}) OwnTracksCallbackServlet otHTTPEndpoint;
98 * Endpoint called by tracker applications
100 private @NonNullByDefault({}) GPSLoggerCallbackServlet glHTTPEndpoint;
103 * Notification broker
105 private final NotificationBroker notificationBroker = new NotificationBroker();
110 private final Map<String, TrackerHandler> trackerHandlers = new HashMap<>();
115 private final Set<String> regions = new HashSet<>();
118 public GPSTrackerHandlerFactory(final @Reference HttpService httpService, //
119 final @Reference TrackerDiscoveryService discoveryService, //
120 final @Reference UnitProvider unitProvider, //
121 final @Reference LocationProvider locationProvider) {
122 this.httpService = httpService;
123 this.discoveryService = discoveryService;
124 this.unitProvider = unitProvider;
125 this.locationProvider = locationProvider;
129 * Called by the framework to find out if thing type is supported by the handler factory.
131 * @param thingTypeUID Thing type UID
132 * @return True if supported.
135 public boolean supportsThingType(ThingTypeUID thingTypeUID) {
136 return GPSTrackerBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
140 * Creates new handler for tracker.
142 * @param thing Tracker thing
143 * @return Handler instance
146 protected @Nullable ThingHandler createHandler(Thing thing) {
147 ThingTypeUID thingTypeUID = thing.getThingTypeUID();
148 if (GPSTrackerBindingConstants.THING_TYPE_TRACKER.equals(thingTypeUID)
149 && ConfigHelper.getTrackerId(thing.getConfiguration()) != null) {
150 TrackerHandler trackerHandler = new TrackerHandler(thing, notificationBroker, regions,
151 locationProvider.getLocation(), unitProvider);
152 discoveryService.removeTracker(trackerHandler.getTrackerId());
153 trackerHandlers.put(trackerHandler.getTrackerId(), trackerHandler);
154 return trackerHandler;
161 protected void removeHandler(ThingHandler thingHandler) {
162 String trackerId = ConfigHelper.getTrackerId(thingHandler.getThing().getConfiguration());
163 trackerHandlers.remove(trackerId);
167 * Activate the binding. It starts the tracker discovery service and the HTTP callback endpoint.
169 * @param componentContext Component context.
172 protected void activate(ComponentContext componentContext) {
173 super.activate(componentContext);
175 logger.debug("Initializing callback servlets");
177 otHTTPEndpoint = new OwnTracksCallbackServlet(discoveryService, this);
178 this.httpService.registerServlet(otHTTPEndpoint.getPath(), otHTTPEndpoint, null,
179 this.httpService.createDefaultHttpContext());
180 logger.debug("Started GPSTracker Callback servlet on {}", otHTTPEndpoint.getPath());
182 glHTTPEndpoint = new GPSLoggerCallbackServlet(discoveryService, this);
183 this.httpService.registerServlet(glHTTPEndpoint.getPath(), glHTTPEndpoint, null,
184 this.httpService.createDefaultHttpContext());
185 logger.debug("Started GPSTracker Callback servlet on {}", glHTTPEndpoint.getPath());
186 } catch (NamespaceException | ServletException e) {
187 logger.error("Could not start GPSTracker Callback servlet: {}", e.getMessage(), e);
192 * Deactivate the binding. It stops the HTTP callback endpoint and stops the tracker discovery service.
194 * @param componentContext Component context.
197 protected void deactivate(ComponentContext componentContext) {
198 logger.debug("Deactivating GPSTracker Binding");
200 this.httpService.unregister(otHTTPEndpoint.getPath());
201 logger.debug("GPSTracker callback servlet stopped on {}", otHTTPEndpoint.getPath());
203 this.httpService.unregister(glHTTPEndpoint.getPath());
204 logger.debug("GPSTracker callback servlet stopped on {}", glHTTPEndpoint.getPath());
206 super.deactivate(componentContext);
210 public @Nullable Collection<ParameterOption> getParameterOptions(URI uri, String param, @Nullable String context,
211 @Nullable Locale locale) {
212 if (URI_STR.equals(uri.toString()) && ConfigHelper.CONFIG_REGION_NAME.equals(param)) {
213 Set<ParameterOption> ret = new HashSet<>();
214 regions.forEach(r -> ret.add(new ParameterOption(r, r)));
221 public @Nullable TrackerHandler getTrackerHandler(String trackerId) {
222 return trackerHandlers.get(trackerId);