diff --git a/bundles/org.openhab.binding.netatmo/README.md b/bundles/org.openhab.binding.netatmo/README.md index 6cd14ea6e..83b19cb45 100644 --- a/bundles/org.openhab.binding.netatmo/README.md +++ b/bundles/org.openhab.binding.netatmo/README.md @@ -563,6 +563,7 @@ Warnings: | signal | strength | Number | Read-only | Signal strength (0 for no signal, 1 for weak...) | | signal | value | Number:Power | Read-only | Signal strength in dBm | | presence | floodlight | String | Read-write | Sets the floodlight to ON/OFF/AUTO | +| presence | siren | Switch | Read-write | Status of the siren, if silent or emitting an alarm | | last-event | type | String | Read-only | Type of event | | last-event | subtype | String | Read-only | Sub-type of event | | last-event | time | DateTime | Read-only | Time of occurrence of event | @@ -614,7 +615,7 @@ Note: live feeds either locally or via VPN are not available in Netatmo API. | Channel Group | Channel ID | Item Type | Read/Write | Description | | ------------- | ----------- | ------------ | ---------- | --------------------------------------------------- | -| siren | status | String | Read-only | Status of the siren, if silent or emitting an alarm | +| siren | status | Switch | Read-only | Status of the siren, if silent or emitting an alarm | | siren | monitoring | Switch | Read-only | State of the siren device | | signal | strength | Number | Read-only | Signal strength (0 for no signal, 1 for weak...) | | signal | value | Number:Power | Read-only | Signal strength in dBm | diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java index 586bd5bee..afe94f7fa 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java @@ -34,6 +34,7 @@ public class NetatmoBindingConstants { public static final String PROPERTY_COUNTRY = "country"; public static final String PROPERTY_TIMEZONE = "timezone"; public static final String PROPERTY_FEATURE = "feature"; + public static final String PROPERTY_THING_TYPE_VERSION = "thingTypeVersion"; // Channel group ids public static final String GROUP_LAST_EVENT = "last-event"; @@ -113,6 +114,7 @@ public class NetatmoBindingConstants { public static final String CHANNEL_SUM_RAIN24 = "sum-24"; public static final String CHANNEL_WIND_ANGLE = "angle"; public static final String CHANNEL_STATUS = GROUP_CAM_STATUS; + public static final String CHANNEL_SIREN = GROUP_SIREN; public static final String CHANNEL_WIND_STRENGTH = "strength"; public static final String CHANNEL_MAX_WIND_STRENGTH = "max-strength"; public static final String CHANNEL_DATE_MAX_WIND_STRENGTH = "max-strength-date"; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/ApiError.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/ApiError.java index 85f5ebf3a..19d83ff94 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/ApiError.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/ApiError.java @@ -16,7 +16,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.ServiceError; /** - * The {@link ApiError} models an errored response from API + * The {@link ApiError} models an error response from API * * @author Gaƫl L'hopital - Initial contribution */ diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/NetatmoException.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/NetatmoException.java index d89570bd2..aa88a28e3 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/NetatmoException.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/NetatmoException.java @@ -29,11 +29,11 @@ public class NetatmoException extends IOException { private ServiceError statusCode = ServiceError.UNKNOWN; public NetatmoException(String format, Object... args) { - super(String.format(format, args)); + super(format.formatted(args)); } public NetatmoException(Exception e, String format, Object... args) { - super(String.format(format, args), e); + super(format.formatted(args), e); } public NetatmoException(String message) { @@ -54,6 +54,6 @@ public class NetatmoException extends IOException { String message = super.getMessage(); return message == null ? null : ServiceError.UNKNOWN.equals(statusCode) ? message - : String.format("Rest call failed: statusCode=%s, message=%s", statusCode, message); + : "Rest call failed: statusCode=%s, message=%s".formatted(statusCode, message); } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java index 1b82c00f9..c56a8cf93 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java @@ -25,6 +25,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode; +import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SirenStatus; import org.openhab.binding.netatmo.internal.api.dto.Home; import org.openhab.binding.netatmo.internal.api.dto.HomeEvent; import org.openhab.binding.netatmo.internal.api.dto.HomeEvent.NAEventsDataResponse; @@ -126,6 +127,12 @@ public class SecurityApi extends RestManager { post(uriBuilder, ApiResponse.Ok.class, payload); } + public void changeSirenStatus(String homeId, String moduleId, SirenStatus status) throws NetatmoException { + UriBuilder uriBuilder = getApiUriBuilder(PATH_STATE); + String payload = PAYLOAD_SIREN_PRESENCE.formatted(homeId, moduleId, status.name().toLowerCase()); + post(uriBuilder, ApiResponse.Ok.class, payload); + } + public void setPersonAwayStatus(String homeId, String personId, boolean away) throws NetatmoException { UriBuilder uriBuilder = getApiUriBuilder(away ? SUB_PATH_PERSON_AWAY : SUB_PATH_PERSON_HOME); String payload = String.format(away ? PAYLOAD_PERSON_AWAY : PAYLOAD_PERSON_HOME, homeId, personId); diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/ModuleType.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/ModuleType.java index d4181ca4d..da58f4348 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/ModuleType.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/ModuleType.java @@ -64,66 +64,67 @@ import org.openhab.core.thing.ThingTypeUID; */ @NonNullByDefault public enum ModuleType { - UNKNOWN(FeatureArea.NONE, "", null, Set.of()), + UNKNOWN(FeatureArea.NONE, "", 1, null, Set.of()), - ACCOUNT(FeatureArea.NONE, "", null, Set.of(), new ChannelGroup(ApiBridgeChannelHelper.class, GROUP_MONITORING)), + ACCOUNT(FeatureArea.NONE, "", 1, null, Set.of(), new ChannelGroup(ApiBridgeChannelHelper.class, GROUP_MONITORING)), - HOME(FeatureArea.NONE, "NAHome", ACCOUNT, + HOME(FeatureArea.NONE, "NAHome", 1, ACCOUNT, Set.of(DeviceCapability.class, HomeCapability.class, ChannelHelperCapability.class), new ChannelGroup(SecurityChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_SECURITY), new ChannelGroup(EnergyChannelHelper.class, GROUP_ENERGY)), - PERSON(FeatureArea.SECURITY, "NAPerson", HOME, Set.of(PersonCapability.class, ChannelHelperCapability.class), + PERSON(FeatureArea.SECURITY, "NAPerson", 1, HOME, Set.of(PersonCapability.class, ChannelHelperCapability.class), new ChannelGroup(PersonChannelHelper.class, GROUP_PERSON), new ChannelGroup(EventPersonChannelHelper.class, GROUP_PERSON_LAST_EVENT)), - WELCOME(FeatureArea.SECURITY, "NACamera", HOME, Set.of(CameraCapability.class, ChannelHelperCapability.class), + WELCOME(FeatureArea.SECURITY, "NACamera", 1, HOME, Set.of(CameraCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.EVENT, new ChannelGroup(CameraChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_CAM_STATUS, GROUP_CAM_LIVE)), - TAG(FeatureArea.SECURITY, "NACamDoorTag", WELCOME, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, + TAG(FeatureArea.SECURITY, "NACamDoorTag", 1, WELCOME, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.BATTERY, ChannelGroup.TIMESTAMP, new ChannelGroup(DoorTagChannelHelper.class, GROUP_TAG)), - SIREN(FeatureArea.SECURITY, "NIS", WELCOME, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, + SIREN(FeatureArea.SECURITY, "NIS", 1, WELCOME, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.BATTERY, ChannelGroup.TIMESTAMP, new ChannelGroup(SirenChannelHelper.class, GROUP_SIREN)), - PRESENCE(FeatureArea.SECURITY, "NOC", HOME, Set.of(PresenceCapability.class, ChannelHelperCapability.class), + PRESENCE(FeatureArea.SECURITY, "NOC", 1, HOME, Set.of(PresenceCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.EVENT, new ChannelGroup(PresenceChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_CAM_STATUS, GROUP_CAM_LIVE, GROUP_PRESENCE), new ChannelGroup(EventCameraChannelHelper.class, GROUP_SUB_EVENT)), - DOORBELL(FeatureArea.SECURITY, "NDB", HOME, Set.of(DoorbellCapability.class, ChannelHelperCapability.class), + DOORBELL(FeatureArea.SECURITY, "NDB", 1, HOME, Set.of(DoorbellCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, new ChannelGroup(CameraChannelHelper.class, GROUP_SECURITY_EVENT, GROUP_DOORBELL_STATUS, GROUP_DOORBELL_LIVE), new ChannelGroup(EventCameraChannelHelper.class, GROUP_DOORBELL_LAST_EVENT, GROUP_DOORBELL_SUB_EVENT)), - WEATHER_STATION(FeatureArea.WEATHER, "NAMain", ACCOUNT, + WEATHER_STATION(FeatureArea.WEATHER, "NAMain", 1, ACCOUNT, Set.of(DeviceCapability.class, WeatherCapability.class, MeasureCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.HUMIDITY, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE, ChannelGroup.AIR_QUALITY, ChannelGroup.LOCATION, ChannelGroup.NOISE, ChannelGroup.TEMP_INSIDE_EXT, new ChannelGroup(PressureChannelHelper.class, MeasureClass.PRESSURE, GROUP_TYPE_PRESSURE_EXTENDED)), - OUTDOOR(FeatureArea.WEATHER, "NAModule1", WEATHER_STATION, + OUTDOOR(FeatureArea.WEATHER, "NAModule1", 1, WEATHER_STATION, Set.of(MeasureCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.HUMIDITY, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE, ChannelGroup.BATTERY, ChannelGroup.TEMP_OUTSIDE_EXT), - WIND(FeatureArea.WEATHER, "NAModule2", WEATHER_STATION, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, - ChannelGroup.TSTAMP_EXT, ChannelGroup.BATTERY, new ChannelGroup(WindChannelHelper.class, GROUP_WIND)), + WIND(FeatureArea.WEATHER, "NAModule2", 1, WEATHER_STATION, Set.of(ChannelHelperCapability.class), + ChannelGroup.SIGNAL, ChannelGroup.TSTAMP_EXT, ChannelGroup.BATTERY, + new ChannelGroup(WindChannelHelper.class, GROUP_WIND)), - RAIN(FeatureArea.WEATHER, "NAModule3", WEATHER_STATION, + RAIN(FeatureArea.WEATHER, "NAModule3", 1, WEATHER_STATION, Set.of(MeasureCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE, ChannelGroup.BATTERY, new ChannelGroup(RainChannelHelper.class, MeasureClass.RAIN_QUANTITY, GROUP_RAIN)), - INDOOR(FeatureArea.WEATHER, "NAModule4", WEATHER_STATION, + INDOOR(FeatureArea.WEATHER, "NAModule4", 1, WEATHER_STATION, Set.of(MeasureCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.TSTAMP_EXT, ChannelGroup.MEASURE, ChannelGroup.BATTERY, ChannelGroup.HUMIDITY, ChannelGroup.TEMP_INSIDE_EXT, ChannelGroup.AIR_QUALITY), - HOME_COACH(FeatureArea.AIR_CARE, "NHC", ACCOUNT, + HOME_COACH(FeatureArea.AIR_CARE, "NHC", 1, ACCOUNT, Set.of(DeviceCapability.class, AirCareCapability.class, MeasureCapability.class, ChannelHelperCapability.class), ChannelGroup.LOCATION, ChannelGroup.SIGNAL, ChannelGroup.NOISE, ChannelGroup.HUMIDITY, @@ -131,22 +132,23 @@ public enum ModuleType { new ChannelGroup(AirQualityChannelHelper.class, GROUP_TYPE_AIR_QUALITY_EXTENDED), new ChannelGroup(PressureChannelHelper.class, MeasureClass.PRESSURE, GROUP_PRESSURE)), - PLUG(FeatureArea.ENERGY, "NAPlug", HOME, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL), + PLUG(FeatureArea.ENERGY, "NAPlug", 1, HOME, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL), - VALVE(FeatureArea.ENERGY, "NRV", PLUG, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, + VALVE(FeatureArea.ENERGY, "NRV", 1, PLUG, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.BATTERY_EXT), - THERMOSTAT(FeatureArea.ENERGY, "NATherm1", PLUG, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, + THERMOSTAT(FeatureArea.ENERGY, "NATherm1", 1, PLUG, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.BATTERY_EXT, new ChannelGroup(Therm1ChannelHelper.class, GROUP_TYPE_TH_PROPERTIES)), - ROOM(FeatureArea.ENERGY, "NARoom", HOME, Set.of(RoomCapability.class, ChannelHelperCapability.class), + ROOM(FeatureArea.ENERGY, "NARoom", 1, HOME, Set.of(RoomCapability.class, ChannelHelperCapability.class), new ChannelGroup(RoomChannelHelper.class, GROUP_TYPE_ROOM_PROPERTIES, GROUP_TYPE_ROOM_TEMPERATURE), new ChannelGroup(SetpointChannelHelper.class, GROUP_SETPOINT)), - SMOKE_DETECTOR(FeatureArea.SECURITY, "NSD", HOME, Set.of(AlarmEventCapability.class, ChannelHelperCapability.class), - ChannelGroup.SIGNAL, ChannelGroup.TIMESTAMP, ChannelGroup.ALARM_LAST_EVENT), + SMOKE_DETECTOR(FeatureArea.SECURITY, "NSD", 1, HOME, + Set.of(AlarmEventCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, + ChannelGroup.TIMESTAMP, ChannelGroup.ALARM_LAST_EVENT), - CO_DETECTOR(FeatureArea.SECURITY, "NCO", HOME, Set.of(AlarmEventCapability.class, ChannelHelperCapability.class), + CO_DETECTOR(FeatureArea.SECURITY, "NCO", 1, HOME, Set.of(AlarmEventCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.TIMESTAMP, ChannelGroup.ALARM_LAST_EVENT); public static final EnumSet AS_SET = EnumSet.allOf(ModuleType.class); @@ -157,8 +159,9 @@ public enum ModuleType { public final ThingTypeUID thingTypeUID; public final FeatureArea feature; public final String apiName; + public final int thingTypeVersion; - ModuleType(FeatureArea feature, String apiName, @Nullable ModuleType bridge, + ModuleType(FeatureArea feature, String apiName, int thingTypeVersion, @Nullable ModuleType bridge, Set> capabilities, ChannelGroup... channelGroups) { this.bridgeType = Optional.ofNullable(bridge); this.feature = feature; @@ -166,6 +169,7 @@ public enum ModuleType { this.apiName = apiName; this.channelGroups = Set.of(channelGroups); this.thingTypeUID = new ThingTypeUID(BINDING_ID, name().toLowerCase().replace("_", "-")); + this.thingTypeVersion = thingTypeVersion; } public boolean isLogical() { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java index e2d692a3f..485af4f67 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java @@ -158,6 +158,7 @@ public class NetatmoConstants { // Payloads public static final String PAYLOAD_FLOODLIGHT = "{\"home\": {\"id\":\"%s\",\"modules\": [ {\"id\":\"%s\",\"floodlight\":\"%s\"} ]}}"; + public static final String PAYLOAD_SIREN_PRESENCE = "{\"home\": {\"id\":\"%s\",\"modules\": [ {\"id\":\"%s\",\"siren_status\":\"%s\"} ]}}"; public static final String PAYLOAD_PERSON_AWAY = "{\"home_id\":\"%s\",\"person_id\":\"%s\"}"; public static final String PAYLOAD_PERSON_HOME = "{\"home_id\":\"%s\",\"person_ids\":[\"%s\"]}"; @@ -348,6 +349,20 @@ public class NetatmoConstants { UNKNOWN; } + public enum SirenStatus { + SOUND, + NO_SOUND, + UNKNOWN; + + public static SirenStatus get(String value) { + try { + return valueOf(value.toUpperCase()); + } catch (IllegalArgumentException e) { + return UNKNOWN; + } + } + } + public enum BatteryState { @SerializedName("full") FULL(100), diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/HomeStatusModule.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/HomeStatusModule.java index d45369b6b..478c0966d 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/HomeStatusModule.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/HomeStatusModule.java @@ -21,6 +21,7 @@ import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.Alimentati import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.BatteryState; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SdCardStatus; +import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SirenStatus; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OpenClosedType; import org.openhab.core.types.State; @@ -42,7 +43,7 @@ public class HomeStatusModule extends NAThing { private FloodLightMode floodlight = FloodLightMode.UNKNOWN; private SdCardStatus sdStatus = SdCardStatus.UNKNOWN; private AlimentationStatus alimStatus = AlimentationStatus.UNKNOWN; - private @Nullable String sirenStatus; + private SirenStatus sirenStatus = SirenStatus.UNKNOWN; private @Nullable String vpnUrl; private boolean isLocal; private BatteryState batteryState = BatteryState.UNKNOWN; @@ -90,8 +91,8 @@ public class HomeStatusModule extends NAThing { return alimStatus; } - public Optional getSirenStatus() { - return Optional.ofNullable(sirenStatus); + public SirenStatus getSirenStatus() { + return sirenStatus; } public @Nullable String getVpnUrl() { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java index c3b820969..105801775 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java @@ -317,6 +317,7 @@ public class ApiBridgeHandler extends BaseBridgeHandler { InputStream stream = new ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8)); try (InputStreamContentProvider inputStreamContentProvider = new InputStreamContentProvider(stream)) { request.content(inputStreamContentProvider, contentType); + request.header(HttpHeader.ACCEPT, "application/json"); } logger.trace(" -with payload : {} ", payload); } @@ -404,10 +405,9 @@ public class ApiBridgeHandler extends BaseBridgeHandler { home.getRooms().values().stream().forEach(room -> { room.getModuleIds().stream().map(id -> home.getModules().get(id)) .map(m -> m != null ? m.getType().feature : FeatureArea.NONE) - .filter(f -> FeatureArea.ENERGY.equals(f)).findAny().ifPresent(f -> { - action.apply(room, homeUID) - .ifPresent(roomUID -> bridgesUids.put(room.getId(), roomUID)); - }); + .filter(f -> FeatureArea.ENERGY.equals(f)).findAny() + .ifPresent(f -> action.apply(room, homeUID) + .ifPresent(roomUID -> bridgesUids.put(room.getId(), roomUID))); }); // Creating modules that have no bridge first, avoiding weather station itself diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java index 916377544..d552d77c5 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java @@ -180,7 +180,7 @@ public interface CommonInterface { String channelName = channelUID.getIdWithoutGroup(); getCapabilities().values().forEach(cap -> cap.handleCommand(channelName, command)); } else { - getLogger().debug("Command {}, on channel {} dropped - thing is not ONLINE", command, channelUID); + getLogger().debug("Command {} on channel {} dropped - thing is not ONLINE", command, channelUID); } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java index f7c75e003..692be0465 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.netatmo.internal.handler.capability; -import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.VENDOR; +import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; import static org.openhab.core.thing.Thing.*; import java.util.Collection; @@ -97,10 +97,13 @@ public class Capability { protected void beforeNewData() { properties = new HashMap<>(thing.getProperties()); firstLaunch = properties.isEmpty(); - if (firstLaunch && !moduleType.isLogical()) { - String name = moduleType.apiName.isBlank() ? moduleType.name() : moduleType.apiName; - properties.put(PROPERTY_MODEL_ID, name); - properties.put(PROPERTY_VENDOR, VENDOR); + if (firstLaunch) { + properties.put(PROPERTY_THING_TYPE_VERSION, Integer.toString(moduleType.thingTypeVersion)); + if (!moduleType.isLogical()) { + String name = moduleType.apiName.isBlank() ? moduleType.name() : moduleType.apiName; + properties.put(PROPERTY_MODEL_ID, name); + properties.put(PROPERTY_VENDOR, VENDOR); + } } statusReason = null; } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java index d615d7dc9..9d3526f95 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java @@ -12,12 +12,14 @@ */ package org.openhab.binding.netatmo.internal.handler.capability; -import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.CHANNEL_FLOODLIGHT; +import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode; +import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SirenStatus; +import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule; import org.openhab.binding.netatmo.internal.handler.CommonInterface; import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper; import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider; @@ -42,6 +44,12 @@ public class PresenceCapability extends CameraCapability { super(handler, descriptionProvider, channelHelpers); } + @Override + public void updateHomeStatusModule(HomeStatusModule newData) { + super.updateHomeStatusModule(newData); + getSecurityCapability().ifPresent(cap -> cap.changeSirenStatus(handler.getId(), SirenStatus.SOUND)); + } + @Override public void handleCommand(String channelName, Command command) { if (CHANNEL_FLOODLIGHT.equals(channelName)) { @@ -50,13 +58,16 @@ public class PresenceCapability extends CameraCapability { return; } else if (command instanceof StringType) { try { - FloodLightMode mode = FloodLightMode.valueOf(command.toString()); - changeFloodlightMode(mode); + changeFloodlightMode(FloodLightMode.valueOf(command.toString())); } catch (IllegalArgumentException e) { logger.info("Incorrect command '{}' received for channel '{}'", command, channelName); } return; } + } else if (CHANNEL_SIREN.equals(channelName) && command instanceof OnOffType) { + getSecurityCapability().ifPresent(cap -> cap.changeSirenStatus(handler.getId(), + command == OnOffType.ON ? SirenStatus.SOUND : SirenStatus.NO_SOUND)); + return; } super.handleCommand(channelName, command); } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java index 84e422ae2..3cecf7f63 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java @@ -25,6 +25,7 @@ import org.openhab.binding.netatmo.internal.api.NetatmoException; import org.openhab.binding.netatmo.internal.api.SecurityApi; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea; import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode; +import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SirenStatus; import org.openhab.binding.netatmo.internal.api.dto.HomeData; import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule; import org.openhab.binding.netatmo.internal.api.dto.HomeDataPerson; @@ -238,4 +239,15 @@ class SecurityCapability extends RestCapability { } }); } + + public void changeSirenStatus(String moduleId, SirenStatus status) { + getApi().ifPresent(api -> { + try { + api.changeSirenStatus(handler.getId(), moduleId, status); + handler.expireData(); + } catch (NetatmoException e) { + logger.warn("Error changing siren status '{}' : {}", status, e.getMessage()); + } + }); + } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/PresenceChannelHelper.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/PresenceChannelHelper.java index d8882afac..b80011004 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/PresenceChannelHelper.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/PresenceChannelHelper.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.netatmo.internal.handler.channelhelper; -import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.CHANNEL_FLOODLIGHT; +import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.toStringType; import java.util.Set; @@ -22,7 +22,9 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule; import org.openhab.binding.netatmo.internal.api.dto.NAThing; import org.openhab.core.config.core.Configuration; +import org.openhab.core.library.types.OnOffType; import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; /** * The {@link PresenceChannelHelper} handles specific channels of Presence external cameras @@ -39,11 +41,19 @@ public class PresenceChannelHelper extends CameraChannelHelper { @Override protected @Nullable State internalGetProperty(String channelId, NAThing naThing, Configuration config) { - if (naThing instanceof HomeStatusModule) { - HomeStatusModule camera = (HomeStatusModule) naThing; + if (naThing instanceof HomeStatusModule presence) { switch (channelId) { case CHANNEL_FLOODLIGHT: - return toStringType(camera.getFloodlight()); + return toStringType(presence.getFloodlight()); + case CHANNEL_SIREN: + switch (presence.getSirenStatus()) { + case NO_SOUND: + return OnOffType.OFF; + case SOUND: + return OnOffType.ON; + case UNKNOWN: + return UnDefType.NULL; + } } } return super.internalGetProperty(channelId, naThing, config); diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/SirenChannelHelper.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/SirenChannelHelper.java index 896f4f806..3a17c2f66 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/SirenChannelHelper.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/SirenChannelHelper.java @@ -13,15 +13,16 @@ package org.openhab.binding.netatmo.internal.handler.channelhelper; import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; -import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.toStringType; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SirenStatus; import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule; import org.openhab.binding.netatmo.internal.api.dto.NAThing; import org.openhab.core.config.core.Configuration; +import org.openhab.core.library.types.OnOffType; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; @@ -32,7 +33,7 @@ import org.openhab.core.types.UnDefType; * */ @NonNullByDefault -public class SirenChannelHelper extends ChannelHelper { +public class SirenChannelHelper extends EventChannelHelper { public SirenChannelHelper(Set providedGroups) { super(providedGroups); @@ -40,14 +41,14 @@ public class SirenChannelHelper extends ChannelHelper { @Override protected @Nullable State internalGetProperty(String channelId, NAThing naThing, Configuration config) { - if (naThing instanceof HomeStatusModule) { - HomeStatusModule homeStatus = (HomeStatusModule) naThing; - switch (channelId) { - case CHANNEL_MONITORING: - return homeStatus.getMonitoring(); - case CHANNEL_STATUS: - return homeStatus.getStatus().map(status -> toStringType(status)).orElse(UnDefType.UNDEF); - } + if (naThing instanceof HomeStatusModule homeStatus) { + return switch (channelId) { + case CHANNEL_MONITORING -> homeStatus.getMonitoring(); + case CHANNEL_STATUS -> homeStatus.getStatus().map(SirenStatus::get) + .map(status -> SirenStatus.SOUND == status ? OnOffType.ON : OnOffType.OFF) + .map(State.class::cast).orElse(UnDefType.UNDEF); + default -> null; + }; } return null; } diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties index d86de3707..c67f080b4 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties @@ -311,10 +311,10 @@ channel-type.netatmo.setpoint.label = Setpoint channel-type.netatmo.setpoint.description = Thermostat temperature setpoint. channel-type.netatmo.siren-monitoring.label = Monitoring channel-type.netatmo.siren-monitoring.description = Monitoring state of the equipment -channel-type.netatmo.siren-status.label = Status +channel-type.netatmo.siren-status-rw.label = Siren +channel-type.netatmo.siren-status-rw.description = Status of the siren +channel-type.netatmo.siren-status.label = Siren channel-type.netatmo.siren-status.description = Status of the siren -channel-type.netatmo.siren-status.state.option.no_sound = Silent -channel-type.netatmo.siren-status.state.option.sound = Alarm channel-type.netatmo.tag-status.label = Door Status channel-type.netatmo.th-mode.label = Thermostat Mode channel-type.netatmo.th-mode.description = Chosen thermostat mode (home, frost guard, manual, max). diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/channels.xml index ae4b96ff0..c57680b2b 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/channels.xml @@ -18,15 +18,18 @@ - String - + Switch + Status of the siren - - - - - - + Soundvolume + + + + + Switch + + Status of the siren + Soundvolume diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/security.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/security.xml index 1a8bd9afb..29a601f53 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/security.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/security.xml @@ -225,6 +225,7 @@ + diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/update/instructions.xml new file mode 100644 index 000000000..10d3dff09 --- /dev/null +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/update/instructions.xml @@ -0,0 +1,19 @@ + + + + + + + + netatmo:siren-status-rw + + + netatmo:siren-status + + + + + +