2 * Copyright (c) 2010-2022 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.netatmo.internal.api;
15 import static org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.*;
17 import java.time.ZonedDateTime;
18 import java.util.Collection;
19 import java.util.List;
21 import javax.ws.rs.core.UriBuilder;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
26 import org.openhab.binding.netatmo.internal.api.dto.MeasureBodyElem;
27 import org.openhab.binding.netatmo.internal.api.dto.NAMain;
28 import org.openhab.binding.netatmo.internal.api.dto.NAMain.StationDataResponse;
29 import org.openhab.binding.netatmo.internal.handler.ApiBridgeHandler;
32 * Base class for all Weather related endpoints
34 * @author Gaƫl L'hopital - Initial contribution
37 public class WeatherApi extends RestManager {
38 private class NAMeasuresResponse extends ApiResponse<List<MeasureBodyElem<Double>>> {
41 private class NADateMeasuresResponse extends ApiResponse<List<MeasureBodyElem<ZonedDateTime>>> {
44 public WeatherApi(ApiBridgeHandler apiClient) {
45 super(apiClient, FeatureArea.WEATHER);
49 * Returns data from a user's Weather Stations (measures and device specific data);
51 * @param deviceId Id of the device you want to retrieve information of (optional)
52 * @param getFavorites Whether to include the user's favorite Weather Stations in addition to the user's
53 * own Weather Stations
54 * @return StationDataResponse
55 * @throws NetatmoException If fail to call the API, e.g. server error or deserializing
57 private StationDataResponse getStationsData(@Nullable String deviceId, boolean getFavorites)
58 throws NetatmoException {
59 UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_STATION, PARAM_DEVICE_ID, deviceId, //
60 PARAM_FAVORITES, getFavorites);
61 StationDataResponse response = get(uriBuilder, StationDataResponse.class);
66 * Returns data from a user's Weather Station, this stations can be a station owned by the user or a favorite
67 * station or a guest station.
69 * @param deviceId Id of the device you want to retrieve information
71 * @throws NetatmoException If fail to call the API, e.g. server error or deserializing
73 public NAMain getStationData(String deviceId) throws NetatmoException {
74 ListBodyResponse<NAMain> answer = getStationsData(deviceId, true).getBody();
76 NAMain station = answer.getElement(deviceId);
77 if (station != null) {
81 throw new NetatmoException("Unexpected answer searching device '%s' : not found.", deviceId);
85 * Returns data from a Weather Station owned by the user
87 * This method must be preferred to getStationData when you know that the device is a station owned by the user
88 * (because it avoids requesting additional data for favorite/guest stations).
90 * @param deviceId Id of the device you want to retrieve information
92 * @throws NetatmoException If fail to call the API, e.g. server error or deserializing
94 public NAMain getOwnedStationData(String deviceId) throws NetatmoException {
95 ListBodyResponse<NAMain> answer = getStationsData(deviceId, false).getBody();
97 NAMain station = answer.getElement(deviceId);
98 if (station != null) {
102 throw new NetatmoException("Unexpected answer searching device '%s' : not found.", deviceId);
105 public Collection<NAMain> getFavoriteAndGuestStationsData() throws NetatmoException {
106 ListBodyResponse<NAMain> answer = getStationsData(null, true).getBody();
107 return answer != null ? answer.getElements() : List.of();
110 public @Nullable Object getMeasures(String deviceId, @Nullable String moduleId, @Nullable String scale,
111 String apiDescriptor) throws NetatmoException {
112 MeasureBodyElem<?> result = getMeasure(deviceId, moduleId, scale, apiDescriptor);
113 return result.getSingleValue();
116 public @Nullable Object getMeasures(String deviceId, @Nullable String moduleId, @Nullable String scale,
117 String apiDescriptor, String limit) throws NetatmoException {
118 String queryLimit = limit;
119 if (!apiDescriptor.contains("_")) {
120 queryLimit += "_" + apiDescriptor;
123 MeasureBodyElem<?> result = getMeasure(deviceId, moduleId, scale, queryLimit.toLowerCase());
124 return result.getSingleValue();
127 private MeasureBodyElem<?> getMeasure(String deviceId, @Nullable String moduleId, @Nullable String scale,
128 String measureType) throws NetatmoException {
129 // NAMeasuresResponse is not designed for optimize=false
130 UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_MEASURE, PARAM_DEVICE_ID, deviceId, "real_time", true,
131 "date_end", "last", "optimize", true, "type", measureType.toLowerCase(), PARAM_MODULE_ID, moduleId);
134 uriBuilder.queryParam("scale", scale.toLowerCase());
136 if (measureType.startsWith("date")) {
137 NADateMeasuresResponse response = get(uriBuilder, NADateMeasuresResponse.class);
138 List<MeasureBodyElem<ZonedDateTime>> body = response.getBody();
139 if (body != null && !body.isEmpty()) {
143 NAMeasuresResponse response = get(uriBuilder, NAMeasuresResponse.class);
144 List<MeasureBodyElem<Double>> body = response.getBody();
145 if (body != null && !body.isEmpty()) {
149 throw new NetatmoException("Empty response while getting measurements");