2 * Copyright (c) 2010-2024 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"));
77 callback.onResponse(Objects.requireNonNull(getContentAsString()));
84 public @Nullable List<SensorDataValue> getLatestValues(String response) {
85 SensorData[] valueArray = GSON.fromJson(response, SensorData[].class);
86 if (valueArray.length == 0) {
88 } else if (valueArray.length == 1) {
89 SensorData v = valueArray[0];
90 return v.getSensorDataValues();
91 } else if (valueArray.length > 1) {
92 // declare first item as latest
93 SensorData latestData = valueArray[0];
94 String latestTimeStr = latestData.getTimeStamp();
95 LocalDateTime latestTime = DateTimeUtils.toDate(latestTimeStr);
96 if (latestTime == null) {
97 logDateConversionError(response, latestData);
99 for (int i = 1; i < valueArray.length; i++) {
100 SensorData iterData = valueArray[i];
101 String iterTimeStr = iterData.getTimeStamp();
102 LocalDateTime iterTime = DateTimeUtils.toDate(iterTimeStr);
103 if (iterTime == null) {
104 logDateConversionError(response, latestData);
106 if (iterTime != null && latestTime != null) {
107 if (latestTime.isBefore(iterTime)) {
108 // found item is newer - take it as latest
109 latestTime = iterTime;
110 latestData = iterData;
111 } // else - found item is older - nothing to do
113 logger.warn("One or two dates cannot be decoded 1) {} 2) {}", iterTimeStr, latestTimeStr);
116 return latestData.getSensorDataValues();
122 public void logDateConversionError(final String response, final Object dto) {
123 logger.warn("Unable to get timestamp");
124 logger.warn("Response: {}", response);
125 String json = GSON.toJson(dto);
126 logger.warn("GSon: {}", json);
129 public boolean isParticulate(@Nullable List<SensorDataValue> valueList) {
130 if (valueList == null) {
133 return valueList.stream().map(v -> v.getValueType()).filter(t -> t.endsWith(P1) || t.endsWith(P2)).findAny()
137 public boolean isCondition(@Nullable List<SensorDataValue> valueList) {
138 if (valueList == null) {
141 return valueList.stream().map(v -> v.getValueType()).filter(t -> t.equals(TEMPERATURE) || t.endsWith(HUMIDITY)
142 || t.endsWith(PRESSURE) || t.endsWith(PRESSURE_SEALEVEL)).findAny().isPresent();
145 public boolean isNoise(@Nullable List<SensorDataValue> valueList) {
146 if (valueList == null) {
149 return valueList.stream().map(v -> v.getValueType())
150 .filter(t -> t.endsWith(NOISE_EQ) || t.endsWith(NOISE_MAX) || t.endsWith(NOISE_MIN)).findAny()