]> git.basschouten.com Git - openhab-addons.git/blob
505e81f6d429d4ff3529b704c54690639ce3dc84
[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.gpstracker.internal;
14
15 import static org.openhab.binding.gpstracker.internal.GPSTrackerBindingConstants.CONFIG_PID;
16
17 import java.net.URI;
18 import java.util.Collection;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Locale;
22 import java.util.Map;
23 import java.util.Set;
24
25 import javax.servlet.ServletException;
26
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;
53
54 /**
55  * Main component
56  *
57  * @author Gabor Bicskei - Initial contribution
58  */
59 @Component(configurationPid = CONFIG_PID, service = { ThingHandlerFactory.class, ConfigOptionProvider.class })
60 @NonNullByDefault
61 public class GPSTrackerHandlerFactory extends BaseThingHandlerFactory implements TrackerRegistry, ConfigOptionProvider {
62     /**
63      * Config URI
64      */
65     private static final String URI_STR = "profile:gpstracker:trigger-geofence";
66
67     /**
68      * Class logger
69      */
70     private final Logger logger = LoggerFactory.getLogger(GPSTrackerHandlerFactory.class);
71
72     /**
73      * Discovery service instance
74      */
75     private final TrackerDiscoveryService discoveryService;
76
77     /**
78      * Unit provider
79      */
80     private final UnitProvider unitProvider;
81
82     /**
83      * Location provider
84      */
85     private final LocationProvider locationProvider;
86
87     /**
88      * HTTP service reference
89      */
90     private final HttpService httpService;
91
92     /**
93      * Endpoint called by tracker applications
94      */
95     private @NonNullByDefault({}) OwnTracksCallbackServlet otHTTPEndpoint;
96
97     /**
98      * Endpoint called by tracker applications
99      */
100     private @NonNullByDefault({}) GPSLoggerCallbackServlet glHTTPEndpoint;
101
102     /**
103      * Notification broker
104      */
105     private final NotificationBroker notificationBroker = new NotificationBroker();
106
107     /**
108      * Handler registry
109      */
110     private final Map<String, TrackerHandler> trackerHandlers = new HashMap<>();
111
112     /**
113      * All regions.
114      */
115     private final Set<String> regions = new HashSet<>();
116
117     @Activate
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;
126     }
127
128     /**
129      * Called by the framework to find out if thing type is supported by the handler factory.
130      *
131      * @param thingTypeUID Thing type UID
132      * @return True if supported.
133      */
134     @Override
135     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
136         return GPSTrackerBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
137     }
138
139     /**
140      * Creates new handler for tracker.
141      *
142      * @param thing Tracker thing
143      * @return Handler instance
144      */
145     @Override
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;
155         } else {
156             return null;
157         }
158     }
159
160     @Override
161     protected void removeHandler(ThingHandler thingHandler) {
162         String trackerId = ConfigHelper.getTrackerId(thingHandler.getThing().getConfiguration());
163         trackerHandlers.remove(trackerId);
164     }
165
166     /**
167      * Activate the binding. It starts the tracker discovery service and the HTTP callback endpoint.
168      *
169      * @param componentContext Component context.
170      */
171     @Override
172     protected void activate(ComponentContext componentContext) {
173         super.activate(componentContext);
174
175         logger.debug("Initializing callback servlets");
176         try {
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());
181
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);
188         }
189     }
190
191     /**
192      * Deactivate the binding. It stops the HTTP callback endpoint and stops the tracker discovery service.
193      *
194      * @param componentContext Component context.
195      */
196     @Override
197     protected void deactivate(ComponentContext componentContext) {
198         logger.debug("Deactivating GPSTracker Binding");
199
200         this.httpService.unregister(otHTTPEndpoint.getPath());
201         logger.debug("GPSTracker callback servlet stopped on {}", otHTTPEndpoint.getPath());
202
203         this.httpService.unregister(glHTTPEndpoint.getPath());
204         logger.debug("GPSTracker callback servlet stopped on {}", glHTTPEndpoint.getPath());
205
206         super.deactivate(componentContext);
207     }
208
209     @Override
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)));
215             return ret;
216         }
217         return null;
218     }
219
220     @Override
221     public @Nullable TrackerHandler getTrackerHandler(String trackerId) {
222         return trackerHandlers.get(trackerId);
223     }
224 }