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.netatmo.internal.api.data;
15 import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
16 import static org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.*;
19 import java.util.EnumSet;
20 import java.util.List;
21 import java.util.Objects;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
27 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.MeasureClass;
28 import org.openhab.binding.netatmo.internal.handler.capability.AirCareCapability;
29 import org.openhab.binding.netatmo.internal.handler.capability.AlarmEventCapability;
30 import org.openhab.binding.netatmo.internal.handler.capability.CameraCapability;
31 import org.openhab.binding.netatmo.internal.handler.capability.Capability;
32 import org.openhab.binding.netatmo.internal.handler.capability.ChannelHelperCapability;
33 import org.openhab.binding.netatmo.internal.handler.capability.DeviceCapability;
34 import org.openhab.binding.netatmo.internal.handler.capability.DoorbellCapability;
35 import org.openhab.binding.netatmo.internal.handler.capability.HomeCapability;
36 import org.openhab.binding.netatmo.internal.handler.capability.MeasureCapability;
37 import org.openhab.binding.netatmo.internal.handler.capability.ParentUpdateCapability;
38 import org.openhab.binding.netatmo.internal.handler.capability.PersonCapability;
39 import org.openhab.binding.netatmo.internal.handler.capability.PresenceCapability;
40 import org.openhab.binding.netatmo.internal.handler.capability.RefreshAutoCapability;
41 import org.openhab.binding.netatmo.internal.handler.capability.RefreshCapability;
42 import org.openhab.binding.netatmo.internal.handler.capability.RoomCapability;
43 import org.openhab.binding.netatmo.internal.handler.capability.WeatherCapability;
44 import org.openhab.binding.netatmo.internal.handler.channelhelper.AirQualityChannelHelper;
45 import org.openhab.binding.netatmo.internal.handler.channelhelper.ApiBridgeChannelHelper;
46 import org.openhab.binding.netatmo.internal.handler.channelhelper.CameraChannelHelper;
47 import org.openhab.binding.netatmo.internal.handler.channelhelper.DoorTagChannelHelper;
48 import org.openhab.binding.netatmo.internal.handler.channelhelper.EnergyChannelHelper;
49 import org.openhab.binding.netatmo.internal.handler.channelhelper.EventCameraChannelHelper;
50 import org.openhab.binding.netatmo.internal.handler.channelhelper.EventPersonChannelHelper;
51 import org.openhab.binding.netatmo.internal.handler.channelhelper.PersonChannelHelper;
52 import org.openhab.binding.netatmo.internal.handler.channelhelper.PresenceChannelHelper;
53 import org.openhab.binding.netatmo.internal.handler.channelhelper.PressureChannelHelper;
54 import org.openhab.binding.netatmo.internal.handler.channelhelper.RainChannelHelper;
55 import org.openhab.binding.netatmo.internal.handler.channelhelper.RoomChannelHelper;
56 import org.openhab.binding.netatmo.internal.handler.channelhelper.SecurityChannelHelper;
57 import org.openhab.binding.netatmo.internal.handler.channelhelper.SetpointChannelHelper;
58 import org.openhab.binding.netatmo.internal.handler.channelhelper.SirenChannelHelper;
59 import org.openhab.binding.netatmo.internal.handler.channelhelper.Therm1ChannelHelper;
60 import org.openhab.binding.netatmo.internal.handler.channelhelper.WindChannelHelper;
61 import org.openhab.core.thing.ThingTypeUID;
64 * This enum describes all Netatmo modules and devices along with their capabilities.
66 * @author Gaƫl L'hopital - Initial contribution
69 public enum ModuleType {
70 UNKNOWN(FeatureArea.NONE, "", 1, "virtual", null, Set.of()),
72 ACCOUNT(FeatureArea.NONE, "", 1, "api_bridge", null, Set.of(),
73 new ChannelGroup(ApiBridgeChannelHelper.class, GROUP_MONITORING)),
75 HOME(FeatureArea.NONE, "NAHome", 1, "home", ACCOUNT,
76 Set.of(DeviceCapability.class, HomeCapability.class, ChannelHelperCapability.class,
77 RefreshCapability.class),
78 new ChannelGroup(SecurityChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_SECURITY),
79 new ChannelGroup(EnergyChannelHelper.class, GROUP_ENERGY)),
81 PERSON(FeatureArea.SECURITY, "NAPerson", 1, "virtual", HOME,
82 Set.of(PersonCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
83 new ChannelGroup(PersonChannelHelper.class, GROUP_PERSON),
84 new ChannelGroup(EventPersonChannelHelper.class, GROUP_PERSON_LAST_EVENT)),
86 WELCOME(FeatureArea.SECURITY, "NACamera", 1, "camera", HOME,
87 Set.of(CameraCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
88 ChannelGroup.SIGNAL, ChannelGroup.EVENT,
89 new ChannelGroup(CameraChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_CAM_STATUS, GROUP_CAM_LIVE)),
91 TAG(FeatureArea.SECURITY, "NACamDoorTag", 1, "device", WELCOME,
92 Set.of(ChannelHelperCapability.class, ParentUpdateCapability.class), ChannelGroup.SIGNAL,
93 ChannelGroup.BATTERY, ChannelGroup.TIMESTAMP, new ChannelGroup(DoorTagChannelHelper.class, GROUP_TAG)),
95 SIREN(FeatureArea.SECURITY, "NIS", 1, "device", WELCOME,
96 Set.of(ChannelHelperCapability.class, ParentUpdateCapability.class), ChannelGroup.SIGNAL,
97 ChannelGroup.BATTERY, ChannelGroup.TIMESTAMP, new ChannelGroup(SirenChannelHelper.class, GROUP_SIREN)),
99 PRESENCE(FeatureArea.SECURITY, "NOC", 1, "camera", HOME,
100 Set.of(PresenceCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
101 ChannelGroup.SIGNAL, ChannelGroup.EVENT,
102 new ChannelGroup(PresenceChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_CAM_STATUS, GROUP_CAM_LIVE,
104 new ChannelGroup(EventCameraChannelHelper.class, GROUP_SUB_EVENT)),
106 DOORBELL(FeatureArea.SECURITY, "NDB", 1, "camera", HOME,
107 Set.of(DoorbellCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
109 new ChannelGroup(CameraChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_DOORBELL_STATUS,
110 GROUP_DOORBELL_LIVE),
111 new ChannelGroup(EventCameraChannelHelper.class, GROUP_DOORBELL_LAST_EVENT, GROUP_DOORBELL_SUB_EVENT)),
113 WEATHER_STATION(FeatureArea.WEATHER, "NAMain", 1, "weather", ACCOUNT,
114 Set.of(DeviceCapability.class, WeatherCapability.class, MeasureCapability.class,
115 ChannelHelperCapability.class, RefreshAutoCapability.class),
116 ChannelGroup.SIGNAL, ChannelGroup.HUMIDITY, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE,
117 ChannelGroup.AIR_QUALITY, ChannelGroup.LOCATION, ChannelGroup.NOISE, ChannelGroup.TEMP_INSIDE_EXT,
118 new ChannelGroup(PressureChannelHelper.class, MeasureClass.PRESSURE, GROUP_TYPE_PRESSURE_EXTENDED)),
120 OUTDOOR(FeatureArea.WEATHER, "NAModule1", 1, "device", WEATHER_STATION,
121 Set.of(MeasureCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
122 ChannelGroup.SIGNAL, ChannelGroup.HUMIDITY, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE,
123 ChannelGroup.BATTERY, ChannelGroup.TEMP_OUTSIDE_EXT),
125 WIND(FeatureArea.WEATHER, "NAModule2", 1, "device", WEATHER_STATION,
126 Set.of(ChannelHelperCapability.class, ParentUpdateCapability.class), ChannelGroup.SIGNAL,
127 ChannelGroup.TSTAMP_EXT, ChannelGroup.BATTERY, new ChannelGroup(WindChannelHelper.class, GROUP_WIND)),
129 RAIN(FeatureArea.WEATHER, "NAModule3", 1, "device", WEATHER_STATION,
130 Set.of(MeasureCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
131 ChannelGroup.SIGNAL, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE, ChannelGroup.BATTERY,
132 new ChannelGroup(RainChannelHelper.class, MeasureClass.RAIN_QUANTITY, GROUP_RAIN)),
134 INDOOR(FeatureArea.WEATHER, "NAModule4", 1, "device", WEATHER_STATION,
135 Set.of(MeasureCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
136 ChannelGroup.SIGNAL, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE, ChannelGroup.BATTERY,
137 ChannelGroup.HUMIDITY, ChannelGroup.TEMP_INSIDE_EXT, ChannelGroup.AIR_QUALITY),
139 HOME_COACH(FeatureArea.AIR_CARE, "NHC", 1, "weather", ACCOUNT,
140 Set.of(DeviceCapability.class, AirCareCapability.class, MeasureCapability.class,
141 ChannelHelperCapability.class, RefreshAutoCapability.class),
142 ChannelGroup.LOCATION, ChannelGroup.SIGNAL, ChannelGroup.NOISE, ChannelGroup.HUMIDITY,
143 ChannelGroup.TEMP_INSIDE, ChannelGroup.MEASURE, ChannelGroup.TSTAMP_EXT,
144 new ChannelGroup(AirQualityChannelHelper.class, GROUP_TYPE_AIR_QUALITY_EXTENDED),
145 new ChannelGroup(PressureChannelHelper.class, MeasureClass.PRESSURE, GROUP_PRESSURE)),
147 PLUG(FeatureArea.ENERGY, "NAPlug", 1, "device", HOME,
148 Set.of(ChannelHelperCapability.class, ParentUpdateCapability.class), ChannelGroup.SIGNAL),
150 VALVE(FeatureArea.ENERGY, "NRV", 1, "device", PLUG,
151 Set.of(ChannelHelperCapability.class, ParentUpdateCapability.class), ChannelGroup.SIGNAL,
152 ChannelGroup.BATTERY_EXT),
154 THERMOSTAT(FeatureArea.ENERGY, "NATherm1", 1, "device", PLUG,
155 Set.of(ChannelHelperCapability.class, ParentUpdateCapability.class), ChannelGroup.SIGNAL,
156 ChannelGroup.BATTERY_EXT, new ChannelGroup(Therm1ChannelHelper.class, GROUP_TYPE_TH_PROPERTIES)),
158 ROOM(FeatureArea.ENERGY, "NARoom", 1, "virtual", HOME,
159 Set.of(RoomCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
160 new ChannelGroup(RoomChannelHelper.class, GROUP_TYPE_ROOM_PROPERTIES, GROUP_TYPE_ROOM_TEMPERATURE),
161 new ChannelGroup(SetpointChannelHelper.class, GROUP_SETPOINT)),
163 SMOKE_DETECTOR(FeatureArea.SECURITY, "NSD", 1, "device", HOME,
164 Set.of(AlarmEventCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
165 ChannelGroup.SIGNAL, ChannelGroup.TIMESTAMP, ChannelGroup.ALARM_LAST_EVENT),
167 CO_DETECTOR(FeatureArea.SECURITY, "NCO", 1, "device", HOME,
168 Set.of(AlarmEventCapability.class, ChannelHelperCapability.class, ParentUpdateCapability.class),
169 ChannelGroup.SIGNAL, ChannelGroup.TIMESTAMP, ChannelGroup.ALARM_LAST_EVENT);
171 public static final EnumSet<ModuleType> AS_SET = EnumSet.allOf(ModuleType.class);
173 private final @Nullable ModuleType bridgeType;
174 public final Set<ChannelGroup> channelGroups;
175 public final Set<Class<? extends Capability>> capabilities;
176 public final ThingTypeUID thingTypeUID;
177 public final FeatureArea feature;
178 public final String apiName;
179 public final String thingTypeVersion;
180 public final URI configDescription;
182 ModuleType(FeatureArea feature, String apiName, int thingTypeVersion, String config, @Nullable ModuleType bridge,
183 Set<Class<? extends Capability>> capabilities, ChannelGroup... channelGroups) {
184 this.bridgeType = bridge;
185 this.feature = feature;
186 this.capabilities = capabilities;
187 this.apiName = apiName;
188 this.channelGroups = Set.of(channelGroups);
189 this.thingTypeUID = new ThingTypeUID(BINDING_ID, name().toLowerCase().replace("_", "-"));
190 this.thingTypeVersion = Integer.toString(thingTypeVersion);
191 this.configDescription = URI.create(BINDING_ID + ":" + config);
194 public boolean isLogical() {
195 return !channelGroups.contains(ChannelGroup.SIGNAL);
198 public boolean isABridge() { // I am a bridge if any module references me as being so
199 return AS_SET.stream().anyMatch(mt -> this.equals(mt.getBridge()));
202 public List<String> getExtensions() {
203 return channelGroups.stream().map(cg -> cg.extensions).flatMap(Set::stream).toList();
206 public List<String> getGroupTypes() {
207 return channelGroups.stream().map(cg -> cg.groupTypes).flatMap(Set::stream).toList();
210 public int[] getSignalLevels() {
212 return (channelGroups.contains(ChannelGroup.BATTERY) || channelGroups.contains(ChannelGroup.BATTERY_EXT))
213 ? RADIO_SIGNAL_LEVELS
214 : WIFI_SIGNAL_LEVELS;
216 throw new IllegalArgumentException(
217 "getSignalLevels should not be called for module type: '%s', please file a bug report."
221 public ModuleType getBridge() {
222 return Objects.requireNonNullElse(this.bridgeType, UNKNOWN);
225 public int getDepth() {
226 ModuleType parent = getBridge();
227 return parent == UNKNOWN ? 1 : parent.getDepth() + 1;
230 public static ModuleType from(ThingTypeUID thingTypeUID) {
231 return AS_SET.stream().filter(mt -> mt.thingTypeUID.equals(thingTypeUID)).findFirst()
232 .orElseThrow(() -> new IllegalArgumentException(
233 "No known ModuleType matched '%s'".formatted(thingTypeUID.toString())));