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);
}
/**
*/
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);
}
/**
uriBuilder.queryParam("temp", temp > THERM_MAX_SETPOINT ? THERM_MAX_SETPOINT : temp);
}
}
- post(uriBuilder, ApiResponse.Ok.class, null, null);
+ post(uriBuilder, ApiResponse.Ok.class, null);
}
}
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,
import java.net.URI;
import java.util.Collection;
-import java.util.stream.Collectors;
import javax.ws.rs.core.UriBuilder;
*/
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);
}
/**
*/
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) {
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);
}
}
}
}
+ // 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/";
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";
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;
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());
}
result.add(homeStatus);
}
} catch (NetatmoException e) {
- logger.warn("Error gettting Home informations : {}", e.getMessage());
+ logger.warn("Error getting Home informations : {}", e.getMessage());
}
return result;
}
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;
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;
*/
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;
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;
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);
}
});
}
- 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);
}).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);
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;
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;