mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[netatmo] Adding Webhook event support for Doorbell (#12972)
* Adding Webhook event support for Doorbell * Adding doorbell rtc. * Enhancing NAPushType deserialization * Setting empty fields to NULL Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
parent
8ee86d786a
commit
a1a02f05bf
@ -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) {
|
||||
|
@ -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<EventType> AS_SET = EnumSet.allOf(EventType.class);
|
||||
|
||||
private final Set<ModuleType> appliesTo;
|
||||
|
||||
EventType(ModuleType... appliesTo) {
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<Person> 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<String> getNAObjectList() {
|
||||
List<String> 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<String> list, String value) {
|
||||
if (!value.isBlank()) {
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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<NAPushType> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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<ChannelHelper> 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));
|
||||
}
|
||||
}
|
@ -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<WebhookServlet> 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()));
|
||||
}
|
||||
}
|
@ -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<WebhookServlet> webhook = Optional.empty();
|
||||
protected Optional<SecurityCapability> securityCapability = Optional.empty();
|
||||
protected Optional<HomeCapability> 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();
|
||||
}
|
||||
}
|
||||
|
@ -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<String, EventCapability> dataListeners = new ConcurrentHashMap<>();
|
||||
private final Map<String, Capability> 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<String> 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<String> 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) {
|
||||
|
@ -100,6 +100,6 @@ public class ChannelTypeUtils {
|
||||
return picture;
|
||||
}
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
return UnDefType.NULL;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -356,6 +356,7 @@
|
||||
<option value="ALIM">Power status changed</option>
|
||||
<option value="ACCEPTED_CALL">Call is incoming</option>
|
||||
<option value="INCOMING_CALL">Call has been answered by a user</option>
|
||||
<option value="RTC">Button pressed</option>
|
||||
<option value="MISSED_CALL">Call has not been answered by anyone</option>
|
||||
<option value="HUSH">Smoke detector status</option>
|
||||
<option value="SMOKE">Smoke detection</option>
|
||||
@ -433,6 +434,7 @@
|
||||
<option value="ALIM"/>
|
||||
<option value="ACCEPTED_CALL"/>
|
||||
<option value="INCOMING_CALL"/>
|
||||
<option value="RTC"/>
|
||||
<option value="MISSED_CALL"/>
|
||||
</options>
|
||||
</event>
|
||||
|
Loading…
Reference in New Issue
Block a user