]> git.basschouten.com Git - openhab-addons.git/commitdiff
[netatmo] Buffer last event requests per child modules (#13489)
authorGaël L'hopital <gael@lhopital.org>
Fri, 7 Oct 2022 09:56:15 +0000 (11:56 +0200)
committerGitHub <noreply@github.com>
Fri, 7 Oct 2022 09:56:15 +0000 (11:56 +0200)
* Buffer last event requests per child modules
This is targetted to decrease the number of requests transmitted to Netatmo API.
Solves #13358

Signed-off-by: clinique <gael@lhopital.org>
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/RestManager.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/data/NetatmoConstants.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/HomeCapability.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/capability/SmokeCapability.java

index b213fb592cb1c96a50dece7188c0c260ead415e4..00c2296305cc88c9c75755af7174366e9c5d9a3e 100644 (file)
@@ -47,7 +47,7 @@ public class EnergyApi extends RestManager {
     public void switchSchedule(String homeId, String scheduleId) throws NetatmoException {
         UriBuilder uriBuilder = getAppUriBuilder(SUB_PATH_SWITCH_SCHEDULE, PARAM_HOME_ID, homeId, PARAM_SCHEDULE_ID,
                 scheduleId);
-        post(uriBuilder, ApiResponse.Ok.class, null, null);
+        post(uriBuilder, ApiResponse.Ok.class, null);
     }
 
     /**
@@ -64,7 +64,7 @@ public class EnergyApi extends RestManager {
      */
     public void setThermMode(String homeId, String mode) throws NetatmoException {
         UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_SET_THERM_MODE, PARAM_HOME_ID, homeId, PARAM_MODE, mode);
-        post(uriBuilder, ApiResponse.Ok.class, null, null);
+        post(uriBuilder, ApiResponse.Ok.class, null);
     }
 
     /**
@@ -88,6 +88,6 @@ public class EnergyApi extends RestManager {
                 uriBuilder.queryParam("temp", temp > THERM_MAX_SETPOINT ? THERM_MAX_SETPOINT : temp);
             }
         }
-        post(uriBuilder, ApiResponse.Ok.class, null, null);
+        post(uriBuilder, ApiResponse.Ok.class, null);
     }
 }
index c556a8a0a900fdf102bf62d6b0ee6520a51d3993..b35d23376e18962ca74358313df6a9e467a4358b 100644 (file)
@@ -52,14 +52,13 @@ public abstract class RestManager {
         return executeUri(uriBuilder, HttpMethod.GET, clazz, null, null);
     }
 
-    protected <T extends ApiResponse<?>> T post(UriBuilder uriBuilder, Class<T> clazz, @Nullable String payload,
-            @Nullable String contentType) throws NetatmoException {
-        return executeUri(uriBuilder, HttpMethod.POST, clazz, payload, contentType);
+    protected <T extends ApiResponse<?>> T post(UriBuilder uriBuilder, Class<T> clazz, @Nullable String payload)
+            throws NetatmoException {
+        return executeUri(uriBuilder, HttpMethod.POST, clazz, payload, payload == null ? null : CONTENT_APP_JSON);
     }
 
     protected <T> T post(URI uri, Class<T> clazz, Map<String, String> entries) throws NetatmoException {
-        return apiBridge.executeUri(uri, POST, clazz, toRequest(entries),
-                "application/x-www-form-urlencoded;charset=UTF-8", 3);
+        return apiBridge.executeUri(uri, POST, clazz, toRequest(entries), CONTENT_APP_FORM, 3);
     }
 
     private <T extends ApiResponse<?>> T executeUri(UriBuilder uriBuilder, HttpMethod method, Class<T> clazz,
index aa2157b6e7984a53e0a75c59d9479b9fff9a5a2c..7b0e49b9b8bddc3ddf9e8823c73b53f2c08d66e7 100644 (file)
@@ -16,7 +16,6 @@ import static org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.*;
 
 import java.net.URI;
 import java.util.Collection;
-import java.util.stream.Collectors;
 
 import javax.ws.rs.core.UriBuilder;
 
@@ -52,7 +51,7 @@ public class SecurityApi extends RestManager {
      */
     public void dropWebhook() throws NetatmoException {
         UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_DROP_WEBHOOK);
-        post(uriBuilder, ApiResponse.Ok.class, null, null);
+        post(uriBuilder, ApiResponse.Ok.class, null);
     }
 
     /**
@@ -63,37 +62,33 @@ public class SecurityApi extends RestManager {
      */
     public boolean addwebhook(URI uri) throws NetatmoException {
         UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_ADD_WEBHOOK, PARAM_URL, uri.toString());
