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.station;
15 import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
16 import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
18 import java.util.ArrayList;
19 import java.util.List;
21 import java.util.Optional;
22 import java.util.concurrent.ConcurrentHashMap;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.openhab.binding.netatmo.internal.WeatherUtils;
26 import org.openhab.binding.netatmo.internal.handler.NetatmoModuleHandler;
27 import org.openhab.core.i18n.TimeZoneProvider;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.types.State;
31 import io.swagger.client.model.NADashboardData;
32 import io.swagger.client.model.NAStationModule;
35 * {@link NAModule4Handler} is the class used to handle the additional
36 * indoor module capable of reporting temperature, humidity and CO2 level
38 * @author Gaƫl L'hopital - Initial contribution
39 * @author Rob Nielsen - Added day, week, and month measurements to the weather station and modules
43 public class NAModule4Handler extends NetatmoModuleHandler<NAStationModule> {
44 private Map<String, Float> channelMeasurements = new ConcurrentHashMap<>();
46 public NAModule4Handler(Thing thing, final TimeZoneProvider timeZoneProvider) {
47 super(thing, timeZoneProvider);
51 protected void updateProperties(NAStationModule moduleData) {
52 updateProperties(moduleData.getFirmware(), moduleData.getType());
56 public void updateMeasurements() {
57 updateDayMeasurements();
58 updateWeekMeasurements();
59 updateMonthMeasurements();
62 private void updateDayMeasurements() {
63 List<String> channels = new ArrayList<>();
64 List<String> types = new ArrayList<>();
65 addMeasurement(channels, types, CHANNEL_MIN_CO2, MIN_CO2);
66 addMeasurement(channels, types, CHANNEL_MAX_CO2, MAX_CO2);
67 addMeasurement(channels, types, CHANNEL_MIN_HUMIDITY, MIN_HUM);
68 addMeasurement(channels, types, CHANNEL_MAX_HUMIDITY, MAX_HUM);
69 addMeasurement(channels, types, CHANNEL_DATE_MIN_CO2, DATE_MIN_CO2);
70 addMeasurement(channels, types, CHANNEL_DATE_MAX_CO2, DATE_MAX_CO2);
71 addMeasurement(channels, types, CHANNEL_DATE_MIN_HUMIDITY, DATE_MIN_HUM);
72 addMeasurement(channels, types, CHANNEL_DATE_MAX_HUMIDITY, DATE_MAX_HUM);
73 if (!channels.isEmpty()) {
74 getMeasurements(getParentId(), getId(), ONE_DAY, types, channels, channelMeasurements);
78 private void updateWeekMeasurements() {
79 List<String> channels = new ArrayList<>();
80 List<String> types = new ArrayList<>();
81 addMeasurement(channels, types, CHANNEL_MIN_CO2_THIS_WEEK, MIN_CO2);
82 addMeasurement(channels, types, CHANNEL_MAX_CO2_THIS_WEEK, MAX_CO2);
83 addMeasurement(channels, types, CHANNEL_MIN_HUMIDITY_THIS_WEEK, MIN_HUM);
84 addMeasurement(channels, types, CHANNEL_MAX_HUMIDITY_THIS_WEEK, MAX_HUM);
85 addMeasurement(channels, types, CHANNEL_MIN_TEMP_THIS_WEEK, MIN_TEMP);
86 addMeasurement(channels, types, CHANNEL_MAX_TEMP_THIS_WEEK, MAX_TEMP);
87 addMeasurement(channels, types, CHANNEL_DATE_MIN_CO2_THIS_WEEK, DATE_MIN_CO2);
88 addMeasurement(channels, types, CHANNEL_DATE_MAX_CO2_THIS_WEEK, DATE_MAX_CO2);
89 addMeasurement(channels, types, CHANNEL_DATE_MIN_HUMIDITY_THIS_WEEK, DATE_MIN_HUM);
90 addMeasurement(channels, types, CHANNEL_DATE_MAX_HUMIDITY_THIS_WEEK, DATE_MAX_HUM);
91 addMeasurement(channels, types, CHANNEL_DATE_MIN_TEMP_THIS_WEEK, DATE_MIN_TEMP);
92 addMeasurement(channels, types, CHANNEL_DATE_MAX_TEMP_THIS_WEEK, DATE_MAX_TEMP);
93 if (!channels.isEmpty()) {
94 getMeasurements(getParentId(), getId(), ONE_WEEK, types, channels, channelMeasurements);
98 private void updateMonthMeasurements() {
99 List<String> channels = new ArrayList<>();
100 List<String> types = new ArrayList<>();
101 addMeasurement(channels, types, CHANNEL_MIN_CO2_THIS_MONTH, MIN_CO2);
102 addMeasurement(channels, types, CHANNEL_MAX_CO2_THIS_MONTH, MAX_CO2);
103 addMeasurement(channels, types, CHANNEL_MIN_HUMIDITY_THIS_MONTH, MIN_HUM);
104 addMeasurement(channels, types, CHANNEL_MAX_HUMIDITY_THIS_MONTH, MAX_HUM);
105 addMeasurement(channels, types, CHANNEL_MIN_TEMP_THIS_MONTH, MIN_TEMP);
106 addMeasurement(channels, types, CHANNEL_MAX_TEMP_THIS_MONTH, MAX_TEMP);
107 addMeasurement(channels, types, CHANNEL_DATE_MIN_CO2_THIS_MONTH, DATE_MIN_CO2);
108 addMeasurement(channels, types, CHANNEL_DATE_MAX_CO2_THIS_MONTH, DATE_MAX_CO2);
109 addMeasurement(channels, types, CHANNEL_DATE_MIN_HUMIDITY_THIS_MONTH, DATE_MIN_HUM);
110 addMeasurement(channels, types, CHANNEL_DATE_MAX_HUMIDITY_THIS_MONTH, DATE_MAX_HUM);
111 addMeasurement(channels, types, CHANNEL_DATE_MIN_TEMP_THIS_MONTH, DATE_MIN_TEMP);
112 addMeasurement(channels, types, CHANNEL_DATE_MAX_TEMP_THIS_MONTH, DATE_MAX_TEMP);
113 if (!channels.isEmpty()) {
114 getMeasurements(getParentId(), getId(), ONE_MONTH, types, channels, channelMeasurements);
119 protected State getNAThingProperty(String channelId) {
120 NADashboardData dashboardData = getModule().map(m -> m.getDashboardData()).orElse(null);
121 if (dashboardData != null) {
123 case CHANNEL_TEMP_TREND:
124 return toStringType(dashboardData.getTempTrend());
126 return toQuantityType(dashboardData.getCo2(), API_CO2_UNIT);
127 case CHANNEL_TEMPERATURE:
128 return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
129 case CHANNEL_DATE_MIN_TEMP:
130 return toDateTimeType(dashboardData.getDateMinTemp(), timeZoneProvider.getTimeZone());
131 case CHANNEL_DATE_MAX_TEMP:
132 return toDateTimeType(dashboardData.getDateMaxTemp(), timeZoneProvider.getTimeZone());
133 case CHANNEL_MIN_TEMP:
134 return toQuantityType(dashboardData.getMinTemp(), API_TEMPERATURE_UNIT);
135 case CHANNEL_MAX_TEMP:
136 return toQuantityType(dashboardData.getMaxTemp(), API_TEMPERATURE_UNIT);
137 case CHANNEL_TIMEUTC:
138 return toDateTimeType(dashboardData.getTimeUtc(), timeZoneProvider.getTimeZone());
139 case CHANNEL_HUMIDITY:
140 return toQuantityType(dashboardData.getHumidity(), API_HUMIDITY_UNIT);
141 case CHANNEL_HUMIDEX:
142 return toDecimalType(
143 WeatherUtils.getHumidex(dashboardData.getTemperature(), dashboardData.getHumidity()));
144 case CHANNEL_HEATINDEX:
145 return toQuantityType(
146 WeatherUtils.getHeatIndex(dashboardData.getTemperature(), dashboardData.getHumidity()),
147 API_TEMPERATURE_UNIT);
148 case CHANNEL_DEWPOINT:
149 return toQuantityType(
150 WeatherUtils.getDewPoint(dashboardData.getTemperature(), dashboardData.getHumidity()),
151 API_TEMPERATURE_UNIT);
152 case CHANNEL_DEWPOINTDEP:
153 Double dewpoint = WeatherUtils.getDewPoint(dashboardData.getTemperature(),
154 dashboardData.getHumidity());
155 return toQuantityType(WeatherUtils.getDewPointDep(dashboardData.getTemperature(), dewpoint),
156 API_TEMPERATURE_UNIT);
161 case CHANNEL_MIN_CO2:
162 case CHANNEL_MIN_CO2_THIS_WEEK:
163 case CHANNEL_MIN_CO2_THIS_MONTH:
164 case CHANNEL_MAX_CO2:
165 case CHANNEL_MAX_CO2_THIS_WEEK:
166 case CHANNEL_MAX_CO2_THIS_MONTH:
167 return toQuantityType(channelMeasurements.get(channelId), API_CO2_UNIT);
168 case CHANNEL_MIN_HUMIDITY:
169 case CHANNEL_MIN_HUMIDITY_THIS_WEEK:
170 case CHANNEL_MIN_HUMIDITY_THIS_MONTH:
171 case CHANNEL_MAX_HUMIDITY:
172 case CHANNEL_MAX_HUMIDITY_THIS_WEEK:
173 case CHANNEL_MAX_HUMIDITY_THIS_MONTH:
174 return toQuantityType(channelMeasurements.get(channelId), API_HUMIDITY_UNIT);
175 case CHANNEL_MIN_TEMP_THIS_WEEK:
176 case CHANNEL_MIN_TEMP_THIS_MONTH:
177 case CHANNEL_MAX_TEMP_THIS_WEEK:
178 case CHANNEL_MAX_TEMP_THIS_MONTH:
179 return toQuantityType(channelMeasurements.get(channelId), API_TEMPERATURE_UNIT);
180 case CHANNEL_DATE_MIN_CO2:
181 case CHANNEL_DATE_MIN_CO2_THIS_WEEK:
182 case CHANNEL_DATE_MIN_CO2_THIS_MONTH:
183 case CHANNEL_DATE_MAX_CO2:
184 case CHANNEL_DATE_MAX_CO2_THIS_WEEK:
185 case CHANNEL_DATE_MAX_CO2_THIS_MONTH:
186 case CHANNEL_DATE_MIN_HUMIDITY:
187 case CHANNEL_DATE_MIN_HUMIDITY_THIS_WEEK:
188 case CHANNEL_DATE_MIN_HUMIDITY_THIS_MONTH:
189 case CHANNEL_DATE_MAX_HUMIDITY:
190 case CHANNEL_DATE_MAX_HUMIDITY_THIS_WEEK:
191 case CHANNEL_DATE_MAX_HUMIDITY_THIS_MONTH:
192 case CHANNEL_DATE_MIN_TEMP_THIS_WEEK:
193 case CHANNEL_DATE_MIN_TEMP_THIS_MONTH:
194 case CHANNEL_DATE_MAX_TEMP_THIS_WEEK:
195 case CHANNEL_DATE_MAX_TEMP_THIS_MONTH:
196 return toDateTimeType(channelMeasurements.get(channelId), timeZoneProvider.getTimeZone());
199 return super.getNAThingProperty(channelId);
203 protected boolean isReachable() {
204 boolean result = false;
205 Optional<NAStationModule> module = getModule();
206 if (module.isPresent()) {
207 Boolean reachable = module.get().isReachable();
208 result = reachable != null ? reachable.booleanValue() : false;