2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.sensorcommunity.internal.handler;
15 import static org.openhab.binding.sensorcommunity.internal.utils.Constants.*;
17 import java.time.LocalDateTime;
18 import java.util.List;
19 import java.util.Objects;
20 import java.util.concurrent.TimeUnit;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.eclipse.jetty.client.HttpClient;
25 import org.eclipse.jetty.client.api.Request;
26 import org.eclipse.jetty.client.util.BufferingResponseListener;
27 import org.openhab.binding.sensorcommunity.internal.dto.SensorData;
28 import org.openhab.binding.sensorcommunity.internal.dto.SensorDataValue;
29 import org.openhab.binding.sensorcommunity.internal.utils.DateTimeUtils;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import com.google.gson.Gson;
36 * The {@link HTTPHandler} is responsible for HTTP requests and JSON handling
38 * @author Bernd Weymann - Initial contribution
41 public class HTTPHandler {
42 private final Logger logger = LoggerFactory.getLogger(HTTPHandler.class);
44 private static final Gson GSON = new Gson();
45 private static final HTTPHandler HTTP_HANDLER = new HTTPHandler();
47 private static @Nullable HttpClient commonHttpClient;
49 public static void init(HttpClient httpClient) {
50 commonHttpClient = httpClient;
53 public static HTTPHandler getHandler() {
57 public synchronized void request(String url, BaseSensorHandler callback) {
58 HttpClient localClient = commonHttpClient;
59 if (localClient == null) {
60 logger.warn("HTTP Client not initialized");
62 Request req = localClient.newRequest(url);
63 req.timeout(15, TimeUnit.SECONDS).send(new BufferingResponseListener() {
66 public void onComplete(org.eclipse.jetty.client.api.Result result) {
67 if (result.getResponse().getStatus() != 200) {
69 if (result.getResponse().getReason() != null) {
70 failure = result.getResponse().getReason();
72 failure = result.getFailure().getMessage();
74 callback.onError(Objects.requireNonNullElse(failure, "Unknown error"));
76 callback.onResponse(getContentAsString());
83 public @Nullable List<SensorDataValue> getLatestValues(String response) {
84 SensorData[] valueArray = GSON.fromJson(response, SensorData[].class);
85 if (valueArray.length == 0) {
87 } else if (valueArray.length == 1) {
88 SensorData v = valueArray[0];
89 return v.getSensorDataValues();
90 } else if (valueArray.length > 1) {
91 // declare first item as latest
92 SensorData latestData = valueArray[0];
93 String latestTimeStr = latestData.getTimeStamp();
94 LocalDateTime latestTime = DateTimeUtils.toDate(latestTimeStr);
95 if (latestTime == null) {
96 logDateConversionError(response, latestData);
98 for (int i = 1; i < valueArray.length; i++) {
99 SensorData iterData = valueArray[i];
100 String iterTimeStr = iterData.getTimeStamp();
101 LocalDateTime iterTime = DateTimeUtils.toDate(iterTimeStr);
102 if (iterTime == null) {
103 logDateConversionError(response, latestData);
105 if (iterTime != null && latestTime != null) {
106 if (latestTime.isBefore(iterTime)) {
107 // found item is newer - take it as latest
108 latestTime = iterTime;
109 latestData = iterData;
110 } // else - found item is older - nothing to do
112 logger.warn("One or two dates cannot be decoded 1) {} 2) {}", iterTimeStr, latestTimeStr);
115 return latestData.getSensorDataValues();
121 public void logDateConversionError(final String response, final Object dto) {
122 logger.warn("Unable to get timestamp");
123 logger.warn("Response: {}", response);
124 String json = GSON.toJson(dto);
125 logger.warn("GSon: {}", json);
128 public boolean isParticulate(@Nullable List<SensorDataValue> valueList) {
129 if (valueList == null) {
132 return valueList.stream().map(v -> v.getValueType()).filter(t -> t.endsWith(P1) || t.endsWith(P2)).findAny()
136 public boolean isCondition(@Nullable List<SensorDataValue> valueList) {
137 if (valueList == null) {
140 return valueList.stream().map(v -> v.getValueType()).filter(t -> t.equals(TEMPERATURE) || t.endsWith(HUMIDITY)
141 || t.endsWith(PRESSURE) || t.endsWith(PRESSURE_SEALEVEL)).findAny().isPresent();
144 public boolean isNoise(@Nullable List<SensorDataValue> valueList) {
145 if (valueList == null) {
148 return valueList.stream().map(v -> v.getValueType())
149 .filter(t -> t.endsWith(NOISE_EQ) || t.endsWith(NOISE_MAX) || t.endsWith(NOISE_MIN)).findAny()