]> git.basschouten.com Git - openhab-addons.git/commitdiff
[netatmo] Add doorbell support (#12776)
authorGaël L'hopital <gael@lhopital.org>
Tue, 24 May 2022 19:56:55 +0000 (21:56 +0200)
committerGitHub <noreply@github.com>
Tue, 24 May 2022 19:56:55 +0000 (21:56 +0200)
* Adding doorbell handling to netatmo
Closes #8571

Signed-off-by: clinique <gael@lhopital.org>
31 files changed:
bundles/org.openhab.binding.netatmo/README.md
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/AircareApi.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/EnergyApi.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/HomeApi.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/SecurityApi.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/WeatherApi.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/EventType.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/ModuleType.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/HomeEvent.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/dto/HomeStatusModule.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/SecurityCapability.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/CameraChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/ChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/DoorbellChannelHelper.java [new file with mode: 0644]
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/EventChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/EventDoorbellChannelHelper.java [new file with mode: 0644]
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/EventPersonChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/PresenceChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/RoomChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/SetpointChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/Therm1ChannelHelper.java
bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/providers/NetatmoThingTypeProvider.java
bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties
bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo_it.properties
bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/channels.xml
bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/energy.xml
bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/thing/security.xml

index 9e7cb90c66dd15974f6c42fa14d711796202c3b9..9da4a57049ea451221717249f3b531ff9eda5ea4 100644 (file)
@@ -350,16 +350,16 @@ All these channels are read only.
 
 **Supported channels for the Room thing:**
 
-| Channel Group    | Channel Id            | Item Type            | Description                                             |
-|------------------|-----------------------|----------------------|---------------------------------------------------------|
-| room-temperature | value                 | Number:Temperature   | Current temperature in the room                         |
-| room-properties  | window-open           | Contact              | Windows of the room are opened                          |
-| room-properties  | anticipating          | Switch               | Anticipates next scheduled setpoint                     |
-| room-properties  | heating-power-request | Number:Dimensionless | Percentage of heating power                             |
-| setpoint         | value                 | Number:Temperature   | Thermostat temperature setpoint                         |
-| setpoint         | mode                  | String               | Chosen thermostat mode (home, frost guard, manual, max) |
-| setpoint         | start                 | DateTime             | Start time of the currently applied setpoint            |
-| setpoint         | end                   | DateTime             | End time of the currently applied setpoint              |
+| Channel Group | Channel Id            | Item Type            | Description                                             |
+|---------------|-----------------------|----------------------|---------------------------------------------------------|
+| temperature   | value                 | Number:Temperature   | Current temperature in the room                         |
+| properties    | window-open           | Contact              | Windows of the room are opened                          |
+| properties    | anticipating          | Switch               | Anticipates next scheduled setpoint                     |
+| properties    | heating-power-request | Number:Dimensionless | Percentage of heating power                             |
+| setpoint      | value                 | Number:Temperature   | Thermostat temperature setpoint                         |
+| setpoint      | mode                  | String               | Chosen thermostat mode (home, frost guard, manual, max) |
+| setpoint      | start                 | DateTime             | Start time of the currently applied setpoint            |
+| setpoint      | end                   | DateTime             | End time of the currently applied setpoint              |
 
 All these channels except setpoint and setpoint-mode are read only.
 
@@ -368,14 +368,14 @@ All these channels except setpoint and setpoint-mode are read only.
 
 **Supported channels for the thermostat module:**
 
-| Channel Group       | Channel Id         | Item Type            | Description                                      |
-|---------------------|--------------------|----------------------|--------------------------------------------------|
-| th-properties       | relay-status       | Contact              | Indicates if the boiler is currently heating     |
-| signal              | strength           | Number               | Signal strength (0 for no signal, 1 for weak...) |
-| signal              | value              | Number:Power         | Signal strength in dBm                           |
-| battery             | value              | Number               | Battery level                                    |
-| battery             | low-battery        | Switch               | Low battery                                      |
-| battery             | status             | String               | Description of the battery status (*)            |
+| Channel Group | Channel Id  | Item Type    | Description                                      |
+|---------------|-------------|--------------|--------------------------------------------------|
+| properties    | relay       | Contact      | Indicates if the boiler is currently heating     |
+| signal        | strength    | Number       | Signal strength (0 for no signal, 1 for weak...) |
+| signal        | value       | Number:Power | Signal strength in dBm                           |
+| battery       | value       | Number       | Battery level                                    |
+| battery       | low-battery | Switch       | Low battery                                      |
+| battery       | status      | String       | Description of the battery status (*)            |
 
 (*) Can be UNDEF on some modules
 
@@ -438,7 +438,7 @@ All these channels are read only.
 |                  | TAG_UNINSTALLED        | Triggered when a tag gets uninstalled                                                                                                                                            |  
 |                  | TAG_OPEN               | Triggered when an open event of a tag was detected                                                                                                                               |
 
-### Welcome and Presence Camera
+### Welcome, Presence and Doorbell Cameras
 
 Warnings:
 
@@ -503,6 +503,33 @@ Warnings:
 
 (*) This channel is configurable : low, poor, high.
 
+**Supported channels for the Welcome Doorbell thing:**
+
+| Channel Group | Channel ID        | Item Type    | Read/Write | Description                                                                                                                                 |
+|---------------|-------------------|--------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------|
+| status        | sd-card           | String       | Read-only  | State of the SD card                                                                                                                        |
+| status        | alim              | String       | Read-only  | State of the power connector                                                                                                                |
+| live          | picture           | Image        | Read-only  | Camera Live Snapshot                                                                                                                        |
+| live          | local-picture-url | String       | Read-only  | Local Url of the live snapshot for this camera                                                                                              |
+| live          | vpn-picture-url   | String       | Read-only  | Url of the live snapshot for this camera through Netatmo VPN.                                                                               |
+| signal        | strength          | Number       | Read-only  | Signal strength (0 for no signal, 1 for weak...)                                                                                            |
+| signal        | value             | Number:Power | Read-only  | Signal strength in dBm                                                                                                                      |
+| last-event    | type              | String       | Read-only  | Type of event                                                                                                                               |
+| last-event    | video-status      | String       | Read-only  | Status of the video (recording, deleted or available)                                                                                       |
+| last-event    | time              | DateTime     | Read-only  | Time of occurrence of event                                                                                                                 |
+| last-event    | local-video-url   | String       | Read-only  | If the last event (depending upon event type) in the home lead a snapshot picture, the corresponding local video URL will be available here |
+| last-event    | vpn-video-url     | String       | Read-only  | If the last event (depending upon event type) in the home lead a snapshot picture, the corresponding VPN video URL will be available here   |
+| sub-event     | type              | String       | Read-only  | Type of sub-event                                                                                                                           |
+| sub-event     | time              | DateTime     | Read-only  | Time of occurrence of sub-event                                                                                                             |
+| sub-event     | message           | String       | Read-only  | Message sent by Netatmo corresponding to given sub-event                                                                                    |
+| sub-event     | snapshot-url      | String       | Read-only  | Depending upon event type in the home, a snapshot picture of the corresponding local video URL will be available here                       |
+| sub-event     | vignette-url      | String       | Read-only  | A vignette representing the snapshot                                                                                                        |
+| sub-event     | snapshot          | Image        | Read-only  | picture of the snapshot                                                                                                                     |
+| sub-event     | vignet            | Image        | Read-only  | picture of the vignette                                                                                                                     |
+
+
+Note: live feeds either locally or via VPN are not available in Netatmo API.
+
 
 ### Welcome Person
 
@@ -515,18 +542,18 @@ Person things are automatically created in discovery process for all known perso
 
 **Supported channels for the Person thing:**
 
-| Channel Group  | Channel ID     | Item Type    | Description                                            |
-|----------------|----------------|--------------|--------------------------------------------------------|
-| person         | avatar-url     | String       | URL for the avatar of this person                      |
-| person         | avatar         | Image        | Avatar of this person                                  |
-| person         | at-home        | Switch       | Indicates if this person is known to be at home or not |
-| person         | last-seen      | DateTime     | Moment when this person was last seen                  |
-| person-event   | subtype        | String       | Sub-type of event                                      |
-| person-event   | message        | String       | Last event message from this person                    |
-| person-event   | time           | DateTime     | Moment of the last event for this person               |
-| person-event   | snapshot       | Image        | Picture of the last event for this person              |
-| person-event   | snapshot-url   | String       | URL for the picture of the last event for this person  |
-| person-event   | camera-id      | String       | ID of the camera that triggered the event              |
+| Channel Group | Channel ID   | Item Type | Description                                            |
+|---------------|--------------|-----------|--------------------------------------------------------|
+| person        | avatar-url   | String    | URL for the avatar of this person                      |
+| person        | avatar       | Image     | Avatar of this person                                  |
+| person        | at-home      | Switch    | Indicates if this person is known to be at home or not |
+| person        | last-seen    | DateTime  | Moment when this person was last seen                  |
+| last-event    | subtype      | String    | Sub-type of event                                      |
+| last-event    | message      | String    | Last event message from this person                    |
+| last-event    | time         | DateTime  | Moment of the last event for this person               |
+| last-event    | snapshot     | Image     | Picture of the last event for this person              |
+| last-event    | snapshot-url | String    | URL for the picture of the last event for this person  |
+| last-event    | camera-id    | String    | ID of the camera that triggered the event              |
 
 All these channels except at-home are read only.
 
index fc556be85fae256e9f798a5cf3a6ea37c5a320ec..c4a3d585fc4f078011f6263fe415fd5c0e24b778 100644 (file)
@@ -12,6 +12,8 @@
  */
 package org.openhab.binding.netatmo.internal;
 
+import java.util.Set;
+
 import org.eclipse.jdt.annotation.NonNullByDefault;
 
 /**
@@ -35,6 +37,7 @@ public class NetatmoBindingConstants {
 
     // Channel group ids
     public static final String GROUP_LAST_EVENT = "last-event";
+    public static final String GROUP_SUB_EVENT = "sub-event";
     public static final String GROUP_TEMPERATURE = "temperature";
     public static final String GROUP_HUMIDITY = "humidity";
     public static final String GROUP_AIR_QUALITY = "airquality";
@@ -51,22 +54,33 @@ public class NetatmoBindingConstants {
     public static final String GROUP_CAM_LIVE = "live";
     public static final String GROUP_PRESENCE = "presence";
     public static final String GROUP_PERSON = "person";
-    public static final String GROUP_PERSON_EVENT = "person-event";
-    public static final String GROUP_ROOM_TEMPERATURE = "room-temperature";
-    public static final String GROUP_ROOM_PROPERTIES = "room-properties";
-    public static final String GROUP_TH_PROPERTIES = "th-properties";
-    public static final String GROUP_TH_SETPOINT = "setpoint";
+    public static final String GROUP_PROPERTIES = "properties";
+    public static final String GROUP_SETPOINT = "setpoint";
     public static final String GROUP_LOCATION = "location";
 
     // Alternative extended groups
     public static final String OPTION_EXTENDED = "-extended";
     public static final String OPTION_OUTSIDE = "-outside";
+    public static final String OPTION_DOORBELL = "-doorbell";
+    public static final String OPTION_PERSON = "-person";
+    public static final String OPTION_ROOM = "-room";
+    public static final String OPTION_THERMOSTAT = "-thermostat";
+    public static final Set<String> GROUP_VARIATIONS = Set.of(OPTION_EXTENDED, OPTION_OUTSIDE, OPTION_DOORBELL,
+            OPTION_PERSON, OPTION_ROOM, OPTION_THERMOSTAT);
     public static final String GROUP_TYPE_TIMESTAMP_EXTENDED = GROUP_TIMESTAMP + OPTION_EXTENDED;
     public static final String GROUP_TYPE_BATTERY_EXTENDED = GROUP_BATTERY + OPTION_EXTENDED;
     public static final String GROUP_TYPE_PRESSURE_EXTENDED = GROUP_PRESSURE + OPTION_EXTENDED;
     public static final String GROUP_TYPE_TEMPERATURE_EXTENDED = GROUP_TEMPERATURE + OPTION_EXTENDED;
     public static final String GROUP_TYPE_AIR_QUALITY_EXTENDED = GROUP_AIR_QUALITY + OPTION_EXTENDED;
     public static final String GROUP_TYPE_TEMPERATURE_OUTSIDE = GROUP_TEMPERATURE + OPTION_OUTSIDE;
+    public static final String GROUP_DOORBELL_STATUS = GROUP_CAM_STATUS + OPTION_DOORBELL;
+    public static final String GROUP_DOORBELL_LIVE = GROUP_CAM_LIVE + OPTION_DOORBELL;
+    public static final String GROUP_DOORBELL_LAST_EVENT = GROUP_LAST_EVENT + OPTION_DOORBELL;
+    public static final String GROUP_DOORBELL_SUB_EVENT = GROUP_SUB_EVENT + OPTION_DOORBELL;
+    public static final String GROUP_PERSON_LAST_EVENT = GROUP_LAST_EVENT + OPTION_PERSON;
+    public static final String GROUP_TYPE_ROOM_TEMPERATURE = GROUP_TEMPERATURE + OPTION_ROOM;
+    public static final String GROUP_TYPE_ROOM_PROPERTIES = GROUP_PROPERTIES + OPTION_ROOM;
+    public static final String GROUP_TYPE_TH_PROPERTIES = GROUP_PROPERTIES + OPTION_THERMOSTAT;
 
     // Channel ids
     public static final String CHANNEL_VALUE = "value";
@@ -99,7 +113,7 @@ public class NetatmoBindingConstants {
     public static final String CHANNEL_SETPOINT_MODE = "mode";
     public static final String CHANNEL_SETPOINT_START_TIME = "start";
     public static final String CHANNEL_SETPOINT_END_TIME = "end";
-    public static final String CHANNEL_THERM_RELAY = "relay-status";
+    public static final String CHANNEL_THERM_RELAY = "relay";
     public static final String CHANNEL_ANTICIPATING = "anticipating";
     public static final String CHANNEL_ROOM_WINDOW_OPEN = "window-open";
     public static final String CHANNEL_ROOM_HEATING_POWER = "heating-power-request";
@@ -122,6 +136,8 @@ public class NetatmoBindingConstants {
     public static final String CHANNEL_EVENT_TIME = "time";
     public static final String CHANNEL_EVENT_SNAPSHOT = "snapshot";
     public static final String CHANNEL_EVENT_SNAPSHOT_URL = "snapshot-url";
+    public static final String CHANNEL_EVENT_VIGNETTE = "vignette";
+    public static final String CHANNEL_EVENT_VIGNETTE_URL = "vignette-url";
     public static final String CHANNEL_EVENT_VIDEO_VPN_URL = "vpn-video-url";
     public static final String CHANNEL_EVENT_VIDEO_LOCAL_URL = "local-video-url";
     public static final String CHANNEL_EVENT_PERSON_ID = "person-id";
index a2d41dbea3d4a180fda9050ae4e91cb0ee712273..82121dcdd50a8618c3317315a4e12555ce8f719b 100644 (file)
@@ -43,7 +43,7 @@ public class AircareApi extends RestManager {
      * @throws NetatmoException If fail to call the API, e.g. server error or deserializing
      */
     public StationDataResponse getHomeCoachData(@Nullable String deviceId) throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_HOMECOACH, PARAM_DEVICEID, deviceId);
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_HOMECOACH, PARAM_DEVICE_ID, deviceId);
         return get(uriBuilder, StationDataResponse.class);
     }
 
