]> git.basschouten.com Git - openhab-addons.git/blob
bb82fd44808126cc7aa8d299add3ec72c45114cf
[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.sensebox.internal;
14
15 import static org.openhab.binding.sensebox.internal.SenseBoxBindingConstants.*;
16
17 import java.io.IOException;
18 import java.util.List;
19 import java.util.Properties;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.sensebox.internal.dto.SenseBoxData;
23 import org.openhab.binding.sensebox.internal.dto.SenseBoxDescriptor;
24 import org.openhab.binding.sensebox.internal.dto.SenseBoxLoc;
25 import org.openhab.binding.sensebox.internal.dto.SenseBoxLocation;
26 import org.openhab.binding.sensebox.internal.dto.SenseBoxSensor;
27 import org.openhab.core.io.net.http.HttpUtil;
28 import org.openhab.core.thing.ThingStatus;
29 import org.osgi.framework.FrameworkUtil;
30 import org.osgi.framework.Version;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import com.google.gson.Gson;
35 import com.google.gson.JsonSyntaxException;
36
37 /**
38  * The {@link SenseBoxAPIConnection} is responsible for fetching data from the senseBox API server.
39  *
40  * @author Hakan Tandogan - Initial contribution
41  */
42 @NonNullByDefault
43 public class SenseBoxAPIConnection {
44
45     private final Logger logger = LoggerFactory.getLogger(SenseBoxAPIConnection.class);
46
47     private final Gson gson = new Gson();
48
49     private static final Properties HEADERS = new Properties();
50
51     private static final String METHOD = "GET";
52
53     private static final int TIMEOUT = 30 * 1000; // 30 seconds
54
55     public SenseBoxAPIConnection() {
56         Version version = FrameworkUtil.getBundle(this.getClass()).getVersion();
57         HEADERS.put("User-Agent", "openHAB / senseBox binding " + version.toString());
58         logger.trace("Headers: {}", HEADERS);
59     }
60
61     public SenseBoxData reallyFetchDataFromServer(String senseBoxId) {
62         String query = SENSEMAP_API_URL_BASE + "/boxes/" + senseBoxId;
63
64         // the caching layer does not like null values
65         SenseBoxData result = new SenseBoxData();
66
67         String body = null;
68         try {
69             body = HttpUtil.executeUrl(METHOD, query, HEADERS, null, null, TIMEOUT);
70
71             logger.trace("Fetched Data: {}", body);
72             SenseBoxData parsedData = gson.fromJson(body, SenseBoxData.class);
73
74             // Assume all is well at first
75             parsedData.setStatus(ThingStatus.ONLINE);
76
77             // Could perhaps be simplified via triply-nested arrays
78             // http://stackoverflow.com/questions/36946875/how-can-i-parse-geojson-with-gson
79             for (SenseBoxLoc loc : parsedData.getLocs()) {
80                 if (loc.getGeometry() != null) {
81                     List<Double> locationData = loc.getGeometry().getData();
82                     if (locationData != null) {
83                         int locationDataCount = locationData.size();
84                         SenseBoxLocation location = new SenseBoxLocation();
85
86                         if (locationDataCount > 0) {
87                             location.setLongitude(locationData.get(0));
88                         }
89
90                         if (locationDataCount > 1) {
91                             location.setLatitude(locationData.get(1));
92                         }
93
94                         if (locationDataCount > 2) {
95                             location.setHeight(locationData.get(2));
96                         }
97
98                         parsedData.setLocation(location);
99                     }
100                 }
101             }
102
103             for (SenseBoxSensor sensor : parsedData.getSensors()) {
104                 if ("VEML6070".equals(sensor.getSensorType())) {
105                     // "unit" is not nicely comparable, so use sensor type for now
106                     parsedData.setUvIntensity(sensor);
107                 } else if ("SDS 011".equals(sensor.getSensorType())) {
108                     // "unit" is not nicely comparable, neither is type, so use sensor title for now
109                     if ("PM2.5".equals(sensor.getTitle())) {
110                         parsedData.setParticulateMatter2dot5(sensor);
111                     } else if ("PM10".equals(sensor.getTitle())) {
112                         parsedData.setParticulateMatter10(sensor);
113                     } else {
114                         logger.debug("SDS 011 sensor title is {}", sensor.getTitle());
115                     }
116                 } else if ("lx".equals(sensor.getUnit())) {
117                     if (sensor.getLastMeasurement() != null) {
118                         if (!(INVALID_BRIGHTNESS.equals(sensor.getLastMeasurement().getValue()))) {
119                             parsedData.setLuminance(sensor);
120                         }
121                     }
122                 } else if ("Pa".equals(sensor.getUnit()) || "hPa".equals(sensor.getUnit())) {
123                     parsedData.setPressure(sensor);
124                 } else if ("%".equals(sensor.getUnit())) {
125                     parsedData.setHumidity(sensor);
126                 } else if ("°C".equals(sensor.getUnit())) {
127                     parsedData.setTemperature(sensor);
128                 } else {
129                     if (logger.isDebugEnabled()) {
130                         logger.debug("    Sensor: {}", sensor);
131                         logger.debug("    Sensor unit: {}", sensor.getUnit());
132                         logger.debug("    Sensor type: {}", sensor.getSensorType());
133                         logger.debug("    Sensor LM: {}", sensor.getLastMeasurement());
134                         if (sensor.getLastMeasurement() != null) {
135                             logger.debug("    Sensor LM value: {}", sensor.getLastMeasurement().getValue());
136                             logger.debug("    Sensor LM date: '{}'", sensor.getLastMeasurement().getCreatedAt());
137                         }
138                     }
139                 }
140             }
141
142             SenseBoxDescriptor descriptor = new SenseBoxDescriptor();
143             descriptor.setApiUrl(query);
144             String image = parsedData.getImage();
145             if (image != null && !image.isEmpty()) {
146                 descriptor.setImageUrl(SENSEMAP_IMAGE_URL_BASE + "/" + image);
147             }
148             descriptor.setMapUrl(SENSEMAP_MAP_URL_BASE + "/explore/" + senseBoxId);
149             parsedData.setDescriptor(descriptor);
150
151             logger.trace("=================================");
152
153             result = parsedData;
154         } catch (JsonSyntaxException e) {
155             logger.debug("An error occurred while parsing the data into desired class: {} / {} / {}", body,
156                     SenseBoxData.class.getName(), e.getMessage());
157             result.setStatus(ThingStatus.OFFLINE);
158         } catch (IOException e) {
159             logger.debug("IO problems while fetching data: {} / {}", query, e.getMessage());
160             result.setStatus(ThingStatus.OFFLINE);
161         }
162
163         return result;
164     }
165 }