]> git.basschouten.com Git - openhab-addons.git/blob
5720388d9bebf865af512be6fb8b8b518020b333
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.netatmo.internal.servlet;
14
15 import java.io.IOException;
16 import java.net.URI;
17 import java.nio.charset.StandardCharsets;
18 import java.util.Map;
19 import java.util.concurrent.ConcurrentHashMap;
20
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23 import javax.ws.rs.HttpMethod;
24 import javax.ws.rs.core.MediaType;
25 import javax.ws.rs.core.UriBuilder;
26 import javax.ws.rs.core.UriBuilderException;
27
28 import org.eclipse.jdt.annotation.NonNullByDefault;
29 import org.openhab.binding.netatmo.internal.api.NetatmoException;
30 import org.openhab.binding.netatmo.internal.api.SecurityApi;
31 import org.openhab.binding.netatmo.internal.api.dto.WebhookEvent;
32 import org.openhab.binding.netatmo.internal.deserialization.NADeserializer;
33 import org.openhab.binding.netatmo.internal.handler.ApiBridgeHandler;
34 import org.openhab.binding.netatmo.internal.handler.capability.Capability;
35 import org.osgi.service.http.HttpService;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * HTTP servlet for Netatmo Webhook.
41  *
42  * @author GaĆ«l L'hopital - Initial contribution
43  */
44 @NonNullByDefault
45 public class WebhookServlet extends NetatmoServlet {
46     private static final long serialVersionUID = -354583910860541214L;
47
48     private final Map<String, Capability> dataListeners = new ConcurrentHashMap<>();
49     private final Logger logger = LoggerFactory.getLogger(WebhookServlet.class);
50     private final SecurityApi securityApi;
51     private final NADeserializer deserializer;
52     private final String webHookUrl;
53
54     private boolean hookSet = false;
55
56     public WebhookServlet(ApiBridgeHandler handler, HttpService httpService, NADeserializer deserializer,
57             SecurityApi securityApi, String webHookUrl) {
58         super(handler, httpService, "webhook");
59         this.deserializer = deserializer;
60         this.securityApi = securityApi;
61         this.webHookUrl = webHookUrl;
62     }
63
64     @Override
65     public void startListening() {
66         super.startListening();
67         URI uri = UriBuilder.fromUri(webHookUrl).path(path).build();
68         try {
69             logger.info("Setting up WebHook at Netatmo to {}", uri.toString());
70             hookSet = securityApi.addwebhook(uri);
71         } catch (UriBuilderException e) {
72             logger.info("webhookUrl is not a valid URI '{}' : {}", uri, e.getMessage());
73         } catch (NetatmoException e) {
74             logger.info("Error setting webhook : {}", e.getMessage());
75         }
76     }
77
78     @Override
79     public void dispose() {
80         if (hookSet) {
81             logger.info("Releasing WebHook at Netatmo ");
82             try {
83                 securityApi.dropWebhook();
84                 hookSet = false;
85             } catch (NetatmoException e) {
86                 logger.warn("Error releasing webhook : {}", e.getMessage());
87             }
88         }
89         super.dispose();
90     }
91
92     @Override
93     protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
94         replyQuick(resp);
95         processEvent(new String(req.getInputStream().readAllBytes(), StandardCharsets.UTF_8));
96     }
97
98     private void processEvent(String data) throws IOException {
99         if (!data.isEmpty()) {
100             logger.debug("Event transmitted from restService : {}", data);
101             try {
102                 WebhookEvent event = deserializer.deserialize(WebhookEvent.class, data);
103                 notifyListeners(event);
104             } catch (NetatmoException e) {
105                 logger.debug("Error deserializing webhook data received : {}. {}", data, e.getMessage());
106             }
107         }
108     }
109
110     private void replyQuick(HttpServletResponse resp) throws IOException {
111         resp.setCharacterEncoding(StandardCharsets.UTF_8.name());
112         resp.setContentType(MediaType.APPLICATION_JSON);
113         resp.setHeader("Access-Control-Allow-Origin", "*");
114         resp.setHeader("Access-Control-Allow-Methods", HttpMethod.POST);
115         resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
116         resp.setIntHeader("Access-Control-Max-Age", 3600);
117         resp.getWriter().write("");
118     }
119
120     private void notifyListeners(WebhookEvent event) {
121         event.getNAObjectList().forEach(id -> {
122             Capability module = dataListeners.get(id);
123             if (module != null) {
124                 module.setNewData(event);
125             }
126         });
127     }
128
129     public void registerDataListener(String id, Capability capability) {
130         dataListeners.put(id, capability);
131     }
132
133     public void unregisterDataListener(String id) {
134         dataListeners.remove(id);
135     }
136 }