]> git.basschouten.com Git - openhab-addons.git/blob
bf9d1c6ac1ed8cd16addafdd8ae0f69a963e569f
[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.station;
14
15 import static org.openhab.binding.netatmo.internal.APIUtils.*;
16 import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
17 import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Optional;
23 import java.util.concurrent.ConcurrentHashMap;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.openhab.binding.netatmo.internal.WeatherUtils;
27 import org.openhab.binding.netatmo.internal.handler.NetatmoDeviceHandler;
28 import org.openhab.binding.netatmo.internal.handler.NetatmoModuleHandler;
29 import org.openhab.core.i18n.TimeZoneProvider;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.types.State;
32
33 import io.swagger.client.model.NADashboardData;
34 import io.swagger.client.model.NAMain;
35
36 /**
37  * {@link NAMainHandler} is the base class for all current Netatmo
38  * weather station equipments (both modules and devices)
39  *
40  * @author GaĆ«l L'hopital - Initial contribution
41  * @author Rob Nielsen - Added day, week, and month measurements to the weather station and modules
42  *
43  */
44 @NonNullByDefault
45 public class NAMainHandler extends NetatmoDeviceHandler<NAMain> {
46     private Map<String, Float> channelMeasurements = new ConcurrentHashMap<>();
47
48     public NAMainHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
49         super(thing, timeZoneProvider);
50     }
51
52     @Override
53     protected Optional<NAMain> updateReadings() {
54         Optional<NAMain> result = getBridgeHandler().flatMap(handler -> handler.getStationsDataBody(getId()))
55                 .map(dataBody -> nonNullStream(dataBody.getDevices())
56                         .filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
57         result.ifPresent(device -> {
58             nonNullList(device.getModules()).forEach(child -> childs.put(child.getId(), child));
59         });
60
61         updateMeasurements();
62
63         childs.keySet().forEach((childId) -> {
64             findNAThing(childId).map(NetatmoModuleHandler.class::cast).ifPresent(naChildModule -> {
65                 naChildModule.updateMeasurements();
66             });
67         });
68
69         return result;
70     }
71
72     @Override
73     protected void updateProperties(NAMain deviceData) {
74         updateProperties(deviceData.getFirmware(), deviceData.getType());
75     }
76
77     @Override
78     public void updateMeasurements() {
79         updateDayMeasurements();
80         updateWeekMeasurements();
81         updateMonthMeasurements();
82     }
83
84     private void updateDayMeasurements() {
85         List<String> channels = new ArrayList<>();
86         List<String> types = new ArrayList<>();
87         addMeasurement(channels, types, CHANNEL_MIN_CO2, MIN_CO2);
88         addMeasurement(channels, types, CHANNEL_MAX_CO2, MAX_CO2);
89         addMeasurement(channels, types, CHANNEL_MIN_HUMIDITY, MIN_HUM);
90         addMeasurement(channels, types, CHANNEL_MAX_HUMIDITY, MAX_HUM);
91         addMeasurement(channels, types, CHANNEL_MIN_NOISE, MIN_NOISE);
92         addMeasurement(channels, types, CHANNEL_MAX_NOISE, MAX_NOISE);
93         addMeasurement(channels, types, CHANNEL_MIN_PRESSURE, MIN_PRESSURE);
94         addMeasurement(channels, types, CHANNEL_MAX_PRESSURE, MAX_PRESSURE);
95         addMeasurement(channels, types, CHANNEL_DATE_MIN_CO2, DATE_MIN_CO2);
96         addMeasurement(channels, types, CHANNEL_DATE_MAX_CO2, DATE_MAX_CO2);
97         addMeasurement(channels, types, CHANNEL_DATE_MIN_HUMIDITY, DATE_MIN_HUM);
98         addMeasurement(channels, types, CHANNEL_DATE_MAX_HUMIDITY, DATE_MAX_HUM);
99         addMeasurement(channels, types, CHANNEL_DATE_MIN_NOISE, DATE_MIN_NOISE);
100         addMeasurement(channels, types, CHANNEL_DATE_MAX_NOISE, DATE_MAX_NOISE);
101         addMeasurement(channels, types, CHANNEL_DATE_MIN_PRESSURE, DATE_MIN_PRESSURE);
102         addMeasurement(channels, types, CHANNEL_DATE_MAX_PRESSURE, DATE_MAX_PRESSURE);
103         if (!channels.isEmpty()) {
104             getMeasurements(getId(), null, ONE_DAY, types, channels, channelMeasurements);
105         }
106     }
107
108     private void updateWeekMeasurements() {
109         List<String> channels = new ArrayList<>();
110         List<String> types = new ArrayList<>();
111         addMeasurement(channels, types, CHANNEL_MIN_CO2_THIS_WEEK, MIN_CO2);
112         addMeasurement(channels, types, CHANNEL_MAX_CO2_THIS_WEEK, MAX_CO2);
113         addMeasurement(channels, types, CHANNEL_MIN_HUMIDITY_THIS_WEEK, MIN_HUM);
114         addMeasurement(channels, types, CHANNEL_MAX_HUMIDITY_THIS_WEEK, MAX_HUM);
115         addMeasurement(channels, types, CHANNEL_MIN_NOISE_THIS_WEEK, MIN_NOISE);
116         addMeasurement(channels, types, CHANNEL_MAX_NOISE_THIS_WEEK, MAX_NOISE);
117         addMeasurement(channels, types, CHANNEL_MIN_PRESSURE_THIS_WEEK, MIN_PRESSURE);
118         addMeasurement(channels, types, CHANNEL_MAX_PRESSURE_THIS_WEEK, MAX_PRESSURE);
119         addMeasurement(channels, types, CHANNEL_MIN_TEMP_THIS_WEEK, MIN_TEMP);
120         addMeasurement(channels, types, CHANNEL_MAX_TEMP_THIS_WEEK, MAX_TEMP);
121         addMeasurement(channels, types, CHANNEL_DATE_MIN_CO2_THIS_WEEK, DATE_MIN_CO2);
122         addMeasurement(channels, types, CHANNEL_DATE_MAX_CO2_THIS_WEEK, DATE_MAX_CO2);
123         addMeasurement(channels, types, CHANNEL_DATE_MIN_HUMIDITY_THIS_WEEK, DATE_MIN_HUM);
124         addMeasurement(channels, types, CHANNEL_DATE_MAX_HUMIDITY_THIS_WEEK, DATE_MAX_HUM);
125         addMeasurement(channels, types, CHANNEL_DATE_MIN_NOISE_THIS_WEEK, DATE_MIN_NOISE);
126         addMeasurement(channels, types, CHANNEL_DATE_MAX_NOISE_THIS_WEEK, DATE_MAX_NOISE);
127         addMeasurement(channels, types, CHANNEL_DATE_MIN_PRESSURE_THIS_WEEK, DATE_MIN_PRESSURE);
128         addMeasurement(channels, types, CHANNEL_DATE_MAX_PRESSURE_THIS_WEEK, DATE_MAX_PRESSURE);
129         addMeasurement(channels, types, CHANNEL_DATE_MIN_TEMP_THIS_WEEK, DATE_MIN_TEMP);
130         addMeasurement(channels, types, CHANNEL_DATE_MAX_TEMP_THIS_WEEK, DATE_MAX_TEMP);
131         if (!channels.isEmpty()) {
132             getMeasurements(getId(), null, ONE_WEEK, types, channels, channelMeasurements);
133         }
134     }
135
136     private void updateMonthMeasurements() {
137         List<String> channels = new ArrayList<>();
138         List<String> types = new ArrayList<>();
139         addMeasurement(channels, types, CHANNEL_MIN_CO2_THIS_MONTH, MIN_CO2);
140         addMeasurement(channels, types, CHANNEL_MAX_CO2_THIS_MONTH, MAX_CO2);
141         addMeasurement(channels, types, CHANNEL_MIN_HUMIDITY_THIS_MONTH, MIN_HUM);
142         addMeasurement(channels, types, CHANNEL_MAX_HUMIDITY_THIS_MONTH, MAX_HUM);
143         addMeasurement(channels, types, CHANNEL_MIN_NOISE_THIS_MONTH, MIN_NOISE);
144         addMeasurement(channels, types, CHANNEL_MAX_NOISE_THIS_MONTH, MAX_NOISE);
145         addMeasurement(channels, types, CHANNEL_MIN_PRESSURE_THIS_MONTH, MIN_PRESSURE);
146         addMeasurement(channels, types, CHANNEL_MAX_PRESSURE_THIS_MONTH, MAX_PRESSURE);
147         addMeasurement(channels, types, CHANNEL_MIN_TEMP_THIS_MONTH, MIN_TEMP);
148         addMeasurement(channels, types, CHANNEL_MAX_TEMP_THIS_MONTH, MAX_TEMP);
149         addMeasurement(channels, types, CHANNEL_DATE_MIN_CO2_THIS_MONTH, DATE_MIN_CO2);
150         addMeasurement(channels, types, CHANNEL_DATE_MAX_CO2_THIS_MONTH, DATE_MAX_CO2);
151         addMeasurement(channels, types, CHANNEL_DATE_MIN_HUMIDITY_THIS_MONTH, DATE_MIN_HUM);
152         addMeasurement(channels, types, CHANNEL_DATE_MAX_HUMIDITY_THIS_MONTH, DATE_MAX_HUM);
153         addMeasurement(channels, types, CHANNEL_DATE_MIN_NOISE_THIS_MONTH, DATE_MIN_NOISE);
154         addMeasurement(channels, types, CHANNEL_DATE_MAX_NOISE_THIS_MONTH, DATE_MAX_NOISE);
155         addMeasurement(channels, types, CHANNEL_DATE_MIN_PRESSURE_THIS_MONTH, DATE_MIN_PRESSURE);
156         addMeasurement(channels, types, CHANNEL_DATE_MAX_PRESSURE_THIS_MONTH, DATE_MAX_PRESSURE);
157         addMeasurement(channels, types, CHANNEL_DATE_MIN_TEMP_THIS_MONTH, DATE_MIN_TEMP);
158         addMeasurement(channels, types, CHANNEL_DATE_MAX_TEMP_THIS_MONTH, DATE_MAX_TEMP);
159         if (!channels.isEmpty()) {
160             getMeasurements(getId(), null, ONE_MONTH, types, channels, channelMeasurements);
161         }
162     }
163
164     @Override
165     protected State getNAThingProperty(String channelId) {
166         NADashboardData dashboardData = getDevice().map(d -> d.getDashboardData()).orElse(null);
167         if (dashboardData != null) {
168             switch (channelId) {
169                 case CHANNEL_CO2:
170                     return toQuantityType(dashboardData.getCo2(), API_CO2_UNIT);
171                 case CHANNEL_TEMPERATURE:
172                     return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
173                 case CHANNEL_MIN_TEMP:
174                     return toQuantityType(dashboardData.getMinTemp(), API_TEMPERATURE_UNIT);
175                 case CHANNEL_MAX_TEMP:
176                     return toQuantityType(dashboardData.getMaxTemp(), API_TEMPERATURE_UNIT);
177                 case CHANNEL_TEMP_TREND:
178                     return toStringType(dashboardData.getTempTrend());
179                 case CHANNEL_NOISE:
180                     return toQuantityType(dashboardData.getNoise(), API_NOISE_UNIT);
181                 case CHANNEL_PRESSURE:
182                     return toQuantityType(dashboardData.getPressure(), API_PRESSURE_UNIT);
183                 case CHANNEL_PRESS_TREND:
184                     return toStringType(dashboardData.getPressureTrend());
185                 case CHANNEL_ABSOLUTE_PRESSURE:
186                     return toQuantityType(dashboardData.getAbsolutePressure(), API_PRESSURE_UNIT);
187                 case CHANNEL_TIMEUTC:
188                     return toDateTimeType(dashboardData.getTimeUtc(), timeZoneProvider.getTimeZone());
189                 case CHANNEL_DATE_MIN_TEMP:
190                     return toDateTimeType(dashboardData.getDateMinTemp(), timeZoneProvider.getTimeZone());
191                 case CHANNEL_DATE_MAX_TEMP:
192                     return toDateTimeType(dashboardData.getDateMaxTemp(), timeZoneProvider.getTimeZone());
193                 case CHANNEL_HUMIDITY:
194                     return toQuantityType(dashboardData.getHumidity(), API_HUMIDITY_UNIT);
195                 case CHANNEL_HUMIDEX:
196                     return toDecimalType(
197                             WeatherUtils.getHumidex(dashboardData.getTemperature(), dashboardData.getHumidity()));
198                 case CHANNEL_HEATINDEX:
199                     return toQuantityType(
200                             WeatherUtils.getHeatIndex(dashboardData.getTemperature(), dashboardData.getHumidity()),
201                             API_TEMPERATURE_UNIT);
202                 case CHANNEL_DEWPOINT:
203                     return toQuantityType(
204                             WeatherUtils.getDewPoint(dashboardData.getTemperature(), dashboardData.getHumidity()),
205                             API_TEMPERATURE_UNIT);
206                 case CHANNEL_DEWPOINTDEP:
207                     Double dewPoint = WeatherUtils.getDewPoint(dashboardData.getTemperature(),
208                             dashboardData.getHumidity());
209                     return toQuantityType(WeatherUtils.getDewPointDep(dashboardData.getTemperature(), dewPoint),
210                             API_TEMPERATURE_UNIT);
211             }
212         }
213
214         switch (channelId) {
215             case CHANNEL_MIN_CO2:
216             case CHANNEL_MIN_CO2_THIS_WEEK:
217             case CHANNEL_MIN_CO2_THIS_MONTH:
218             case CHANNEL_MAX_CO2:
219             case CHANNEL_MAX_CO2_THIS_WEEK:
220             case CHANNEL_MAX_CO2_THIS_MONTH:
221                 return toQuantityType(channelMeasurements.get(channelId), API_CO2_UNIT);
222             case CHANNEL_MIN_HUMIDITY:
223             case CHANNEL_MIN_HUMIDITY_THIS_WEEK:
224             case CHANNEL_MIN_HUMIDITY_THIS_MONTH:
225             case CHANNEL_MAX_HUMIDITY:
226             case CHANNEL_MAX_HUMIDITY_THIS_WEEK:
227             case CHANNEL_MAX_HUMIDITY_THIS_MONTH:
228                 return toQuantityType(channelMeasurements.get(channelId), API_HUMIDITY_UNIT);
229             case CHANNEL_MIN_NOISE:
230             case CHANNEL_MIN_NOISE_THIS_WEEK:
231             case CHANNEL_MIN_NOISE_THIS_MONTH:
232             case CHANNEL_MAX_NOISE:
233             case CHANNEL_MAX_NOISE_THIS_WEEK:
234             case CHANNEL_MAX_NOISE_THIS_MONTH:
235                 return toQuantityType(channelMeasurements.get(channelId), API_NOISE_UNIT);
236             case CHANNEL_MIN_PRESSURE:
237             case CHANNEL_MIN_PRESSURE_THIS_WEEK:
238             case CHANNEL_MIN_PRESSURE_THIS_MONTH:
239             case CHANNEL_MAX_PRESSURE:
240             case CHANNEL_MAX_PRESSURE_THIS_WEEK:
241             case CHANNEL_MAX_PRESSURE_THIS_MONTH:
242                 return toQuantityType(channelMeasurements.get(channelId), API_PRESSURE_UNIT);
243             case CHANNEL_MIN_TEMP_THIS_WEEK:
244             case CHANNEL_MIN_TEMP_THIS_MONTH:
245             case CHANNEL_MAX_TEMP_THIS_WEEK:
246             case CHANNEL_MAX_TEMP_THIS_MONTH:
247                 return toQuantityType(channelMeasurements.get(channelId), API_TEMPERATURE_UNIT);
248             case CHANNEL_DATE_MIN_CO2:
249             case CHANNEL_DATE_MIN_CO2_THIS_WEEK:
250             case CHANNEL_DATE_MIN_CO2_THIS_MONTH:
251             case CHANNEL_DATE_MAX_CO2:
252             case CHANNEL_DATE_MAX_CO2_THIS_WEEK:
253             case CHANNEL_DATE_MAX_CO2_THIS_MONTH:
254             case CHANNEL_DATE_MIN_NOISE:
255             case CHANNEL_DATE_MIN_NOISE_THIS_WEEK:
256             case CHANNEL_DATE_MIN_NOISE_THIS_MONTH:
257             case CHANNEL_DATE_MAX_NOISE:
258             case CHANNEL_DATE_MAX_NOISE_THIS_WEEK:
259             case CHANNEL_DATE_MAX_NOISE_THIS_MONTH:
260             case CHANNEL_DATE_MIN_HUMIDITY:
261             case CHANNEL_DATE_MIN_HUMIDITY_THIS_WEEK:
262             case CHANNEL_DATE_MIN_HUMIDITY_THIS_MONTH:
263             case CHANNEL_DATE_MAX_HUMIDITY:
264             case CHANNEL_DATE_MAX_HUMIDITY_THIS_WEEK:
265             case CHANNEL_DATE_MAX_HUMIDITY_THIS_MONTH:
266             case CHANNEL_DATE_MIN_PRESSURE:
267             case CHANNEL_DATE_MIN_PRESSURE_THIS_WEEK:
268             case CHANNEL_DATE_MIN_PRESSURE_THIS_MONTH:
269             case CHANNEL_DATE_MAX_PRESSURE:
270             case CHANNEL_DATE_MAX_PRESSURE_THIS_WEEK:
271             case CHANNEL_DATE_MAX_PRESSURE_THIS_MONTH:
272             case CHANNEL_DATE_MIN_TEMP_THIS_WEEK:
273             case CHANNEL_DATE_MIN_TEMP_THIS_MONTH:
274             case CHANNEL_DATE_MAX_TEMP_THIS_WEEK:
275             case CHANNEL_DATE_MAX_TEMP_THIS_MONTH:
276                 return toDateTimeType(channelMeasurements.get(channelId), timeZoneProvider.getTimeZone());
277         }
278
279         return super.getNAThingProperty(channelId);
280     }
281
282     @Override
283     protected Optional<Integer> getDataTimestamp() {
284         return getDevice().map(d -> d.getLastStatusStore());
285     }
286
287     @Override
288     protected boolean isReachable() {
289         boolean result = false;
290         Optional<NAMain> device = getDevice();
291         if (device.isPresent()) {
292             Boolean reachable = device.get().isReachable();
293             result = reachable != null ? reachable.booleanValue() : false;
294         }
295         return result;
296     }
297 }