index f5a36405dbbfbb1c6dd6d77f9dc006685f5e91ef..b213fb592cb1c96a50dece7188c0c260ead415e4 100644 (file)
@@ -45,7 +45,7 @@ public class EnergyApi extends RestManager {
      *             response body
      */
     public void switchSchedule(String homeId, String scheduleId) throws NetatmoException {
-        UriBuilder uriBuilder = getAppUriBuilder(SUB_PATH_SWITCHSCHEDULE, PARAM_HOMEID, homeId, PARAM_SCHEDULEID,
+        UriBuilder uriBuilder = getAppUriBuilder(SUB_PATH_SWITCH_SCHEDULE, PARAM_HOME_ID, homeId, PARAM_SCHEDULE_ID,
                 scheduleId);
         post(uriBuilder, ApiResponse.Ok.class, null, null);
     }
@@ -63,7 +63,7 @@ public class EnergyApi extends RestManager {
      * @throws NetatmoCommunicationException when call failed, e.g. server error or cannot deserialize
      */
     public void setThermMode(String homeId, String mode) throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_SETTHERMMODE, PARAM_HOMEID, homeId, PARAM_MODE, mode);
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_SET_THERM_MODE, PARAM_HOME_ID, homeId, PARAM_MODE, mode);
         post(uriBuilder, ApiResponse.Ok.class, null, null);
     }
 
