]> git.basschouten.com Git - openhab-addons.git/blob
340ed123882c5f40e45fc6aeb65354430576a582
[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             if (parsedData != null) {
75                 // Assume all is well at first
76                 parsedData.setStatus(ThingStatus.ONLINE);
77
78                 // Could perhaps be simplified via triply-nested arrays
79                 // http://stackoverflow.com/questions/36946875/how-can-i-parse-geojson-with-gson
80                 for (SenseBoxLoc loc : parsedData.getLocs()) {
81                     if (loc.getGeometry() != null) {
82                         List<Double> locationData = loc.getGeometry().getData();
83                         if (locationData != null) {
84                             int locationDataCount = locationData.size();
85                             SenseBoxLocation location = new SenseBoxLocation();
86
87                             if (locationDataCount > 0) {
88                                 location.setLongitude(locationData.get(0));
89                             }
90
91                             if (locationDataCount > 1) {
92                                 location.setLatitude(locationData.get(1));
93                             }
94
95                             if (locationDataCount > 2) {
96                                 location.setHeight(locationData.get(2));
97                             }
98
99                             parsedData.setLocation(location);
100                         }
101                     }
102                 }
103
104                 for (SenseBoxSensor sensor : parsedData.getSensors()) {
105                     if ("VEML6070".equals(sensor.getSensorType())) {
106                         // "unit" is not nicely comparable, so use sensor type for now
107                         parsedData.setUvIntensity(sensor);
108                     } else if ("SDS 011".equals(sensor.getSensorType())) {
109                         // "unit" is not nicely comparable, neither is type, so use sensor title for now
110                         if ("PM2.5".equals(sensor.getTitle())) {
111                             parsedData.setParticulateMatter2dot5(sensor);
112                         } else if ("PM10".equals(sensor.getTitle())) {
113                             parsedData.setParticulateMatter10(sensor);
114                         } else {
115                             logger.debug("SDS 011 sensor title is {}", sensor.getTitle());
116                         }
117                     } else if ("lx".equals(sensor.getUnit())) {
118                         if (sensor.getLastMeasurement() != null) {
119                             if (!(INVALID_BRIGHTNESS.equals(sensor.getLastMeasurement().getValue()))) {
120                                 parsedData.setLuminance(sensor);
121                             }
122                         }
123                     } else if ("Pa".equals(sensor.getUnit()) || "hPa".equals(sensor.getUnit())) {
124                         parsedData.setPressure(sensor);
125                     } else if ("%".equals(sensor.getUnit())) {
126                         parsedData.setHumidity(sensor);
127                     } else if ("°C".equals(sensor.getUnit())) {
128                         parsedData.setTemperature(sensor);
129                     } else {
130                         if (logger.isDebugEnabled()) {
131                             logger.debug("    Sensor: {}", sensor);
132                             logger.debug("    Sensor unit: {}", sensor.getUnit());
133                             logger.debug("    Sensor type: {}", sensor.getSensorType());
134                             logger.debug("    Sensor LM: {}", sensor.getLastMeasurement());
135                             if (sensor.getLastMeasurement() != null) {
136                                 logger.debug("    Sensor LM value: {}", sensor.getLastMeasurement().getValue());
137                                 logger.debug("    Sensor LM date: '{}'", sensor.getLastMeasurement().getCreatedAt());
138                             }
139                         }
140                     }
141                 }
142
143                 SenseBoxDescriptor descriptor = new SenseBoxDescriptor();
144                 descriptor.setApiUrl(query);
145                 String image = parsedData.getImage();
146                 if (image != null && !image.isEmpty()) {
147                     descriptor.setImageUrl(SENSEMAP_IMAGE_URL_BASE + "/" + image);
148                 }
149                 descriptor.setMapUrl(SENSEMAP_MAP_URL_BASE + "/explore/" + senseBoxId);
150                 parsedData.setDescriptor(descriptor);
151
152                 logger.trace("=================================");
153
154                 result = parsedData;
155             } else {
156                 logger.debug("An error occurred while parsing the data into desired class: {} / {}", body,
157                         SenseBoxData.class.getName());
158                 result.setStatus(ThingStatus.OFFLINE);
159             }
160         } catch (JsonSyntaxException e) {
161             logger.debug("An error occurred while parsing the data into desired class: {} / {} / {}", body,
162                     SenseBoxData.class.getName(), e.getMessage());
163             result.setStatus(ThingStatus.OFFLINE);
164         } catch (IOException e) {
165             logger.debug("IO problems while fetching data: {} / {}", query, e.getMessage());
166             result.setStatus(ThingStatus.OFFLINE);
167         }
168         return result;
169     }
170 }