]> git.basschouten.com Git - openhab-addons.git/blob
80e8ef6cc86c1f434675d5e90422dd301a92f983
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.netatmo.internal.api.data;
14
15 import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
16 import static org.openhab.core.library.CoreItemFactory.*;
17 import static org.openhab.core.library.unit.MetricPrefix.*;
18
19 import java.net.URI;
20 import java.util.EnumSet;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.stream.Collectors;
25 import java.util.stream.Stream;
26
27 import javax.measure.Unit;
28
29 import org.eclipse.jdt.annotation.NonNullByDefault;
30 import org.openhab.core.library.unit.SIUnits;
31 import org.openhab.core.library.unit.Units;
32 import org.openhab.core.types.StateDescriptionFragment;
33 import org.openhab.core.types.StateDescriptionFragmentBuilder;
34 import org.openhab.core.types.util.UnitUtils;
35
36 import com.google.gson.annotations.SerializedName;
37
38 /**
39  * This class holds various definitions and settings provided by the Netatmo
40  * API documentation
41  *
42  * @author GaĆ«l L'hopital - Initial contribution
43  */
44 @NonNullByDefault
45 public class NetatmoConstants {
46     public static class Measure {
47         public final double minValue;
48         public final double maxValue;
49         public final int scale;
50         public final Unit<?> unit;
51
52         private Measure(double minValue, double maxValue, double precision, Unit<?> unit) {
53             this.minValue = minValue;
54             this.maxValue = maxValue;
55             this.unit = unit;
56             String[] splitter = Double.valueOf(precision).toString().split("\\.");
57             if (splitter.length > 1) {
58                 int dec = Integer.parseInt(splitter[1]);
59                 this.scale = dec > 0 ? Integer.toString(dec).length() : 0;
60             } else {
61                 this.scale = 0;
62             }
63         }
64     }
65
66     public static class MeasureChannelDetails {
67         private static final StateDescriptionFragmentBuilder BUILDER = StateDescriptionFragmentBuilder.create();
68         public final URI configURI;
69         public final String itemType;
70         public final StateDescriptionFragment stateDescriptionFragment;
71
72         private MeasureChannelDetails(String measureType, String itemType, String pattern) {
73             this.configURI = URI.create(String.join(":", BINDING_ID, measureType, "config"));
74             this.itemType = itemType;
75             this.stateDescriptionFragment = BUILDER.withReadOnly(true).withPattern(pattern).build();
76         }
77     }
78
79     public enum MeasureClass {
80         INSIDE_TEMPERATURE(0, 50, 0.3, SIUnits.CELSIUS, "temp", "measure", true),
81         OUTSIDE_TEMPERATURE(-40, 65, 0.3, SIUnits.CELSIUS, "temp", "measure", true),
82         HEAT_INDEX(-40, 65, 1, SIUnits.CELSIUS, "", "", false),
83         PRESSURE(260, 1260, 1, HECTO(SIUnits.PASCAL), "pressure", "measure", true),
84         CO2(0, 5000, 50, Units.PARTS_PER_MILLION, "co2", "measure", true),
85         NOISE(35, 120, 1, Units.DECIBEL, "noise", "measure", true),
86         RAIN_QUANTITY(0, 150, 0.1, MILLI(SIUnits.METRE), "sum_rain", "sum_rain", false),
87         RAIN_INTENSITY(0, 150, 0.1, Units.MILLIMETRE_PER_HOUR, "", "", false),
88         WIND_SPEED(0, 160, 1.8, SIUnits.KILOMETRE_PER_HOUR, "", "", false),
89         WIND_ANGLE(0, 360, 5, Units.DEGREE_ANGLE, "", "", false),
90         HUMIDITY(0, 100, 3, Units.PERCENT, "hum", "measure", true);
91
92         public static final EnumSet<MeasureClass> AS_SET = EnumSet.allOf(MeasureClass.class);
93
94         public final Measure measureDefinition;
95         public final String apiDescriptor;
96         public final Map<String, MeasureChannelDetails> channels = new HashMap<>(2);
97
98         MeasureClass(double min, double max, double precision, Unit<?> unit, String apiDescriptor, String confFragment,
99                 boolean canScale) {
100             this.measureDefinition = new Measure(min, max, precision, unit);
101             this.apiDescriptor = apiDescriptor;
102             if (!apiDescriptor.isBlank()) {
103                 String dimension = UnitUtils.getDimensionName(unit);
104
105                 channels.put(String.join("-", apiDescriptor, "measurement"),
106                         new MeasureChannelDetails(confFragment, String.join(":", NUMBER, dimension),
107                                 String.format("%%.%df %s", measureDefinition.scale, UnitUtils.UNIT_PLACEHOLDER)));
108                 if (canScale) {
109                     channels.put(String.join("-", apiDescriptor, GROUP_TIMESTAMP),
110                             new MeasureChannelDetails(GROUP_TIMESTAMP, DATETIME, "%1$tA, %1$td.%1$tm. %1$tH:%1$tM"));
111                 }
112             }
113         }
114     }
115
116     // Netatmo API urls
117     public static final String URL_API = "https://api.netatmo.com/";
118     public static final String URL_APP = "https://app.netatmo.net/";
119     public static final String PATH_OAUTH = "oauth2";
120     public static final String SUB_PATH_TOKEN = "token";
121     public static final String SUB_PATH_AUTHORIZE = "authorize";
122     public static final String PATH_API = "api";
123     public static final String PATH_COMMAND = "command";
124     public static final String PATH_STATE = "setstate";
125     public static final String SUB_PATH_PERSON_AWAY = "setpersonsaway";
126     public static final String SUB_PATH_PERSON_HOME = "setpersonshome";
127     public static final String SUB_PATH_HOMES_DATA = "homesdata";
128     public static final String SUB_PATH_ADD_WEBHOOK = "addwebhook";
129     public static final String SUB_PATH_DROP_WEBHOOK = "dropwebhook";
130     public static final String SUB_PATH_SET_ROOM_THERMPOINT = "setroomthermpoint";
131     public static final String SUB_PATH_SET_THERM_MODE = "setthermmode";
132     public static final String SUB_PATH_SWITCH_SCHEDULE = "switchschedule";
133     public static final String SUB_PATH_GET_STATION = "getstationsdata";
134     public static final String SUB_PATH_GET_MEASURE = "getmeasure";
135     public static final String SUB_PATH_HOMESTATUS = "homestatus";
136     public static final String SUB_PATH_HOMECOACH = "gethomecoachsdata";
137     public static final String SUB_PATH_GET_EVENTS = "getevents";
138     public static final String SUB_PATH_PING = "ping";
139     public static final String SUB_PATH_CHANGESTATUS = "changestatus";
140     public static final String PARAM_DEVICE_ID = "device_id";
141     public static final String PARAM_MODULE_ID = "module_id";
142     public static final String PARAM_HOME_ID = "home_id";
143     public static final String PARAM_ROOM_ID = "room_id";
144     public static final String PARAM_PERSON_ID = "person_id";
145     public static final String PARAM_SCHEDULE_ID = "schedule_id";
146     public static final String PARAM_OFFSET = "offset";
147     public static final String PARAM_GATEWAY_TYPE = "gateway_types";
148     public static final String PARAM_MODE = "mode";
149     public static final String PARAM_URL = "url";
150     public static final String PARAM_FAVORITES = "get_favorites";
151     public static final String PARAM_STATUS = "status";
152     public static final String PARAM_DEVICES_TYPE = "device_types";
153
154     // Autentication process params
155     public static final String PARAM_ERROR = "error";
156
157     // Global variables
158     public static final int THERM_MAX_SETPOINT = 30;
159
160     // Token scopes
161     public static enum Scope {
162         @SerializedName("read_station")
163         READ_STATION,
164         @SerializedName("read_thermostat")
165         READ_THERMOSTAT,
166         @SerializedName("write_thermostat")
167         WRITE_THERMOSTAT,
168         @SerializedName("read_camera")
169         READ_CAMERA,
170         @SerializedName("write_camera")
171         WRITE_CAMERA,
172         @SerializedName("access_camera")
173         ACCESS_CAMERA,
174         @SerializedName("read_presence")
175         READ_PRESENCE,
176         @SerializedName("write_presence")
177         WRITE_PRESENCE,
178         @SerializedName("access_presence")
179         ACCESS_PRESENCE,
180         @SerializedName("read_smokedetector")
181         READ_SMOKEDETECTOR,
182         @SerializedName("read_homecoach")
183         READ_HOMECOACH,
184         @SerializedName("read_doorbell")
185         READ_DOORBELL,
186         @SerializedName("write_doorbell")
187         WRITE_DOORBELL,
188         @SerializedName("access_doorbell")
189         ACCESS_DOORBELL,
190         UNKNOWN;
191     }
192
193     private static final Set<Scope> SMOKE = Set.of(Scope.READ_SMOKEDETECTOR);
194     private static final Set<Scope> WELCOME = Set.of(Scope.READ_CAMERA, Scope.WRITE_CAMERA, Scope.ACCESS_CAMERA);
195     private static final Set<Scope> DOORBELL = Set.of(Scope.READ_DOORBELL, Scope.WRITE_DOORBELL, Scope.ACCESS_DOORBELL);
196     private static final Set<Scope> PRESENCE = Set.of(Scope.READ_PRESENCE, Scope.WRITE_PRESENCE, Scope.ACCESS_PRESENCE);
197
198     // Radio signal quality thresholds
199     static final int[] WIFI_SIGNAL_LEVELS = new int[] { 99, 84, 69, 54 }; // Resp : bad, average, good, full
200     static final int[] RADIO_SIGNAL_LEVELS = new int[] { 90, 80, 70, 60 }; // Resp : low, medium, high, full
201
202     public static enum FeatureArea {
203         AIR_CARE(Scope.READ_HOMECOACH),
204         WEATHER(Scope.READ_STATION),
205         ENERGY(Scope.READ_THERMOSTAT, Scope.WRITE_THERMOSTAT),
206         SECURITY(Stream.of(WELCOME, PRESENCE, SMOKE, DOORBELL).flatMap(Set::stream).toArray(Scope[]::new)),
207         NONE();
208
209         public static final Set<FeatureArea> AS_SET = EnumSet.allOf(FeatureArea.class);
210
211         public static String toScopeString(Set<FeatureArea> featureSet) {
212             return featureSet.stream().map(fa -> fa.scopes).flatMap(Set::stream).map(s -> s.name().toLowerCase())
213                     .collect(Collectors.joining(" "));
214         }
215
216         public final Set<Scope> scopes;
217
218         FeatureArea(Scope... scopes) {
219             this.scopes = Set.of(scopes);
220         }
221     }
222
223     // Thermostat definitions
224     public static enum SetpointMode {
225         @SerializedName("program")
226         PROGRAM("program"),
227         @SerializedName("away")
228         AWAY("away"),
229         @SerializedName("hg")
230         FROST_GUARD("hg"),
231         @SerializedName("manual")
232         MANUAL("manual"),
233         @SerializedName("off")
234         OFF("off"),
235         @SerializedName("max")
236         MAX("max"),
237         @SerializedName("schedule")
238         SCHEDULE("schedule"),
239         HOME("home"),
240         UNKNOWN("");
241
242         public final String apiDescriptor;
243
244         SetpointMode(String descriptor) {
245             this.apiDescriptor = descriptor;
246         }
247     }
248
249     public static enum ThermostatZoneType {
250         @SerializedName("0")
251         DAY("0"),
252         @SerializedName("1")
253         NIGHT("1"),
254         @SerializedName("2")
255         AWAY("2"),
256         @SerializedName("3")
257         FROST_GUARD("3"),
258         @SerializedName("4")
259         CUSTOM("4"),
260         @SerializedName("5")
261         ECO("5"),
262         @SerializedName("8")
263         COMFORT("8"),
264         UNKNOWN("");
265
266         public final String zoneId;
267
268         private ThermostatZoneType(String id) {
269             zoneId = id;
270         }
271     }
272
273     public enum FloodLightMode {
274         @SerializedName("on")
275         ON,
276         @SerializedName("off")
277         OFF,
278         @SerializedName("auto")
279         AUTO,
280         UNKNOWN;
281     }
282
283     public enum EventCategory {
284         @SerializedName("human")
285         HUMAN,
286         @SerializedName("animal")
287         ANIMAL,
288         @SerializedName("vehicle")
289         VEHICLE,
290         UNKNOWN;
291     }
292
293     public enum TrendDescription {
294         @SerializedName("up")
295         UP,
296         @SerializedName("stable")
297         STABLE,
298         @SerializedName("down")
299         DOWN,
300         UNKNOWN;
301     }
302
303     public enum VideoStatus {
304         @SerializedName("recording")
305         RECORDING,
306         @SerializedName("available")
307         AVAILABLE,
308         @SerializedName("deleted")
309         DELETED,
310         UNKNOWN;
311     }
312
313     public enum SdCardStatus {
314         @SerializedName("1")
315         SD_CARD_MISSING,
316         @SerializedName("2")
317         SD_CARD_INSERTED,
318         @SerializedName("3")
319         SD_CARD_FORMATTED,
320         @SerializedName("4")
321         SD_CARD_WORKING,
322         @SerializedName("5")
323         SD_CARD_DEFECTIVE,
324         @SerializedName("6")
325         SD_CARD_INCOMPATIBLE_SPEED,
326         @SerializedName("7")
327         SD_CARD_INSUFFICIENT_SPACE,
328         UNKNOWN;
329     }
330
331     public enum AlimentationStatus {
332         @SerializedName("1")
333         ALIM_INCORRECT_POWER,
334         @SerializedName("2")
335         ALIM_CORRECT_POWER,
336         UNKNOWN;
337     }
338
339     public enum BatteryState {
340         @SerializedName("full")
341         FULL(100),
342         @SerializedName("high")
343         HIGH(80),
344         @SerializedName("medium")
345         MEDIUM(50),
346         @SerializedName("low")
347         LOW(15),
348         UNKNOWN(-1);
349
350         public final int level;
351
352         BatteryState(int i) {
353             this.level = i;
354         }
355     }
356
357     public enum ServiceError {
358         @SerializedName("99")
359         UNKNOWN,
360         @SerializedName("-2")
361         UNKNOWN_ERROR_IN_OAUTH,
362         @SerializedName("-1")
363         GRANT_IS_INVALID,
364         @SerializedName("1")
365         ACCESS_TOKEN_MISSING,
366         @SerializedName("2")
367         INVALID_TOKEN_MISSING,
368         @SerializedName("3")
369         ACCESS_TOKEN_EXPIRED,
370         @SerializedName("5")
371         APPLICATION_DEACTIVATED,
372         @SerializedName("7")
373         NOTHING_TO_MODIFY,
374         @SerializedName("9")
375         DEVICE_NOT_FOUND,
376         @SerializedName("10")
377         MISSING_ARGUMENTS,
378         @SerializedName("13")
379         OPERATION_FORBIDDEN,
380         @SerializedName("19")
381         IP_NOT_FOUND,
382         @SerializedName("21")
383         INVALID_ARGUMENT,
384         @SerializedName("22")
385         APPLICATION_NOT_FOUND,
386         @SerializedName("23")
387         USER_NOT_FOUND,
388         @SerializedName("25")
389         INVALID_DATE,
390         @SerializedName("26")
391         MAXIMUM_USAGE_REACHED,
392         @SerializedName("30")
393         INVALID_REFRESH_TOKEN,
394         @SerializedName("31")
395         METHOD_NOT_FOUND,
396         @SerializedName("35")
397         UNABLE_TO_EXECUTE,
398         @SerializedName("36")
399         PROHIBITED_STRING,
400         @SerializedName("37")
401         NO_MORE_SPACE_AVAILABLE_ON_THE_CAMERA,
402         @SerializedName("40")
403         JSON_GIVEN_HAS_AN_INVALID_ENCODING,
404         @SerializedName("41")
405         DEVICE_IS_UNREACHABLE;
406     }
407 }