diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java index 1912f12f7b8..ffe339dd7ee 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java @@ -31,7 +31,7 @@ import org.openhab.binding.netatmo.internal.handler.capability.CameraCapability; import org.openhab.binding.netatmo.internal.handler.capability.Capability; import org.openhab.binding.netatmo.internal.handler.capability.ChannelHelperCapability; import org.openhab.binding.netatmo.internal.handler.capability.DeviceCapability; -import org.openhab.binding.netatmo.internal.handler.capability.EventCapability; +import org.openhab.binding.netatmo.internal.handler.capability.DoorbellCapability; import org.openhab.binding.netatmo.internal.handler.capability.HomeCapability; import org.openhab.binding.netatmo.internal.handler.capability.MeasureCapability; import org.openhab.binding.netatmo.internal.handler.capability.PersonCapability; @@ -122,14 +122,14 @@ public class NetatmoHandlerFactory extends BaseThingHandlerFactory { newCap = new DeviceCapability(handler); } else if (capability == AirCareCapability.class) { newCap = new AirCareCapability(handler); - } else if (capability == EventCapability.class) { - newCap = new EventCapability(handler); } else if (capability == HomeCapability.class) { newCap = new HomeCapability(handler, stateDescriptionProvider); } else if (capability == WeatherCapability.class) { newCap = new WeatherCapability(handler); } else if (capability == RoomCapability.class) { newCap = new RoomCapability(handler); + } else if (capability == DoorbellCapability.class) { + newCap = new DoorbellCapability(handler, stateDescriptionProvider, helpers); } else if (capability == PersonCapability.class) { newCap = new PersonCapability(handler, stateDescriptionProvider, helpers); } else if (capability == CameraCapability.class) { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/EventType.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/EventType.java index e7b8708f204..19528e6e708 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/EventType.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/EventType.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.netatmo.internal.api.data; +import java.util.EnumSet; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -97,6 +98,9 @@ public enum EventType { @SerializedName("incoming_call") // When a call as been answered by a user INCOMING_CALL(ModuleType.DOORBELL), + @SerializedName("rtc") // Button pressed + RTC(ModuleType.DOORBELL), + @SerializedName("missed_call") // When a call has not been answered by anyone MISSED_CALL(ModuleType.DOORBELL), @@ -124,6 +128,8 @@ public enum EventType { @SerializedName("new_device") NEW_DEVICE(ModuleType.HOME); + public static final EnumSet AS_SET = EnumSet.allOf(EventType.class); + private final Set appliesTo; EventType(ModuleType... appliesTo) { 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 8eef2416869..f999e6a1e16 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 @@ -30,7 +30,7 @@ import org.openhab.binding.netatmo.internal.handler.capability.CameraCapability; import org.openhab.binding.netatmo.internal.handler.capability.Capability; import org.openhab.binding.netatmo.internal.handler.capability.ChannelHelperCapability; import org.openhab.binding.netatmo.internal.handler.capability.DeviceCapability; -import org.openhab.binding.netatmo.internal.handler.capability.EventCapability; +import org.openhab.binding.netatmo.internal.handler.capability.DoorbellCapability; import org.openhab.binding.netatmo.internal.handler.capability.HomeCapability; import org.openhab.binding.netatmo.internal.handler.capability.MeasureCapability; import org.openhab.binding.netatmo.internal.handler.capability.PersonCapability; @@ -67,29 +67,27 @@ public enum ModuleType { ACCOUNT(FeatureArea.NONE, "", null, Set.of()), HOME(FeatureArea.NONE, "NAHome", ACCOUNT, - Set.of(DeviceCapability.class, EventCapability.class, HomeCapability.class, ChannelHelperCapability.class), + Set.of(DeviceCapability.class, HomeCapability.class, ChannelHelperCapability.class), new ChannelGroup(SecurityChannelHelper.class, GROUP_SECURITY), new ChannelGroup(EnergyChannelHelper.class, GROUP_ENERGY)), - PERSON(FeatureArea.SECURITY, "NAPerson", HOME, - Set.of(EventCapability.class, PersonCapability.class, ChannelHelperCapability.class), + PERSON(FeatureArea.SECURITY, "NAPerson", 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(EventCapability.class, CameraCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, - ChannelGroup.EVENT, new ChannelGroup(CameraChannelHelper.class, GROUP_CAM_STATUS, GROUP_CAM_LIVE)), + WELCOME(FeatureArea.SECURITY, "NACamera", HOME, Set.of(CameraCapability.class, ChannelHelperCapability.class), + ChannelGroup.SIGNAL, ChannelGroup.EVENT, + new ChannelGroup(CameraChannelHelper.class, GROUP_CAM_STATUS, GROUP_CAM_LIVE)), SIREN(FeatureArea.SECURITY, "NIS", WELCOME, Set.of(ChannelHelperCapability.class), ChannelGroup.SIGNAL, ChannelGroup.BATTERY, ChannelGroup.TIMESTAMP, new ChannelGroup(SirenChannelHelper.class, GROUP_SIREN)), - PRESENCE(FeatureArea.SECURITY, "NOC", HOME, - Set.of(EventCapability.class, PresenceCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, - ChannelGroup.EVENT, + PRESENCE(FeatureArea.SECURITY, "NOC", HOME, Set.of(PresenceCapability.class, ChannelHelperCapability.class), + ChannelGroup.SIGNAL, ChannelGroup.EVENT, new ChannelGroup(PresenceChannelHelper.class, GROUP_CAM_STATUS, GROUP_CAM_LIVE, GROUP_PRESENCE)), - DOORBELL(FeatureArea.SECURITY, "NDB", HOME, - Set.of(EventCapability.class, CameraCapability.class, ChannelHelperCapability.class), ChannelGroup.SIGNAL, + DOORBELL(FeatureArea.SECURITY, "NDB", HOME, Set.of(DoorbellCapability.class, ChannelHelperCapability.class), + ChannelGroup.SIGNAL, new ChannelGroup(CameraChannelHelper.class, GROUP_DOORBELL_STATUS, GROUP_DOORBELL_LIVE), new ChannelGroup(EventDoorbellChannelHelper.class, GROUP_DOORBELL_LAST_EVENT, GROUP_DOORBELL_SUB_EVENT)), @@ -208,9 +206,4 @@ public enum ModuleType { return ModuleType.AS_SET.stream().filter(mt -> mt.thingTypeUID.equals(thingTypeUID)).findFirst() .orElseThrow(() -> new IllegalArgumentException()); } - - public static ModuleType from(String apiName) { - return ModuleType.AS_SET.stream().filter(mt -> apiName.equals(mt.apiName)).findFirst() - .orElseThrow(() -> new IllegalArgumentException()); - } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/Event.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/Event.java index 305815c0c7c..09edf976b43 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/Event.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/Event.java @@ -61,8 +61,4 @@ public abstract class Event extends NAObject { return Stream.of(EventSubType.values()).filter(v -> v.types.contains(getEventType()) && v.subType == subType) .findFirst(); } - - public void setEventType(EventType type) { - this.type = type; - } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/WebhookEvent.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/WebhookEvent.java index eefa6a53815..21f4a245cf1 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/WebhookEvent.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/WebhookEvent.java @@ -13,6 +13,8 @@ package org.openhab.binding.netatmo.internal.api.dto; import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -29,9 +31,11 @@ import org.openhab.binding.netatmo.internal.deserialization.NAPushType; */ @NonNullByDefault public class WebhookEvent extends Event { - private @NonNullByDefault({}) NAPushType pushType; + private NAPushType pushType = NAPushType.UNKNOWN; private String homeId = ""; + private String deviceId = ""; private @Nullable String snapshotUrl; + private @Nullable String vignetteUrl; private NAObjectMap persons = new NAObjectMap<>(); // Webhook does not provide the event generation time, so we'll use the event reception time private ZonedDateTime time = ZonedDateTime.now(); @@ -63,4 +67,24 @@ public class WebhookEvent extends Event { public @Nullable String getSnapshotUrl() { return snapshotUrl; } + + public @Nullable String getVignetteUrl() { + return vignetteUrl; + } + + public List getNAObjectList() { + List result = new ArrayList<>(); + result.add(getCameraId()); + addNotBlank(result, homeId); + addNotBlank(result, deviceId); + addNotBlank(result, getCameraId()); + result.addAll(getPersons().keySet()); + return result; + } + + private void addNotBlank(List list, String value) { + if (!value.isBlank()) { + list.add(value); + } + } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushType.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushType.java index 096e8943b56..cac492ec68f 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushType.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushType.java @@ -23,6 +23,8 @@ import org.openhab.binding.netatmo.internal.api.data.ModuleType; */ @NonNullByDefault public class NAPushType { + public final static NAPushType UNKNOWN = new NAPushType(ModuleType.UNKNOWN, EventType.UNKNOWN); + private final ModuleType moduleType; private final EventType event; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushTypeDeserializer.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushTypeDeserializer.java index b99cb4db68c..78f5fc45140 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushTypeDeserializer.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/deserialization/NAPushTypeDeserializer.java @@ -18,11 +18,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.netatmo.internal.api.data.EventType; import org.openhab.binding.netatmo.internal.api.data.ModuleType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; /** * Specialized deserializer for push_type field @@ -31,21 +32,41 @@ import com.google.gson.JsonParseException; */ @NonNullByDefault class NAPushTypeDeserializer implements JsonDeserializer { + private final Logger logger = LoggerFactory.getLogger(NAPushTypeDeserializer.class); @Override - public @Nullable NAPushType deserialize(JsonElement json, Type clazz, JsonDeserializationContext context) - throws JsonParseException { - String string = json.getAsString(); - String[] elements = string.split("-"); - if (elements.length > 1) { - try { - ModuleType moduleType = ModuleType.from(elements[0]); - EventType eventType = EventType.valueOf(elements[1].toUpperCase()); - - return new NAPushType(moduleType, eventType); - } catch (IllegalArgumentException e) { - } + public @Nullable NAPushType deserialize(JsonElement json, Type clazz, JsonDeserializationContext context) { + final String string = json.getAsString(); + final String[] elements = string.split("-"); + ModuleType moduleType = ModuleType.UNKNOWN; + EventType eventType = EventType.UNKNOWN; + if (elements.length == 2) { + moduleType = fromNetatmoObject(elements[0]); + eventType = fromEvent(elements[1]); + } else { + logger.warn("Unexpected syntax received for push_type field : {}", string); } - throw new JsonParseException("Error deserializing : " + string); + if (moduleType.equals(ModuleType.UNKNOWN) || eventType.equals(EventType.UNKNOWN)) { + logger.warn("Unknown module or event type : {}, deserialized to '{}-{}'", string, moduleType, eventType); + } + return new NAPushType(moduleType, eventType); + } + + /** + * @param apiName : Netatmo Object name (NSD, NACamera...) + * @return moduletype value if found, or else Unknown + */ + public static ModuleType fromNetatmoObject(String apiName) { + return ModuleType.AS_SET.stream().filter(mt -> apiName.equals(mt.apiName)).findFirst() + .orElse(ModuleType.UNKNOWN); + } + + /** + * @param apiName : Netatmo Event name (hush, off, on ...) + * @return eventType value if found, or else Unknown + */ + public static EventType fromEvent(String apiName) { + return EventType.AS_SET.stream().filter(et -> apiName.equalsIgnoreCase(et.name())).findFirst() + .orElse(EventType.UNKNOWN); } } 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 380c6f5f249..ac7a9f0e375 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 @@ -32,6 +32,7 @@ import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus; import org.openhab.binding.netatmo.internal.api.dto.NAMain; import org.openhab.binding.netatmo.internal.api.dto.NAObject; import org.openhab.binding.netatmo.internal.api.dto.NAThing; +import org.openhab.binding.netatmo.internal.api.dto.WebhookEvent; import org.openhab.binding.netatmo.internal.handler.CommonInterface; import org.openhab.core.thing.Thing; import org.openhab.core.thing.binding.ThingHandlerService; @@ -74,6 +75,9 @@ public class Capability { if (newData instanceof Event) { updateEvent((Event) newData); } + if (newData instanceof WebhookEvent) { + updateWebhookEvent((WebhookEvent) newData); + } if (newData instanceof HomeEvent) { updateHomeEvent((HomeEvent) newData); } @@ -137,6 +141,10 @@ public class Capability { // do nothing by default, can be overridden by subclasses } + protected void updateWebhookEvent(WebhookEvent newData) { + // do nothing by default, can be overridden by subclasses + } + protected void updateNADevice(Device newData) { // do nothing by default, can be overridden by subclasses } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/DoorbellCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/DoorbellCapability.java new file mode 100644 index 00000000000..3bbc2e9fdbd --- /dev/null +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/DoorbellCapability.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.netatmo.internal.handler.capability; + +import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; +import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.*; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.netatmo.internal.api.dto.WebhookEvent; +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; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.ThingUID; +import org.openhab.core.types.UnDefType; + +/** + * {@link DoorbellCapability} give to handle Welcome Doorbell specifics + * + * @author Gaël L'hopital - Initial contribution + * + */ +@NonNullByDefault +public class DoorbellCapability extends CameraCapability { + private final ThingUID thingUid; + + public DoorbellCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider, + List channelHelpers) { + super(handler, descriptionProvider, channelHelpers); + thingUid = handler.getThing().getUID(); + } + + @Override + public void updateWebhookEvent(WebhookEvent event) { + super.updateWebhookEvent(event); + + handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_TYPE), + toStringType(event.getEventType())); + handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_TIME), + toDateTimeType(event.getTime())); + handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_SNAPSHOT), + toRawType(event.getSnapshotUrl())); + handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_SNAPSHOT_URL), + toStringType(event.getSnapshotUrl())); + handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_VIGNETTE), + toRawType(event.getVignetteUrl())); + handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_VIGNETTE_URL), + toStringType(event.getVignetteUrl())); + + String message = event.getName(); + handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_MESSAGE), + message == null || message.isBlank() ? UnDefType.NULL : toStringType(message)); + } +} diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/EventCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/EventCapability.java deleted file mode 100644 index aa4e294981d..00000000000 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/EventCapability.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2010-2022 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.netatmo.internal.handler.capability; - -import java.util.Optional; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.netatmo.internal.handler.ApiBridgeHandler; -import org.openhab.binding.netatmo.internal.handler.CommonInterface; -import org.openhab.binding.netatmo.internal.servlet.WebhookServlet; - -/** - * {@link EventCapability} is the base class for handlers subject to receive event notifications. - * This class registers to NetatmoServletService so it can be notified when an event arrives. - * - * @author Gaël L'hopital - Initial contribution - * - */ -@NonNullByDefault -public class EventCapability extends Capability { - private Optional webhook = Optional.empty(); - - public EventCapability(CommonInterface handler) { - super(handler); - } - - @Override - public void initialize() { - ApiBridgeHandler accountHandler = handler.getAccountHandler(); - if (accountHandler != null) { - webhook = accountHandler.getWebHookServlet(); - webhook.ifPresent(servlet -> servlet.registerDataListener(handler.getId(), this)); - } - } - - @Override - public void dispose() { - webhook.ifPresent(servlet -> servlet.unregisterDataListener(handler.getId())); - } -} diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java index 0b808fab93b..88c1aa2c51a 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java @@ -16,10 +16,12 @@ import java.util.List; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.netatmo.internal.handler.ApiBridgeHandler; import org.openhab.binding.netatmo.internal.handler.CommonInterface; import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper; import org.openhab.binding.netatmo.internal.handler.channelhelper.EventChannelHelper; import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider; +import org.openhab.binding.netatmo.internal.servlet.WebhookServlet; /** * {@link HomeSecurityThingCapability} is the ancestor of capabilities hosted by a security home @@ -33,6 +35,7 @@ public class HomeSecurityThingCapability extends Capability { protected final NetatmoDescriptionProvider descriptionProvider; protected final EventChannelHelper eventHelper; + private Optional webhook = Optional.empty(); protected Optional securityCapability = Optional.empty(); protected Optional homeCapability = Optional.empty(); @@ -51,5 +54,16 @@ public class HomeSecurityThingCapability extends Capability { super.initialize(); securityCapability = handler.getHomeCapability(SecurityCapability.class); homeCapability = handler.getHomeCapability(HomeCapability.class); + ApiBridgeHandler accountHandler = handler.getAccountHandler(); + if (accountHandler != null) { + webhook = accountHandler.getWebHookServlet(); + webhook.ifPresent(servlet -> servlet.registerDataListener(handler.getId(), this)); + } + } + + @Override + public void dispose() { + webhook.ifPresent(servlet -> servlet.unregisterDataListener(handler.getId())); + super.dispose(); } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java index 378081e2960..5720388d9be 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java @@ -13,13 +13,9 @@ package org.openhab.binding.netatmo.internal.servlet; import java.io.IOException; -import java.io.InputStream; import java.net.URI; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import java.util.Scanner; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpServletRequest; @@ -35,7 +31,7 @@ import org.openhab.binding.netatmo.internal.api.SecurityApi; import org.openhab.binding.netatmo.internal.api.dto.WebhookEvent; import org.openhab.binding.netatmo.internal.deserialization.NADeserializer; import org.openhab.binding.netatmo.internal.handler.ApiBridgeHandler; -import org.openhab.binding.netatmo.internal.handler.capability.EventCapability; +import org.openhab.binding.netatmo.internal.handler.capability.Capability; import org.osgi.service.http.HttpService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +45,7 @@ import org.slf4j.LoggerFactory; public class WebhookServlet extends NetatmoServlet { private static final long serialVersionUID = -354583910860541214L; - private final Map dataListeners = new ConcurrentHashMap<>(); + private final Map dataListeners = new ConcurrentHashMap<>(); private final Logger logger = LoggerFactory.getLogger(WebhookServlet.class); private final SecurityApi securityApi; private final NADeserializer deserializer; @@ -96,7 +92,7 @@ public class WebhookServlet extends NetatmoServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { replyQuick(resp); - processEvent(inputStreamToString(req.getInputStream())); + processEvent(new String(req.getInputStream().readAllBytes(), StandardCharsets.UTF_8)); } private void processEvent(String data) throws IOException { @@ -104,10 +100,7 @@ public class WebhookServlet extends NetatmoServlet { logger.debug("Event transmitted from restService : {}", data); try { WebhookEvent event = deserializer.deserialize(WebhookEvent.class, data); - List toBeNotified = new ArrayList<>(); - toBeNotified.add(event.getCameraId()); - toBeNotified.addAll(event.getPersons().keySet()); - notifyListeners(toBeNotified, event); + notifyListeners(event); } catch (NetatmoException e) { logger.debug("Error deserializing webhook data received : {}. {}", data, e.getMessage()); } @@ -119,31 +112,22 @@ public class WebhookServlet extends NetatmoServlet { resp.setContentType(MediaType.APPLICATION_JSON); resp.setHeader("Access-Control-Allow-Origin", "*"); resp.setHeader("Access-Control-Allow-Methods", HttpMethod.POST); - resp.setIntHeader("Access-Control-Max-Age", 3600); resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); + resp.setIntHeader("Access-Control-Max-Age", 3600); resp.getWriter().write(""); } - private String inputStreamToString(InputStream is) throws IOException { - String value = ""; - try (Scanner scanner = new Scanner(is)) { - scanner.useDelimiter("\\A"); - value = scanner.hasNext() ? scanner.next() : ""; - } - return value; - } - - private void notifyListeners(List tobeNotified, WebhookEvent event) { - tobeNotified.forEach(id -> { - EventCapability module = dataListeners.get(id); + private void notifyListeners(WebhookEvent event) { + event.getNAObjectList().forEach(id -> { + Capability module = dataListeners.get(id); if (module != null) { module.setNewData(event); } }); } - public void registerDataListener(String id, EventCapability eventCapability) { - dataListeners.put(id, eventCapability); + public void registerDataListener(String id, Capability capability) { + dataListeners.put(id, capability); } public void unregisterDataListener(String id) { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/utils/ChannelTypeUtils.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/utils/ChannelTypeUtils.java index 10f66999d95..518b1a8b4fc 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/utils/ChannelTypeUtils.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/utils/ChannelTypeUtils.java @@ -100,6 +100,6 @@ public class ChannelTypeUtils { return picture; } } - return UnDefType.UNDEF; + return UnDefType.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 38efb1219df..c0f5a687799 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 @@ -206,6 +206,7 @@ channel-type.netatmo.event-type.state.option.SD = SD card status changed channel-type.netatmo.event-type.state.option.ALIM = Power status changed channel-type.netatmo.event-type.state.option.ACCEPTED_CALL = Call is incoming channel-type.netatmo.event-type.state.option.INCOMING_CALL = Call has been answered by a user +channel-type.netatmo.event-type.state.option.RTC = Button pressed channel-type.netatmo.event-type.state.option.MISSED_CALL = Call has not been answered by anyone channel-type.netatmo.event-type.state.option.HUSH = Smoke detector status channel-type.netatmo.event-type.state.option.SMOKE = Smoke detection 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 09e33b0a364..5b60f29de17 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 @@ -356,6 +356,7 @@ + @@ -433,6 +434,7 @@