@@ -80,8 +80,8 @@ public class EnergyApi extends RestManager {
      */
     public void setThermpoint(String homeId, String roomId, SetpointMode mode, long endtime, double temp)
             throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_SETROOMTHERMPOINT, PARAM_HOMEID, homeId, PARAM_ROOMID, roomId,
-                PARAM_MODE, mode.apiDescriptor);
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_SET_ROOM_THERMPOINT, PARAM_HOME_ID, homeId, PARAM_ROOM_ID,
+                roomId, PARAM_MODE, mode.apiDescriptor);
         if (mode == SetpointMode.MANUAL || mode == SetpointMode.MAX) {
             uriBuilder.queryParam("endtime", endtime);
             if (mode == SetpointMode.MANUAL) {
index 5ce35d0f1893c58fb37867e0932fa91c08c42d20..ace5fffe414a7f8a78f11700b75dcf032a27c400 100644 (file)
@@ -44,7 +44,7 @@ public class HomeApi extends RestManager {
     }
 
     public @Nullable HomeStatus getHomeStatus(String homeId) throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_HOMESTATUS, PARAM_HOMEID, homeId);
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_HOMESTATUS, PARAM_HOME_ID, homeId);
 
         NAHomeStatusResponse response = get(uriBuilder, NAHomeStatusResponse.class);
         NAHomeStatus body = response.getBody();
@@ -58,10 +58,10 @@ public class HomeApi extends RestManager {
 
     public Collection<HomeData> getHomesData(@Nullable String homeId, @Nullable ModuleType type)
             throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_HOMES_DATA, PARAM_HOMEID, homeId);
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_HOMES_DATA, PARAM_HOME_ID, homeId);
 
         if (type != null) {
-            uriBuilder.queryParam(PARAM_GATEWAYTYPE, type.name());
+            uriBuilder.queryParam(PARAM_GATEWAY_TYPE, type.name());
         }
 
         HomeData.HomesDataResponse response = get(uriBuilder, HomeData.HomesDataResponse.class);
index a04f2fc7995c9f8ef613d5baa5ab22ae31cf3822..31ad916b1a2993df2f38a8ef0f1aa02dfaba2a17 100644 (file)
@@ -46,7 +46,7 @@ public class SecurityApi extends RestManager {
      * @throws NetatmoException If fail to call the API, e.g. server error or deserializing
      */
     public void dropWebhook() throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_DROPWEBHOOK);
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_DROP_WEBHOOK);
         post(uriBuilder, ApiResponse.Ok.class, null, null);
     }
 
@@ -57,13 +57,13 @@ public class SecurityApi extends RestManager {
      * @throws NetatmoException If fail to call the API, e.g. server error or deserializing
      */
     public boolean addwebhook(URI uri) throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_ADDWEBHOOK, PARAM_URL, uri.toString());
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_ADD_WEBHOOK, PARAM_URL, uri.toString());
         post(uriBuilder, ApiResponse.Ok.class, null, null);
         return true;
     }
 
     public Collection<HomeEvent> getPersonEvents(String homeId, String personId) throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GETEVENTS, PARAM_HOMEID, homeId, PARAM_PERSONID, personId,
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_EVENTS, PARAM_HOME_ID, homeId, PARAM_PERSON_ID, personId,
                 PARAM_OFFSET, 1);
         NAEventsDataResponse response = get(uriBuilder, NAEventsDataResponse.class);
         BodyResponse<Home> body = response.getBody();
@@ -77,10 +77,11 @@ public class SecurityApi extends RestManager {
         throw new NetatmoException("home should not be null");
     }
 