-        post(uriBuilder, ApiResponse.Ok.class, null, null);
+        post(uriBuilder, ApiResponse.Ok.class, null);
         return true;
     }
 
-    public Collection<HomeEvent> getPersonEvents(String homeId, String personId) throws NetatmoException {
-        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();
+    private Collection<HomeEvent> getEvents(@Nullable Object... params) throws NetatmoException {
+        UriBuilder uriBuilder = getApiUriBuilder(SUB_PATH_GET_EVENTS, params);
+        BodyResponse<Home> body = get(uriBuilder, NAEventsDataResponse.class).getBody();
         if (body != null) {
             Home home = body.getElement();
             if (home != null) {
-                return home.getEvents().stream().filter(event -> personId.equals(event.getPersonId()))
-                        .collect(Collectors.toList());
+                return home.getEvents();
             }
         }
         throw new NetatmoException("home should not be null");
     }
 
+    public Collection<HomeEvent> getHomeEvents(String homeId) throws NetatmoException {
+        return getEvents(PARAM_HOME_ID, homeId);
+    }
+
+    public Collection<HomeEvent> getPersonEvents(String homeId, String personId) throws NetatmoException {
+        return getEvents(PARAM_HOME_ID, homeId, PARAM_PERSON_ID, personId, PARAM_OFFSET, 1);
+    }
+
     public Collection<HomeEvent> getDeviceEvents(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) {
-                return home.getEvents();
-            }
-        }
-        throw new NetatmoException("home should not be null");
+        return getEvents(PARAM_HOME_ID, homeId, PARAM_DEVICE_ID, deviceId, PARAM_DEVICES_TYPE, deviceType);
     }
 
     public @Nullable String ping(String vpnUrl) {
@@ -109,22 +104,18 @@ public class SecurityApi extends RestManager {
     public void changeStatus(String localCameraURL, boolean setOn) throws NetatmoException {
         UriBuilder uriBuilder = UriBuilder.fromUri(localCameraURL).path(PATH_COMMAND).path(SUB_PATH_CHANGESTATUS);
         uriBuilder.queryParam(PARAM_STATUS, setOn ? "on" : "off");
-        post(uriBuilder, ApiResponse.Ok.class, null, null);
+        post(uriBuilder, ApiResponse.Ok.class, null);
     }
 
     public void changeFloodLightMode(String homeId, String cameraId, FloodLightMode mode) throws NetatmoException {
         UriBuilder uriBuilder = getAppUriBuilder(PATH_STATE);
-        String payload = String.format(
-                "{\"home\": {\"id\":\"%s\",\"modules\": [ {\"id\":\"%s\",\"floodlight\":\"%s\"} ]}}", homeId, cameraId,
-                mode.name().toLowerCase());
-        post(uriBuilder, ApiResponse.Ok.class, payload, "application/json;charset=utf-8");
+        String payload = String.format(PAYLOAD_FLOODLIGHT, homeId, cameraId, mode.name().toLowerCase());
+        post(uriBuilder, ApiResponse.Ok.class, payload);
     }
 
     public void setPersonAwayStatus(String homeId, String personId, boolean away) throws NetatmoException {
         UriBuilder uriBuilder = getAppUriBuilder(away ? SUB_PATH_PERSON_AWAY : SUB_PATH_PERSON_HOME);
-        String payload = String.format(
-                away ? "{\"home_id\":\"%s\",\"person_id\":\"%s\"}" : "{\"home_id\":\"%s\",\"person_ids\":[\"%s\"]}",
-                homeId, personId);
-        post(uriBuilder, ApiResponse.Ok.class, payload, "application/json;charset=utf-8");
+        String payload = String.format(away ? PAYLOAD_PERSON_AWAY : PAYLOAD_PERSON_HOME, homeId, personId);
+        post(uriBuilder, ApiResponse.Ok.class, payload);
     }
 }
index a8f3f83568f9d1a77f1818497d7cc8f41a1a42d5..f864790c4e17c8bcab5ca8db3bc09b0728741725 100644 (file)
@@ -114,6 +114,10 @@ public class NetatmoConstants {
         }
     }
 
