]> git.basschouten.com Git - openhab-addons.git/blob
8f24072066ff08e1abb4440daa2db423ce9ac7b4
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.webthing.internal.client;
14
15 import java.io.IOException;
16 import java.net.URI;
17 import java.time.Duration;
18 import java.util.Locale;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.TimeoutException;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jetty.client.HttpClient;
25 import org.openhab.binding.webthing.internal.client.dto.WebThingDescription;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import com.google.gson.Gson;
30 import com.google.gson.JsonSyntaxException;
31
32 /**
33  * Utility class to load the WebThing description (meta data). Refer https://iot.mozilla.org/wot/#web-thing-description
34  *
35  * @author Gregor Roth - Initial contribution
36  */
37 @NonNullByDefault
38 public class DescriptionLoader {
39     private final Logger logger = LoggerFactory.getLogger(DescriptionLoader.class);
40     private final Gson gson = new Gson();
41     private final HttpClient httpClient;
42
43     /**
44      * constructor
45      *
46      * @param httpClient the http client to use
47      */
48     public DescriptionLoader(HttpClient httpClient) {
49         this.httpClient = httpClient;
50     }
51
52     /**
53      * loads the WebThing meta data
54      *
55      * @param webthingURI the WebThing URI
56      * @param timeout the timeout
57      * @return the Webthing description
58      * @throws IOException if the WebThing can not be connected
59      */
60     public WebThingDescription loadWebthingDescription(URI webthingURI, Duration timeout) throws IOException {
61         try {
62             var response = httpClient.newRequest(webthingURI).timeout(30, TimeUnit.SECONDS).accept("application/json")
63                     .send();
64             if (response.getStatus() < 200 || response.getStatus() >= 300) {
65                 throw new IOException(
66                         "could not read resource description " + webthingURI + ". Got " + response.getStatus());
67             }
68             var body = response.getContentAsString();
69             var description = gson.fromJson(body, WebThingDescription.class);
70             if ((description != null) && (description.properties != null) && (description.properties.size() > 0)) {
71                 if ((description.contextKeyword == null) || description.contextKeyword.trim().length() == 0) {
72                     description.contextKeyword = "https://webthings.io/schemas";
73                 }
74                 var schema = description.contextKeyword.replaceFirst("/$", "").toLowerCase(Locale.US).trim();
75
76                 // currently, the old and new location of the WebThings schema are supported only.
77                 // In the future, other schemas such as http://iotschema.org/docs/full.html may be supported
78                 if ("https://webthings.io/schemas".equals(schema) || "https://iot.mozilla.org/schemas".equals(schema)) {
79                     return description;
80                 }
81                 logger.debug(
82                         "WebThing {} detected with unsupported schema {} (Supported schemas are https://webthings.io/schemas and https://iot.mozilla.org/schemas)",
83                         webthingURI, description.contextKeyword);
84                 throw new IOException("unsupported schema (@context parameter) " + description.contextKeyword
85                         + " (Supported schemas are https://webthings.io/schemas and https://iot.mozilla.org/schemas)");
86             } else {
87                 throw new IOException("description does not include properties");
88             }
89         } catch (ExecutionException | TimeoutException e) {
90             throw new IOException("error occurred by calling WebThing", e);
91         } catch (JsonSyntaxException se) {
92             throw new IOException("resource seems not to be a WebThing. Typo?");
93         } catch (InterruptedException ie) {
94             throw new IOException("resource seems not to be reachable");
95         }
96     }
97 }