-    public Collection<HomeEvent> getCameraEvents(String homeId, String cameraId) throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GETEVENTS, PARAM_HOMEID, homeId, PARAM_DEVICEID, cameraId);
-        NAEventsDataResponse response = get(uriBuilder, NAEventsDataResponse.class);
-        BodyResponse<Home> body = response.getBody();
+    public Collection<HomeEvent> getCameraEvents(String homeId, String deviceId, String deviceType)
+            throws NetatmoException {
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_EVENTS, PARAM_HOME_ID, homeId, PARAM_DEVICE_ID, deviceId,
+                PARAM_DEVICES_TYPE, deviceType);
+        BodyResponse<Home> body = get(uriBuilder, NAEventsDataResponse.class).getBody();
         if (body != null) {
             Home home = body.getElement();
             if (home != null) {
index 5249a71689f4f190baf037c225f7e63ece123d97..bdb8905c1a57976d56d902400d08890da5bf084c 100644 (file)
@@ -56,7 +56,7 @@ public class WeatherApi extends RestManager {
      */
     private StationDataResponse getStationsData(@Nullable String deviceId, boolean getFavorites)
             throws NetatmoException {
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GETSTATION, PARAM_DEVICEID, deviceId, //
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_STATION, PARAM_DEVICE_ID, deviceId, //
                 PARAM_FAVORITES, getFavorites);
         StationDataResponse response = get(uriBuilder, StationDataResponse.class);
         return response;
@@ -127,8 +127,8 @@ public class WeatherApi extends RestManager {
     private MeasureBodyElem<?> getMeasure(String deviceId, @Nullable String moduleId, @Nullable String scale,
             String measureType) throws NetatmoException {
         // NAMeasuresResponse is not designed for optimize=false
-        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GETMEASURE, PARAM_DEVICEID, deviceId, "real_time", true,
-                "date_end", "last", "optimize", true, "type", measureType.toLowerCase(), PARAM_MODULEID, moduleId);
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_MEASURE, PARAM_DEVICE_ID, deviceId, "real_time", true,
+                "date_end", "last", "optimize", true, "type", measureType.toLowerCase(), PARAM_MODULE_ID, moduleId);
 
         if (scale != null) {
             uriBuilder.queryParam("scale", scale.toLowerCase());
index 6f48291f73906861a2b149079690056ade88fa99..d1560f66118dc89c7fbbde2402a3248edf3e7c64 100644 (file)
@@ -46,11 +46,14 @@ public enum EventType {
     @SerializedName("movement") // When the Indoor Camera detects motion
     MOVEMENT(ModuleType.WELCOME),
 
-    @SerializedName("human") // When the Indoor Camera detects human motion
-    HUMAN(ModuleType.WELCOME),
+    @SerializedName("human") // When the camera detects human motion
+    HUMAN(ModuleType.WELCOME, ModuleType.OUTDOOR, ModuleType.DOORBELL),
 
-    @SerializedName("animal") // When the Indoor Camera detects animal motion
-    ANIMAL(ModuleType.WELCOME),
+    @SerializedName("animal") // When the camera detects animal motion
+    ANIMAL(ModuleType.WELCOME, ModuleType.OUTDOOR),
+
+    @SerializedName("vehicle") // When the Outdoor Camera detects a car
+    VEHICLE(ModuleType.OUTDOOR),
 
     @SerializedName("new_module") // A new Module has been paired with the Indoor Camera
     NEW_MODULE(ModuleType.WELCOME),
@@ -67,10 +70,10 @@ public enum EventType {
     @SerializedName("module_end_update") // Module's firmware update is over
     MODULE_END_UPDATE(ModuleType.WELCOME),
 
-    @SerializedName("connection") // When the Camera connects to Netatmo servers
+    @SerializedName("connection") // When the camera connects to Netatmo servers
     CONNECTION(ModuleType.WELCOME, ModuleType.PRESENCE),
 
-    @SerializedName("disconnection") // When the Camera loses connection with Netatmo servers
+    @SerializedName("disconnection") // When the camera loses connection with Netatmo servers
     DISCONNECTION(ModuleType.WELCOME, ModuleType.PRESENCE),
 
     @SerializedName("on") // When Camera Monitoring is resumed
@@ -86,7 +89,16 @@ public enum EventType {
     SD(ModuleType.WELCOME, ModuleType.PRESENCE),
 
     @SerializedName("alim") // When Camera power supply status changes
-    ALIM(ModuleType.WELCOME, ModuleType.PRESENCE);
+    ALIM(ModuleType.WELCOME, ModuleType.PRESENCE),
+
+    @SerializedName("accepted_call") // When a call is incoming
+    ACCEPTED_CALL(ModuleType.DOORBELL),
+
+    @SerializedName("incoming_call") // When a call as been answered by a user
+    INCOMING_CALL(ModuleType.DOORBELL),
+
+    @SerializedName("missed_call") // When a call has not been answered by anyone
+    MISSED_CALL(ModuleType.DOORBELL);
 
     private final Set<ModuleType> appliesTo;
 
@@ -99,7 +111,7 @@ public enum EventType {
         return name().toLowerCase();
     }
 
-    public boolean appliesOn(ModuleType searched) {
+    public boolean validFor(ModuleType searched) {
         return appliesTo.contains(searched);
     }
 }
index 82a2c7e7b63e13bed61e819196f965a67f8a330b..5a0f9acb8ea304a9191e5925940a65d906712f33 100644 (file)
@@ -41,7 +41,9 @@ import org.openhab.binding.netatmo.internal.handler.channelhelper.BatteryChannel
 import org.openhab.binding.netatmo.internal.handler.channelhelper.BatteryExtChannelHelper;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.CameraChannelHelper;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper;
+import org.openhab.binding.netatmo.internal.handler.channelhelper.DoorbellChannelHelper;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.EventChannelHelper;
+import org.openhab.binding.netatmo.internal.handler.channelhelper.EventDoorbellChannelHelper;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.EventPersonChannelHelper;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.HomeEnergyChannelHelper;
 import org.openhab.binding.netatmo.internal.handler.channelhelper.HomeSecurityChannelHelper;
@@ -75,8 +77,8 @@ import com.google.gson.annotations.SerializedName;
  */
 @NonNullByDefault
 public enum ModuleType {
-    UNKNOWN(FeatureArea.NONE, null, null, List.of(), List.of()),
-    ACCOUNT(FeatureArea.NONE, null, null, List.of(), List.of()),
+    UNKNOWN(FeatureArea.NONE, "", null, List.of(), List.of()),
+    ACCOUNT(FeatureArea.NONE, "", null, List.of(), List.of()),
     @SerializedName("NAHome")
     HOME(FeatureArea.NONE, "NAHome", ACCOUNT,
             List.of(DeviceCapability.class, EventCapability.class, HomeCapability.class, ChannelHelperCapability.class),
@@ -92,14 +94,14 @@ public enum ModuleType {
     @SerializedName("NOC")
     PRESENCE(FeatureArea.SECURITY, "NOC", HOME,
             List.of(EventCapability.class, PresenceCapability.class, ChannelHelperCapability.class),
-            List.of(CameraChannelHelper.class, PresenceChannelHelper.class, SignalChannelHelper.class,
-                    EventChannelHelper.class)),
+            List.of(PresenceChannelHelper.class, SignalChannelHelper.class, EventChannelHelper.class)),
     @SerializedName("NIS")
     SIREN(FeatureArea.SECURITY, "NIS", HOME, List.of(ChannelHelperCapability.class),
             List.of(BatteryChannelHelper.class, TimestampChannelHelper.class, SignalChannelHelper.class)),
     @SerializedName("NDB")
-    DOORBELL(FeatureArea.SECURITY, "NDB", HOME, List.of(ChannelHelperCapability.class),
-            List.of(SignalChannelHelper.class)),
+    DOORBELL(FeatureArea.SECURITY, "NDB", HOME,
+            List.of(EventCapability.class, CameraCapability.class, ChannelHelperCapability.class),
+            List.of(DoorbellChannelHelper.class, SignalChannelHelper.class, EventDoorbellChannelHelper.class)),
     @SerializedName("NAMain")
     WEATHER_STATION(FeatureArea.WEATHER, "NAMain", ACCOUNT,
             List.of(DeviceCapability.class, WeatherCapability.class, MeasureCapability.class,
@@ -156,9 +158,9 @@ public enum ModuleType {
     public final List<Class<? extends Capability>> capabilities;
     public final ThingTypeUID thingTypeUID;
     public final FeatureArea feature;
-    public final @Nullable String apiName;
+    public final String apiName;
 
-    ModuleType(FeatureArea feature, @Nullable String apiName, @Nullable ModuleType bridge,
+    ModuleType(FeatureArea feature, String apiName, @Nullable ModuleType bridge,
             List<Class<? extends Capability>> capabilities, List<Class<? extends ChannelHelper>> helpers) {
         this.channelHelpers = helpers;
         this.bridgeType = bridge;
index 69756ac2b193e89896db8d7d8481b1b585d2406f..80e8ef6cc86c1f434675d5e90422dd301a92f983 100644 (file)
@@ -125,30 +125,31 @@ public class NetatmoConstants {
     public static final String SUB_PATH_PERSON_AWAY = "setpersonsaway";
     public static final String SUB_PATH_PERSON_HOME = "setpersonshome";
     public static final String SUB_PATH_HOMES_DATA = "homesdata";
-    public static final String SUB_PATH_ADDWEBHOOK = "addwebhook";
-    public static final String SUB_PATH_DROPWEBHOOK = "dropwebhook";
-    public static final String SUB_PATH_SETROOMTHERMPOINT = "setroomthermpoint";
-    public static final String SUB_PATH_SETTHERMMODE = "setthermmode";
-    public static final String SUB_PATH_SWITCHSCHEDULE = "switchschedule";
-    public static final String SUB_PATH_GETSTATION = "getstationsdata";
-    public static final String SUB_PATH_GETMEASURE = "getmeasure";
+    public static final String SUB_PATH_ADD_WEBHOOK = "addwebhook";
+    public static final String SUB_PATH_DROP_WEBHOOK = "dropwebhook";
+    public static final String SUB_PATH_SET_ROOM_THERMPOINT = "setroomthermpoint";
+    public static final String SUB_PATH_SET_THERM_MODE = "setthermmode";
+    public static final String SUB_PATH_SWITCH_SCHEDULE = "switchschedule";
+    public static final String SUB_PATH_GET_STATION = "getstationsdata";
+    public static final String SUB_PATH_GET_MEASURE = "getmeasure";
     public static final String SUB_PATH_HOMESTATUS = "homestatus";
     public static final String SUB_PATH_HOMECOACH = "gethomecoachsdata";
-    public static final String SUB_PATH_GETEVENTS = "getevents";
+    public static final String SUB_PATH_GET_EVENTS = "getevents";
     public static final String SUB_PATH_PING = "ping";
     public static final String SUB_PATH_CHANGESTATUS = "changestatus";
-    public static final String PARAM_DEVICEID = "device_id";
-    public static final String PARAM_MODULEID = "module_id";
-    public static final String PARAM_HOMEID = "home_id";
-    public static final String PARAM_ROOMID = "room_id";
-    public static final String PARAM_PERSONID = "person_id";
-    public static final String PARAM_SCHEDULEID = "schedule_id";
+    public static final String PARAM_DEVICE_ID = "device_id";
+    public static final String PARAM_MODULE_ID = "module_id";
+    public static final String PARAM_HOME_ID = "home_id";
+    public static final String PARAM_ROOM_ID = "room_id";
+    public static final String PARAM_PERSON_ID = "person_id";
+    public static final String PARAM_SCHEDULE_ID = "schedule_id";
     public static final String PARAM_OFFSET = "offset";
-    public static final String PARAM_GATEWAYTYPE = "gateway_types";
+    public static final String PARAM_GATEWAY_TYPE = "gateway_types";
     public static final String PARAM_MODE = "mode";
     public static final String PARAM_URL = "url";
     public static final String PARAM_FAVORITES = "get_favorites";
     public static final String PARAM_STATUS = "status";
+    public static final String PARAM_DEVICES_TYPE = "device_types";
 
     // Autentication process params
     public static final String PARAM_ERROR = "error";
index 6a56c2cbc4a12c9ffdf451939bc49e36cfd424a4..ebb0ade4e4b583efd062651664ad1a70a3946a93 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.binding.netatmo.internal.api.dto;
 
 import java.time.ZonedDateTime;
+import java.util.List;
 import java.util.Optional;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -40,9 +41,11 @@ public class HomeEvent extends Event {
     private @Nullable String personId;
     private EventCategory category = EventCategory.UNKNOWN;
     private @Nullable Snapshot snapshot;
+    private @Nullable Snapshot vignette;
     private @Nullable String videoId;
     private VideoStatus videoStatus = VideoStatus.UNKNOWN;
     private boolean isArrival;
+    private List<HomeEvent> subevents = List.of();
 
     @Override
     public ZonedDateTime getTime() {
@@ -90,7 +93,20 @@ public class HomeEvent extends Event {
 
     @Override
     public @Nullable String getSnapshotUrl() {
-        Snapshot localSnap = snapshot;
-        return localSnap != null ? localSnap.getUrl() : null;
+        Snapshot image = snapshot;
+        return image != null ? image.getUrl() : null;
+    }
+
+    public @Nullable String getVignetteUrl() {
+        Snapshot image = vignette;
+        return image != null ? image.getUrl() : null;
+    }
+
+    public List<HomeEvent> getSubevents() {
+        return subevents;
+    }
+
+    public @Nullable Snapshot getVignette() {
+        return vignette;
     }
 }
index ac53c2a34eadbc06e46010790fc89fd514d9a61f..219b47d6b5349d3beef59d7e44b5ddb81f60bc4e 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Optional;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.netatmo.internal.api.data.ModuleType;
 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.AlimentationStatus;
 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.BatteryState;
 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode;
@@ -73,7 +74,8 @@ public class HomeStatusModule extends NAThing {
 
     public State getMonitoring() {
         OnOffType localStatus = monitoring;
-        return localStatus != null ? localStatus : UnDefType.NULL;
+        return localStatus != null ? localStatus // Monitoring is always active on Doorbell
+                : getType().equals(ModuleType.DOORBELL) ? OnOffType.ON : UnDefType.NULL;
     }
 
     public FloodLightMode getFloodlight() {
index 8f6246dbc18be221c06ed0c4d605249d2f9defc9..5e4b948992d42f4d31bb172719c1a302071ca058 100644 (file)
@@ -97,9 +97,11 @@ public class CameraCapability extends HomeSecurityThingCapability {
     public List<NAObject> updateReadings() {
         List<NAObject> result = new ArrayList<>();
         securityCapability.ifPresent(cap -> {
-            Collection<HomeEvent> events = cap.getCameraEvents(handler.getId());
+            Collection<HomeEvent> events = cap.getCameraEvents(handler.getId(), moduleType.apiName);
             if (!events.isEmpty()) {
-                result.add(events.iterator().next());
+                HomeEvent event = events.iterator().next();
+                result.add(event);
+                result.addAll(event.getSubevents());
             }
         });
         return result;
index 3ef4d112f67faa767ca43a88bf34b156c312976e..f03d1306f83d4108225a002106a620860f6fa914 100644 (file)
@@ -51,7 +51,7 @@ public class PersonCapability extends HomeSecurityThingCapability {
     public PersonCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider,
             List<ChannelHelper> channelHelpers) {
         super(handler, descriptionProvider, channelHelpers);
-        this.cameraChannelUID = new ChannelUID(thing.getUID(), GROUP_PERSON_EVENT, CHANNEL_EVENT_CAMERA_ID);
+        this.cameraChannelUID = new ChannelUID(thing.getUID(), GROUP_PERSON_LAST_EVENT, CHANNEL_EVENT_CAMERA_ID);
     }
 
     @Override
@@ -78,7 +78,7 @@ public class PersonCapability extends HomeSecurityThingCapability {
         EventType eventType = event.getEventType();
         ZonedDateTime localLast = lastEventTime;
         ZonedDateTime eventTime = event.getTime();
-        if ((localLast != null && !eventTime.isAfter(localLast)) || !eventType.appliesOn(ModuleType.PERSON)) {
+        if ((localLast != null && !eventTime.isAfter(localLast)) || !eventType.validFor(ModuleType.PERSON)) {
             return; // ignore incoming events if they are deprecated
         }
         lastEventTime = eventTime;
index b488348dd858159aaf3411f80914350ce6cc671c..c19757d4aec2e000b5686348623d18080ec7786a 100644 (file)
@@ -99,10 +99,10 @@ class SecurityCapability extends RestCapability<SecurityApi> {
                 });
     }
 
-    public Collection<HomeEvent> getCameraEvents(String cameraId) {
+    public Collection<HomeEvent> getCameraEvents(String cameraId, String deviceType) {
         return getApi().map(api -> {
             try {
-                return api.getCameraEvents(handler.getId(), cameraId);
+                return api.getCameraEvents(handler.getId(), cameraId, deviceType);
             } catch (NetatmoException e) {
                 logger.warn("Error retrieving last events of camera '{}' : {}", cameraId, e.getMessage());
                 return null;
index db73b2dee278687d386b680a0d3506d911ac0ce4..9b63f121853012cb96eaa410c7dff77fbfb93908 100644 (file)
@@ -39,7 +39,11 @@ public class CameraChannelHelper extends ChannelHelper {
     private @Nullable String localUrl;
 
     public CameraChannelHelper() {
-        super(GROUP_CAM_STATUS, GROUP_CAM_LIVE);
+        this(GROUP_CAM_STATUS, GROUP_CAM_LIVE);
+    }
+
+    protected CameraChannelHelper(String... providedGroups) {
+        super(providedGroups);
     }
 
     public void setUrls(String vpnUrl, @Nullable String localUrl) {
index a5c9adbef073f2ebc66947366cd2856caaac9f15..246380bebb66304c825854e8a337b613267504d9 100644 (file)
@@ -20,6 +20,7 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.MeasureClass;
 import org.openhab.binding.netatmo.internal.api.dto.Dashboard;
 import org.openhab.binding.netatmo.internal.api.dto.Event;
+import org.openhab.binding.netatmo.internal.api.dto.HomeEvent;
 import org.openhab.binding.netatmo.internal.api.dto.NAObject;
 import org.openhab.binding.netatmo.internal.api.dto.NAThing;
 import org.openhab.binding.netatmo.internal.providers.NetatmoThingTypeProvider;
@@ -57,6 +58,12 @@ public abstract class ChannelHelper {
         State result = null;
         if (channelGroups.isEmpty() || (groupId != null && channelGroups.contains(groupId))) {
             NAObject localData = data;
+            if (localData instanceof HomeEvent) {
+                result = internalGetHomeEvent(channelId, groupId, (HomeEvent) localData);
+                if (result != null) {
+                    return result;
+                }
+            }
             if (localData instanceof Event) {
                 result = internalGetEvent(channelId, (Event) localData);
                 if (result != null) {
@@ -108,6 +115,10 @@ public abstract class ChannelHelper {
         return null;
     }
 
+    protected @Nullable State internalGetHomeEvent(String channelId, @Nullable String groupId, HomeEvent event) {
+        return null;
+    }
+
     public Set<String> getChannelGroupTypes() {
         return channelGroupTypes;
     }
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/DoorbellChannelHelper.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/DoorbellChannelHelper.java
new file mode 100644 (file)
index 0000000..9dee8b9
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * 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.channelhelper;
+
+import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link DoorbellChannelHelper} handles specific channels of doorbells
+ *
+ * @author Gaël L'hopital - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class DoorbellChannelHelper extends CameraChannelHelper {
+
+    public DoorbellChannelHelper() {
+        super(GROUP_DOORBELL_STATUS, GROUP_DOORBELL_LIVE);
+    }
+}
index a5fe003f7e5b7d04fce18fe270a90e332e2214b6..e8b8fdc6ff8d9a4e2a820c850fdd464834907d5d 100644 (file)
@@ -36,14 +36,14 @@ import org.openhab.core.types.UnDefType;
 public class EventChannelHelper extends ChannelHelper {
     private boolean isLocal;
     private @Nullable String vpnUrl, localUrl;
-    private ModuleType moduleType = ModuleType.UNKNOWN;
+    protected ModuleType moduleType = ModuleType.UNKNOWN;
 
     public EventChannelHelper() {
         this(GROUP_LAST_EVENT);
     }
 
-    protected EventChannelHelper(String groupName) {
-        super(groupName);
+    protected EventChannelHelper(String... providedGroups) {
+        super(providedGroups);
     }
 
     public void setModuleType(ModuleType moduleType) {
@@ -60,7 +60,7 @@ public class EventChannelHelper extends ChannelHelper {
     public void setNewData(@Nullable NAObject data) {
         if (data instanceof Event) {
             Event event = (Event) data;
-            if (!event.getEventType().appliesOn(moduleType)) {
+            if (!event.getEventType().validFor(moduleType)) {
                 return;
             }
         }
@@ -87,16 +87,18 @@ public class EventChannelHelper extends ChannelHelper {
             case CHANNEL_EVENT_SNAPSHOT_URL:
                 return toStringType(event.getSnapshotUrl());
         }
-        if (event instanceof HomeEvent) {
-            HomeEvent homeEvent = (HomeEvent) event;
-            switch (channelId) {
-                case CHANNEL_EVENT_VIDEO_STATUS:
-                    return homeEvent.getVideoId() != null ? toStringType(homeEvent.getVideoStatus()) : UnDefType.NULL;
-                case CHANNEL_EVENT_VIDEO_LOCAL_URL:
-                    return getStreamURL(true, homeEvent.getVideoId(), homeEvent.getVideoStatus());
-                case CHANNEL_EVENT_VIDEO_VPN_URL:
-                    return getStreamURL(false, homeEvent.getVideoId(), homeEvent.getVideoStatus());
-            }
+        return null;
+    }
+
+    @Override
+    protected @Nullable State internalGetHomeEvent(String channelId, @Nullable String groupId, HomeEvent event) {
+        switch (channelId) {
+            case CHANNEL_EVENT_VIDEO_STATUS:
+                return event.getVideoId() != null ? toStringType(event.getVideoStatus()) : UnDefType.NULL;
+            case CHANNEL_EVENT_VIDEO_LOCAL_URL:
+                return getStreamURL(true, event.getVideoId(), event.getVideoStatus());
+            case CHANNEL_EVENT_VIDEO_VPN_URL:
+                return getStreamURL(false, event.getVideoId(), event.getVideoStatus());
         }
         return null;
     }
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/EventDoorbellChannelHelper.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/EventDoorbellChannelHelper.java
new file mode 100644 (file)
index 0000000..f024fc7
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ * 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.channelhelper;
+
+import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
+import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.netatmo.internal.api.dto.HomeEvent;
+import org.openhab.core.library.types.DateTimeType;
+import org.openhab.core.types.State;
+
+/**
+ * The {@link EventDoorbellChannelHelper} handles specific channels of doorbell events
+ *
+ * @author Gaël L'hopital - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class EventDoorbellChannelHelper extends EventChannelHelper {
+
+    public EventDoorbellChannelHelper() {
+        super(GROUP_DOORBELL_LAST_EVENT, GROUP_DOORBELL_SUB_EVENT);
+    }
+
+    @Override
+    protected @Nullable State internalGetHomeEvent(String channelId, @Nullable String groupId, HomeEvent event) {
+        if (groupId != null && GROUP_DOORBELL_SUB_EVENT.startsWith(groupId)) {
+            switch (channelId) {
+                case CHANNEL_EVENT_TYPE:
+                    return toStringType(event.getEventType());
+                case CHANNEL_EVENT_TIME:
+                    return new DateTimeType(event.getTime());
+                case CHANNEL_EVENT_MESSAGE:
+                    return toStringType(event.getName());
+                case CHANNEL_EVENT_SNAPSHOT:
+                    return toRawType(event.getSnapshotUrl());
+                case CHANNEL_EVENT_SNAPSHOT_URL:
+                    return toStringType(event.getSnapshotUrl());
+                case CHANNEL_EVENT_VIGNETTE:
+                    return toRawType(event.getVignetteUrl());
+                case CHANNEL_EVENT_VIGNETTE_URL:
+                    return toStringType(event.getVignetteUrl());
+            }
+        }
+        return super.internalGetHomeEvent(channelId, groupId, event);
+    }
+}
index ff4054be66724659cb6c2d1954ce95a67b0362b5..bc46b3dae8f319abb136634b4b68a1eb72464209 100644 (file)
@@ -14,10 +14,11 @@ package org.openhab.binding.netatmo.internal.handler.channelhelper;
 
 import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
 
+import java.util.Set;
+
 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.openhab.binding.netatmo.internal.api.dto.Event;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.types.State;
@@ -30,16 +31,16 @@ import org.openhab.core.types.State;
  */
 @NonNullByDefault
 public class EventPersonChannelHelper extends EventChannelHelper {
+
     public EventPersonChannelHelper() {
-        super(GROUP_PERSON_EVENT);
+        super(GROUP_PERSON_LAST_EVENT);
     }
 
     @Override
     protected @Nullable State internalGetEvent(String channelId, Event event) {
         EventType eventType = event.getEventType();
-        if (eventType.appliesOn(ModuleType.PERSON) && CHANNEL_PERSON_AT_HOME.equals(channelId)) {
-            return OnOffType.from(EventType.PERSON.equals(eventType) || EventType.PERSON_HOME.equals(eventType));
-        }
-        return super.internalGetEvent(channelId, event);
+        return eventType.validFor(moduleType) && CHANNEL_PERSON_AT_HOME.equals(channelId)
+                ? OnOffType.from(Set.of(EventType.PERSON, EventType.PERSON_HOME).contains(eventType))
+                : super.internalGetEvent(channelId, event);
     }
 }
index c2449c95391d7db656cb7a4f9ad9e57109adbeaf..13ddd1c53ea12f0337dc2497c785ac806327e26b 100644 (file)
@@ -29,9 +29,10 @@ import org.openhab.core.types.State;
  *
  */
 @NonNullByDefault
-public class PresenceChannelHelper extends ChannelHelper {
+public class PresenceChannelHelper extends CameraChannelHelper {
+
     public PresenceChannelHelper() {
-        super(GROUP_PRESENCE);
+        super(GROUP_CAM_STATUS, GROUP_CAM_LIVE, GROUP_PRESENCE);
     }
 
     @Override
index 2914d2e920c9fe4834565026e44e2f0885bfa820..33bb81cba65273cb6e07daca0ff946fe39a52ed3 100644 (file)
@@ -33,7 +33,7 @@ import org.openhab.core.types.State;
 public class RoomChannelHelper extends ChannelHelper {
 
     public RoomChannelHelper() {
-        super(GROUP_ROOM_PROPERTIES, GROUP_ROOM_TEMPERATURE);
+        super(GROUP_TYPE_ROOM_TEMPERATURE, GROUP_TYPE_ROOM_PROPERTIES);
     }
 
     @Override
index 56d9f8744fc0c04465aeab3c7e92c706bfedd316..81b901cd693d33843be4e9870b143fa2d9927b91 100644 (file)
@@ -33,7 +33,7 @@ import org.openhab.core.types.UnDefType;
 public class SetpointChannelHelper extends ChannelHelper {
 
     public SetpointChannelHelper() {
-        super(GROUP_TH_SETPOINT);
+        super(GROUP_SETPOINT);
     }
 
     @Override
index 5cb2a2bfd9c1cb72a33641216bebf677f5b91faa..c78806abf5f6172d8a7480b071b7deae0a74f509 100644 (file)
@@ -31,7 +31,7 @@ import org.openhab.core.types.State;
 public class Therm1ChannelHelper extends ChannelHelper {
 
     public Therm1ChannelHelper() {
-        super(GROUP_TH_PROPERTIES);
+        super(GROUP_TYPE_TH_PROPERTIES);
     }
 
     @Override
index 7f5608beb3c219517acf86aac3fcd05bb3565c41..c94ef91802e2dfc996c708f856b1ede68c364da7 100644 (file)
@@ -99,6 +99,10 @@ public class NetatmoThingTypeProvider implements ThingTypeProvider {
     }
 
     public static String toGroupName(String groupeTypeName) {
-        return groupeTypeName.replace(OPTION_EXTENDED, "").replace(OPTION_OUTSIDE, "");
+        String result = groupeTypeName;
+        for (String variation : GROUP_VARIATIONS) {
+            result = result.replace(variation, "");
+        }
+        return result;
     }
 }
index c24c75c094235ec63145f2474f8b461d183da539..aa356e5a3f031a9db601b4037b955ddf980e9d43 100644 (file)
@@ -18,6 +18,19 @@ channel-group-type.netatmo.energy.label = Home Energy
 channel-group-type.netatmo.energy.channel.end.label = Mode End
 channel-group-type.netatmo.energy.channel.end.description = End time of the currently applied setpoint.
 channel-group-type.netatmo.humidity.label = Humidity
+channel-group-type.netatmo.last-event-doorbell.label = Last Event
+channel-group-type.netatmo.last-event-doorbell.channel.local-video-url.label = Video Local URL
+channel-group-type.netatmo.last-event-doorbell.channel.local-video-url.description = Local URL of the event recording.
+channel-group-type.netatmo.last-event-doorbell.channel.time.label = Event Timestamp
+channel-group-type.netatmo.last-event-doorbell.channel.time.description = Moment when event occurred.
+channel-group-type.netatmo.last-event-doorbell.channel.vpn-video-url.label = Video VPN URL
+channel-group-type.netatmo.last-event-doorbell.channel.vpn-video-url.description = URL of the event recording through Netatmo VPN.
+channel-group-type.netatmo.last-event-person.label = Last Event
+channel-group-type.netatmo.last-event-person.channel.message.description = Last event message from this person.
+channel-group-type.netatmo.last-event-person.channel.snapshot.description = Picture of the last event for this person.
+channel-group-type.netatmo.last-event-person.channel.snapshot-url.description = URL for the picture of the last event for this person.
+channel-group-type.netatmo.last-event-person.channel.time.label = Person Timestamp
+channel-group-type.netatmo.last-event-person.channel.time.description = Moment of the last event for this person.
 channel-group-type.netatmo.last-event.label = Last Event
 channel-group-type.netatmo.last-event.channel.local-video-url.label = Video Local URL
 channel-group-type.netatmo.last-event.channel.local-video-url.description = Local URL of the event recording.
@@ -25,6 +38,9 @@ channel-group-type.netatmo.last-event.channel.time.label = Event Timestamp
 channel-group-type.netatmo.last-event.channel.time.description = Moment when event occurred.
 channel-group-type.netatmo.last-event.channel.vpn-video-url.label = Video VPN URL
 channel-group-type.netatmo.last-event.channel.vpn-video-url.description = URL of the event recording through Netatmo VPN.
+channel-group-type.netatmo.live-doorbell.label = Live Monitoring
+channel-group-type.netatmo.live-doorbell.channel.local-picture-url.label = Live Snapshot Local URL
+channel-group-type.netatmo.live-doorbell.channel.local-picture-url.description = Local URL of the live snapshot for this camera.
 channel-group-type.netatmo.live.label = Live Monitoring
 channel-group-type.netatmo.live.channel.local-picture-url.label = Live Snapshot Local URL
 channel-group-type.netatmo.live.channel.local-picture-url.description = Local URL of the live snapshot for this camera.
@@ -36,12 +52,6 @@ channel-group-type.netatmo.live.channel.vpn-stream-url.label = Live Stream VPN U
 channel-group-type.netatmo.live.channel.vpn-stream-url.description = URL of the live stream for this camera through Netatmo VPN.
 channel-group-type.netatmo.location.label = Location
 channel-group-type.netatmo.noise.label = Noise
-channel-group-type.netatmo.person-event.label = Last Event
-channel-group-type.netatmo.person-event.channel.message.description = Last event message from this person.
-channel-group-type.netatmo.person-event.channel.snapshot.description = Picture of the last event for this person.
-channel-group-type.netatmo.person-event.channel.snapshot-url.description = URL for the picture of the last event for this person.
-channel-group-type.netatmo.person-event.channel.time.label = Person Timestamp
-channel-group-type.netatmo.person-event.channel.time.description = Moment of the last event for this person.
 channel-group-type.netatmo.person.label = Person
 channel-group-type.netatmo.person.channel.last-seen.label = Last Seen
 channel-group-type.netatmo.person.channel.last-seen.description = Moment when this person was last seen.
@@ -55,8 +65,8 @@ channel-group-type.netatmo.rain.channel.sum-1.label = Rain 1h
 channel-group-type.netatmo.rain.channel.sum-1.description = Quantity of water over last hour.
 channel-group-type.netatmo.rain.channel.sum-24.label = Rain 24h
 channel-group-type.netatmo.rain.channel.sum-24.description = Quantity of water during the current day.
-channel-group-type.netatmo.room-properties.label = Room Status
-channel-group-type.netatmo.room-temperature.label = Room Temperature
+channel-group-type.netatmo.properties-room.label = Room Status
+channel-group-type.netatmo.temperature-room.label = Room Temperature
 channel-group-type.netatmo.security.label = Home Security
 channel-group-type.netatmo.setpoint.label = Setpoint
 channel-group-type.netatmo.setpoint.channel.end.label = Setpoint End
@@ -64,7 +74,15 @@ channel-group-type.netatmo.setpoint.channel.end.description = End time of the cu
 channel-group-type.netatmo.setpoint.channel.start.label = Setpoint Start
 channel-group-type.netatmo.setpoint.channel.start.description = Start time of the currently applied setpoint.
 channel-group-type.netatmo.signal.label = Signal
+channel-group-type.netatmo.status-doorbell.label = Camera Status
 channel-group-type.netatmo.status.label = Camera Status
+channel-group-type.netatmo.sub-event-doorbell.label = Sub Event
+channel-group-type.netatmo.sub-event-doorbell.channel.time.label = Sub-Event Timestamp
+channel-group-type.netatmo.sub-event-doorbell.channel.time.description = Moment when then sub-event occurred.
+channel-group-type.netatmo.sub-event-doorbell.channel.vignette.label = Vignette
+channel-group-type.netatmo.sub-event-doorbell.channel.vignette.description = Vignette of the Snapshot.
+channel-group-type.netatmo.sub-event-doorbell.channel.vignette-url.label = Vignette URL
+channel-group-type.netatmo.sub-event-doorbell.channel.vignette-url.description = URL of the vignette.
 channel-group-type.netatmo.temperature-extended.label = Temperature
 channel-group-type.netatmo.temperature-extended.channel.max-time.label = Today Max Timestamp
 channel-group-type.netatmo.temperature-extended.channel.max-time.description = Moment when temperature was measured at its maximum today.
@@ -82,7 +100,7 @@ channel-group-type.netatmo.temperature.channel.max-time.label = Today Max Timest
 channel-group-type.netatmo.temperature.channel.max-time.description = Moment when temperature was measured at its maximum today.
 channel-group-type.netatmo.temperature.channel.min-time.label = Today Min Timestamp
 channel-group-type.netatmo.temperature.channel.min-time.description = Moment when temperature was measured at its minimum today.
-channel-group-type.netatmo.th-properties.label = Thermostat
+channel-group-type.netatmo.properties-thermostat.label = Thermostat
 channel-group-type.netatmo.timestamp-extended.label = Timestamp
 channel-group-type.netatmo.timestamp-extended.channel.last-seen.label = Last Seen
 channel-group-type.netatmo.timestamp-extended.channel.last-seen.description = Last time the module reported its presence.
@@ -154,10 +172,11 @@ channel-type.netatmo.event-type.description = Description of the event.
 channel-type.netatmo.event-type.state.option.PERSON = Face detected
 channel-type.netatmo.event-type.state.option.PERSON_AWAY = Person has left home
 channel-type.netatmo.event-type.state.option.PERSON_HOME = Person is at home
-channel-type.netatmo.event-type.state.option.OUTDOOR = Motion detected by Presence
+channel-type.netatmo.event-type.state.option.OUTDOOR = Motion detected by Outdoor Camera
 channel-type.netatmo.event-type.state.option.MOVEMENT = Motion detected
 channel-type.netatmo.event-type.state.option.HUMAN = Human seen
 channel-type.netatmo.event-type.state.option.ANIMAL = Animal seen
+channel-type.netatmo.event-type.state.option.VEHICLE = Car seen
 channel-type.netatmo.event-type.state.option.NEW_MODULE = New Module has been paired
 channel-type.netatmo.event-type.state.option.MODULE_CONNECT = Module is connected with the Indoor Camera
 channel-type.netatmo.event-type.state.option.MODULE_DISCONNECT = Module lost its connection with the Indoor Camera
@@ -170,6 +189,9 @@ channel-type.netatmo.event-type.state.option.OFF = Monitoring stopped
 channel-type.netatmo.event-type.state.option.BOOT = Camera booting
 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.MISSED_CALL = Call has not been answered by anyone
 channel-type.netatmo.floodlight-mode.label = Floodlight
 channel-type.netatmo.floodlight-mode.description = State of the floodlight (On/Off/Auto)
 channel-type.netatmo.floodlight-mode.state.option.ON = On
index 3cdf85459b6991decad63743a8da605660ab9513..2ad22e4bb4b6363eb079d15dd320c9853428bde9 100644 (file)
@@ -55,8 +55,8 @@ channel-group-type.netatmo.rain.channel.sum-1.label = Pioggia 1h
 channel-group-type.netatmo.rain.channel.sum-1.description = Quantità di acqua nell'ultima ora.
 channel-group-type.netatmo.rain.channel.sum-24.label = Pioggia 24h
 channel-group-type.netatmo.rain.channel.sum-24.description = Quantità di acqua durante il giorno corrente.
-channel-group-type.netatmo.room-properties.label = Stato Stanza
-channel-group-type.netatmo.room-temperature.label = Temperatura Stanza
+channel-group-type.netatmo.properties-room.label = Stato Stanza
+channel-group-type.netatmo.temperature-room.label = Temperatura Stanza
 channel-group-type.netatmo.security.label = Sicurezza Domestica
 channel-group-type.netatmo.setpoint.label = Valore Impostato
 channel-group-type.netatmo.setpoint.channel.end.label = Fine Setpoint
@@ -82,7 +82,7 @@ channel-group-type.netatmo.temperature.channel.max-time.label = Ora Temp Massima
 channel-group-type.netatmo.temperature.channel.max-time.description = Momento quando oggi la temperatura è stata misurata al suo massimo.
 channel-group-type.netatmo.temperature.channel.min-time.label = Ora Temperatura Minima Oggi
 channel-group-type.netatmo.temperature.channel.min-time.description = Momento in cui la temperatura è stata misurata al suo minimo oggi.
-channel-group-type.netatmo.th-properties.label = Termostato
+channel-group-type.netatmo.properties-thermostat.label = Termostato
 channel-group-type.netatmo.timestamp-extended.label = Data/Ora
 channel-group-type.netatmo.timestamp-extended.channel.last-seen.label = Visto per l'ultima volta
 channel-group-type.netatmo.timestamp-extended.channel.last-seen.description = L'ultima volta che il modulo ha segnalato la sua presenza.
index 13c6e55effbcd0be94697d58964d866bc1d01f5c..9c174af72ffaef9b56152590287554c4cd118afc 100644 (file)
                                <option value="PERSON">Face detected</option>
                                <option value="PERSON_AWAY">Person has left home</option>
                                <option value="PERSON_HOME">Person is at home</option>
-                               <option value="OUTDOOR">Motion detected by Presence</option>
+                               <option value="OUTDOOR">Motion detected by Outdoor Camera</option>
                                <option value="MOVEMENT">Motion detected</option>
                                <option value="HUMAN">Human seen</option>
                                <option value="ANIMAL">Animal seen</option>
+                               <option value="VEHICLE">Car seen</option>
                                <option value="NEW_MODULE">New Module has been paired</option>
                                <option value="MODULE_CONNECT">Module is connected with the Indoor Camera</option>
                                <option value="MODULE_DISCONNECT">Module lost its connection with the Indoor Camera</option>
                                <option value="BOOT">Camera booting</option>
                                <option value="SD">SD card status changed</option>
                                <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="MISSED_CALL">Call has not been answered by anyone</option>
                        </options>
                </state>
        </channel-type>
                                <option value="MOVEMENT"/>
                                <option value="HUMAN"/>
                                <option value="ANIMAL"/>
+                               <option value="VEHICLE"/>
                                <option value="NEW_MODULE"/>
                                <option value="MODULE_CONNECT"/>
                                <option value="MODULE_DISCONNECT"/>
                                <option value="BOOT"/>
                                <option value="SD"/>
                                <option value="ALIM"/>
+                               <option value="ACCEPTED_CALL"/>
+                               <option value="INCOMING_CALL"/>
+                               <option value="MISSED_CALL"/>
                        </options>
                </event>
        </channel-type>
index 8a5870745a30b17aa1245fdbe5848273dbe98ee6..29a76de12866bd6ef09c811249e2230c9a5868a7 100644 (file)
                </channels>
        </channel-group-type>
 
-       <channel-group-type id="room-temperature">
+       <channel-group-type id="temperature-room">
                <label>Room Temperature</label>
                <channels>
                        <channel id="value" typeId="system.indoor-temperature"/>
                </channels>
        </channel-group-type>
 
-       <channel-group-type id="room-properties">
+       <channel-group-type id="properties-room">
                <label>Room Status</label>
                <channels>
                        <channel id="window-open" typeId="window-open"/>
                </channels>
        </channel-group-type>
 
-       <channel-group-type id="th-properties">
+       <channel-group-type id="properties-thermostat">
                <label>Thermostat</label>
                <channels>
-                       <channel id="relay-status" typeId="heating-status"/>
+                       <channel id="relay" typeId="heating-status"/>
                </channels>
        </channel-group-type>
 
index 60d3a7b42c7fb15d3770996ed20a44f8c0050de7..82e2483ee45efedfe0787b25a66ce956f5863232 100644 (file)
                </channels>
        </channel-group-type>
 
+       <channel-group-type id="status-doorbell">
+               <label>Camera Status</label>
+               <channels>
+                       <channel id="sd-card" typeId="sd-card-status"/>
+                       <channel id="alim" typeId="alim-status"/>
+               </channels>
+       </channel-group-type>
+
        <channel-group-type id="live">
                <label>Live Monitoring</label>
                <channels>
                </channels>
        </channel-group-type>
 
+       <channel-group-type id="live-doorbell">
+               <label>Live Monitoring</label>
+               <channels>
+                       <channel id="picture" typeId="live-picture"/>
+                       <channel id="local-picture-url" typeId="live-picture-url">
+                               <label>Live Snapshot Local URL</label>
+                               <description>Local URL of the live snapshot for this camera.</description>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
        <channel-group-type id="last-event">
                <label>Last Event</label>
                <channels>
                </channels>
        </channel-group-type>
 
-       <channel-group-type id="person-event">
+       <channel-group-type id="sub-event-doorbell">
+               <label>Sub Event</label>
+               <channels>
+                       <channel id="type" typeId="event-type"/>
+                       <channel id="time" typeId="timestamp">
+                               <label>Sub-Event Timestamp</label>
+                               <description>Moment when then sub-event occurred.</description>
+                       </channel>
+                       <channel id="message" typeId="message"/>
+                       <channel id="snapshot" typeId="event-picture"/>
+                       <channel id="snapshot-url" typeId="event-picture-url"/>
+                       <channel id="vignette" typeId="event-picture">
+                               <label>Vignette</label>
+                               <description>Vignette of the Snapshot.</description>
+                       </channel>
+                       <channel id="vignette-url" typeId="event-picture-url">
+                               <label>Vignette URL</label>
+                               <description>URL of the vignette.</description>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="last-event-doorbell">
+               <label>Last Event</label>
+               <channels>
+                       <channel id="type" typeId="event-type"/>
+                       <channel id="video-status" typeId="video-status"/>
+                       <channel id="time" typeId="timestamp">
+                               <label>Event Timestamp</label>
+                               <description>Moment when event occurred.</description>
+                       </channel>
+                       <channel id="local-video-url" typeId="video-url">
+                               <label>Video Local URL</label>
+                               <description>Local URL of the event recording.</description>
+                       </channel>
+                       <channel id="vpn-video-url" typeId="video-url">
+                               <label>Video VPN URL</label>
+                               <description>URL of the event recording through Netatmo VPN.</description>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="last-event-person">
                <label>Last Event</label>
                <channels>
                        <channel id="subtype" typeId="event-subtype"/>