+    // Content types
+    public static final String CONTENT_APP_JSON = "application/json;charset=utf-8";
+    public static final String CONTENT_APP_FORM = "application/x-www-form-urlencoded;charset=UTF-8";
+
     // Netatmo API urls
     public static final String URL_API = "https://api.netatmo.com/";
     public static final String URL_APP = "https://app.netatmo.net/";
@@ -152,6 +156,11 @@ public class NetatmoConstants {
     public static final String PARAM_STATUS = "status";
     public static final String PARAM_DEVICES_TYPE = "device_types";
 
+    // Payloads
+    public static final String PAYLOAD_FLOODLIGHT = "{\"home\": {\"id\":\"%s\",\"modules\": [ {\"id\":\"%s\",\"floodlight\":\"%s\"} ]}}";
+    public static final String PAYLOAD_PERSON_AWAY = "{\"home_id\":\"%s\",\"person_id\":\"%s\"}";
+    public static final String PAYLOAD_PERSON_HOME = "{\"home_id\":\"%s\",\"person_ids\":[\"%s\"]}";
+
     // Autentication process params
     public static final String PARAM_ERROR = "error";
 
index 910c018c56cb3154b605bd1d6cd4a12513fbe26b..d96c8b35ae09ad4b9c749892577333d0e52b11db 100644 (file)
@@ -15,7 +15,6 @@ package org.openhab.binding.netatmo.internal.handler.capability;
 import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -101,9 +100,8 @@ public class CameraCapability extends HomeSecurityThingCapability {
     public List<NAObject> updateReadings() {
         List<NAObject> result = new ArrayList<>();
         securityCapability.ifPresent(cap -> {
-            Collection<HomeEvent> events = cap.getDeviceEvents(handler.getId(), moduleType.apiName);
-            if (!events.isEmpty()) {
-                HomeEvent event = events.iterator().next();
+            HomeEvent event = cap.getLastDeviceEvent(handler.getId(), moduleType.apiName);
+            if (event != null) {
                 result.add(event);
                 result.addAll(event.getSubevents());
             }
index 0e001bafd435a15374696f5146f6166fa545f2f9..045a368be2572b349c8780f5b15060f7443f34a3 100644 (file)
@@ -113,7 +113,7 @@ public class HomeCapability extends RestCapability<HomeApi> {
                 result.add(homeStatus);
             }
         } catch (NetatmoException e) {
-            logger.warn("Error gettting Home informations : {}", e.getMessage());
+            logger.warn("Error getting Home informations : {}", e.getMessage());
         }
         return result;
     }
index f03d1306f83d4108225a002106a620860f6fa914..aa88faaca5537b4f68823fa00c507786c301c0f0 100644 (file)
@@ -16,7 +16,6 @@ import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
 
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -90,9 +89,9 @@ public class PersonCapability extends HomeSecurityThingCapability {
     public List<NAObject> updateReadings() {
         List<NAObject> result = new ArrayList<>();
         securityCapability.ifPresent(cap -> {
-            Collection<HomeEvent> events = cap.getPersonEvents(handler.getId());
-            if (!events.isEmpty()) {
-                result.add(events.iterator().next());
+            HomeEvent event = cap.getLastPersonEvent(handler.getId());
+            if (event != null) {
+                result.add(event);
             }
         });
         return result;
index 2803973576f51b1e834ac6e4643a09cb52deafab..380eaa2d13059036b5903329a81e5f5fbe90a9c9 100644 (file)
  */
 package org.openhab.binding.netatmo.internal.handler.capability;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -27,6 +30,7 @@ import org.openhab.binding.netatmo.internal.api.dto.HomeEvent;
 import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule;
 import org.openhab.binding.netatmo.internal.api.dto.HomeStatusPerson;
 import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
+import org.openhab.binding.netatmo.internal.api.dto.NAObject;
 import org.openhab.binding.netatmo.internal.deserialization.NAObjectMap;
 import org.openhab.binding.netatmo.internal.handler.CommonInterface;
 import org.slf4j.Logger;
@@ -42,6 +46,8 @@ import org.slf4j.LoggerFactory;
 class SecurityCapability extends RestCapability<SecurityApi> {
     private final Logger logger = LoggerFactory.getLogger(SecurityCapability.class);
 
+    private static final Map<String, HomeEvent> eventBuffer = new HashMap<>();
+
     SecurityCapability(CommonInterface handler) {
         super(handler, SecurityApi.class);
     }
@@ -110,7 +116,55 @@ class SecurityCapability extends RestCapability<SecurityApi> {
                 });
     }
 
-    public Collection<HomeEvent> getDeviceEvents(String cameraId, String deviceType) {
+    @Override
+    protected List<NAObject> updateReadings(SecurityApi api) {
+        List<NAObject> result = new ArrayList<>();
+        try {
+            Collection<HomeEvent> lastEvents = api.getHomeEvents(handler.getId());
+            lastEvents.stream().forEach(event -> {
+                HomeEvent previousEvent = eventBuffer.get(event.getCameraId());
+                if (previousEvent == null || previousEvent.getTime().isBefore(event.getTime())) {
+                    eventBuffer.put(event.getCameraId(), event);
+                }
+                String personId = event.getPersonId();
+                if (personId != null) {
+                    previousEvent = eventBuffer.get(personId);
+                    if (previousEvent == null || previousEvent.getTime().isBefore(event.getTime())) {
+                        eventBuffer.put(personId, event);
+                    }
+                }
+            });
+        } catch (NetatmoException e) {
+            logger.warn("Error retrieving last events for home '{}' : {}", handler.getId(), e.getMessage());
+        }
+        return result;
+    }
+
+    public @Nullable HomeEvent getLastPersonEvent(String personId) {
+        HomeEvent event = eventBuffer.get(personId);
+        if (event == null) {
+            Collection<HomeEvent> events = requestPersonEvents(personId);
+            if (!events.isEmpty()) {
+                event = events.iterator().next();
+                eventBuffer.put(personId, event);
+            }
+        }
+        return event;
+    }
+
+    public @Nullable HomeEvent getLastDeviceEvent(String cameraId, String deviceType) {
+        HomeEvent event = eventBuffer.get(cameraId);
+        if (event == null) {
+            Collection<HomeEvent> events = requestDeviceEvents(cameraId, deviceType);
+            if (!events.isEmpty()) {
+                event = events.iterator().next();
+                eventBuffer.put(cameraId, event);
+            }
+        }
+        return event;
+    }
+
+    private Collection<HomeEvent> requestDeviceEvents(String cameraId, String deviceType) {
         return getApi().map(api -> {
             try {
                 return api.getDeviceEvents(handler.getId(), cameraId, deviceType);
@@ -121,7 +175,7 @@ class SecurityCapability extends RestCapability<SecurityApi> {
         }).orElse(List.of());
     }
 
-    public Collection<HomeEvent> getPersonEvents(String personId) {
+    private Collection<HomeEvent> requestPersonEvents(String personId) {
         return getApi().map(api -> {
             try {
                 return api.getPersonEvents(handler.getId(), personId);
index be188f1d07871c3a38b2bca2a09485fe3dc44cd2..560bc3b7e7ad41b03e265a9d077549fc19a6e7e9 100644 (file)
@@ -13,7 +13,6 @@
 package org.openhab.binding.netatmo.internal.handler.capability;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -41,9 +40,9 @@ public class SmokeCapability extends HomeSecurityThingCapability {
     public List<NAObject> updateReadings() {
         List<NAObject> result = new ArrayList<>();
         securityCapability.ifPresent(cap -> {
-            Collection<HomeEvent> events = cap.getDeviceEvents(handler.getId(), moduleType.apiName);
-            if (!events.isEmpty()) {
-                result.add(events.iterator().next());
+            HomeEvent event = cap.getLastDeviceEvent(handler.getId(), moduleType.apiName);
+            if (event != null) {
+                result.add(event);
             }
         });
         return result;