| battery | low-battery | Switch | Low battery |
| battery | status | String | Description of the battery status (*) |
-### Welcome Home
+### Home
-All these channels are read only.
+A Home is the Thing holding various modules and devices. They can hold two areas of equipments : Security and Energy.
+Depending on the way it is configured the behaviour will be adapted and available channels can vary.
+
+**Home Configuration**
+
+The Home thing has the following configuration elements:
+
+| Parameter | Type | Required | Description |
+| ---------- | ------ | -------- | ----------------------------------------------------------------------------------- |
+| id (1) | String | No | If you have a single type of equipment, this id is to be used for the home |
+| energyId | String | No | Id of a home holding energy control devices |
+| securityId | String | No | Id of a home holding security monitoring devices |
+
+At least one of these parameter must be filled - at most two :
+* id or securityId
+* id or energyId
+* securityId and energyId
-**Supported channels for the Home thing:**
+(1) this parameter is only kept for backward compatibility.
+
+All channels are read only.
+
+**Supported channels for the Security Home thing:**
| Channel Group | Channel Id | Item Type | Description |
| ------------- | ---------------------- | --------- | ------------------------------------------------ |
| security | unknown-person-count | Number | Total number of unknown persons that are at home |
| security | unknown-person-picture | Image | Snapshot of unknown person that is at home |
-All these channels are read only.
-
-**Supported trigger channels for the Home thing:**
+**Supported trigger channels for the Security Home thing:**
| Channel Type ID | Options | Description |
| ---------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
Warnings:
- The URL of the live snapshot is a fixed URL so the value of the channel cameraLivePictureUrl / welcomeCameraLivePictureUrl will never be updated once first set by the binding. So to get a refreshed picture, you need to use the refresh parameter in your sitemap image element.
-- Some features like the video surveillance are accessed via the local network, so it may be helpful to set a static IP address for the camera within your local network.
+- Some features like the video monitoring are accessed via the local network, so it may be helpful to set a static IP address for the camera within your local network.
**Supported channels for the Welcome Camera thing:**
return;
}
getEnergyCapability()
- .ifPresent(cap -> cap.setRoomThermTemp(roomHandler.getId(), temp, endTime, SetpointMode.MANUAL));
+ .ifPresent(cap -> cap.setRoomThermTemp(roomHandler.getId(), SetpointMode.MANUAL, endTime, temp));
}
@RuleAction(label = "@text/actionSetThermRoomModeSetpointLabel", description = "@text/actionSetThermRoomModeSetpointDesc")
long setpointEnd = targetEndTime;
SetpointMode setpointMode = targetMode;
- getEnergyCapability().ifPresent(cap -> cap.setRoomThermTemp(roomHandler.getId(), 0, setpointEnd, setpointMode));
+ getEnergyCapability().ifPresent(cap -> cap.setRoomThermTemp(roomHandler.getId(), setpointMode, setpointEnd, 0));
}
public static void setThermRoomTempSetpoint(ThingActions actions, @Nullable Double temp, @Nullable Long endTime) {
return ignoredForThingUpdate;
}
- public void setIgnoredForThingUpdate(boolean ignoredForThingUpdate) {
- this.ignoredForThingUpdate = ignoredForThingUpdate;
+ public NAObject ignoringForThingUpdate() {
+ this.ignoredForThingUpdate = true;
+ return this;
}
}
return localReachable != null ? localReachable : true;
}
- public void setReachable(boolean reachable) {
- this.reachable = reachable;
- }
-
public @Nullable Dashboard getDashboardData() {
return dashboardData;
}
--- /dev/null
+/**
+ * Copyright (c) 2010-2023 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.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
+
+/**
+ * The {@link HomeConfiguration} is responsible for holding configuration information for any
+ * Netatmo Home - security or energy, or both
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public class HomeConfiguration extends NAThingConfiguration {
+ public String securityId = "";
+ public String energyId = "";
+
+ @Override
+ public String getId() {
+ return getIdForArea(energyId.isBlank() ? FeatureArea.SECURITY : FeatureArea.ENERGY);
+ }
+
+ public String getIdForArea(FeatureArea feature) {
+ return FeatureArea.ENERGY.equals(feature) ? energyId.isBlank() ? id : energyId
+ : FeatureArea.SECURITY.equals(feature) ? securityId.isBlank() ? id : securityId : id;
+ }
+}
public class NAThingConfiguration {
public static final String ID = "id";
- public String id = "";
+ protected String id = "";
public int refreshInterval = -1;
+
+ public String getId() {
+ return id;
+ }
}
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.FeatureArea;
import org.openhab.binding.netatmo.internal.api.dto.NAObject;
import org.openhab.binding.netatmo.internal.api.dto.NAThing;
import org.openhab.binding.netatmo.internal.config.NAThingConfiguration;
import org.openhab.binding.netatmo.internal.handler.capability.HomeCapability;
import org.openhab.binding.netatmo.internal.handler.capability.RefreshCapability;
import org.openhab.binding.netatmo.internal.handler.capability.RestCapability;
+import org.openhab.core.config.core.Configuration;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
}
default String getId() {
- return (String) getThing().getConfiguration().get(NAThingConfiguration.ID);
+ return getConfiguration().as(NAThingConfiguration.class).getId();
+ }
+
+ default Configuration getConfiguration() {
+ return getThing().getConfiguration();
}
default Stream<Channel> getActiveChannels() {
return List.of();
}
+ default Stream<CommonInterface> getActiveChildren(FeatureArea area) {
+ return getActiveChildren().stream().filter(child -> child.getModuleType().feature == area);
+ }
+
default <T extends RestCapability<?>> Optional<T> getHomeCapability(Class<T> clazz) {
return getHomeHandler().map(handler -> handler.getCapabilities().get(clazz)).orElse(Optional.empty());
}
} else {
setThingStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, null);
setRefreshCapability();
- getCapabilities().values().forEach(cap -> cap.initialize());
getScheduler().schedule(() -> {
CommonInterface bridgeHandler = getBridgeHandler();
if (bridgeHandler != null) {
}
}
+ default ModuleType getModuleType() {
+ return ModuleType.from(getThing().getThingTypeUID());
+ }
+
default void setRefreshCapability() {
- ModuleType moduleType = ModuleType.from(getThing().getThingTypeUID());
- if (ModuleType.ACCOUNT.equals(moduleType.getBridge())) {
+ if (ModuleType.ACCOUNT.equals(getModuleType().getBridge())) {
NAThingConfiguration config = getThing().getConfiguration().as(NAThingConfiguration.class);
getCapabilities().put(new RefreshCapability(this, getScheduler(), config.refreshInterval));
}
@Override
protected void beforeNewData() {
super.beforeNewData();
- homeCapability.ifPresent(cap -> {
+ securityCapability.ifPresent(cap -> {
NAObjectMap<HomeDataPerson> persons = cap.getPersons();
descriptionProvider.setStateOptions(personChannelUID, persons.values().stream()
.map(p -> new StateOption(p.getId(), p.getName())).collect(Collectors.toList()));
private static final long serialVersionUID = -3043492242108419801L;
public void put(Capability capability) {
- Class<? extends Capability> clazz = capability.getClass();
+ Class<?> clazz = capability.getClass();
if (super.get(clazz) == null) {
super.put(clazz, capability);
+ capability.initialize();
}
}
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.netatmo.internal.api.EnergyApi;
import org.openhab.binding.netatmo.internal.api.NetatmoException;
+import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.SetpointMode;
import org.openhab.binding.netatmo.internal.api.dto.HomeData;
import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule;
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
import org.openhab.binding.netatmo.internal.api.dto.Room;
+import org.openhab.binding.netatmo.internal.config.HomeConfiguration;
import org.openhab.binding.netatmo.internal.deserialization.NAObjectMap;
import org.openhab.binding.netatmo.internal.handler.CommonInterface;
import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
private int setPointDefaultDuration = -1;
private final NetatmoDescriptionProvider descriptionProvider;
+ private String energyId = "";
EnergyCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider) {
super(handler, EnergyApi.class);
this.descriptionProvider = descriptionProvider;
}
+ @Override
+ public void initialize() {
+ super.initialize();
+ energyId = handler.getConfiguration().as(HomeConfiguration.class).getIdForArea(FeatureArea.ENERGY);
+ }
+
@Override
protected void updateHomeData(HomeData homeData) {
NAObjectMap<HomeDataRoom> rooms = homeData.getRooms();
NAObjectMap<HomeDataModule> modules = homeData.getModules();
- handler.getActiveChildren().forEach(childHandler -> {
+ handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
String childId = childHandler.getId();
- rooms.getOpt(childId).ifPresentOrElse(roomData -> {
- roomData.setIgnoredForThingUpdate(true);
- childHandler.setNewData(roomData);
- }, () -> {
- modules.getOpt(childId).ifPresent(childData -> {
- childData.setIgnoredForThingUpdate(true);
- childHandler.setNewData(childData);
- });
- modules.values().stream().filter(module -> childId.equals(module.getBridge()))
- .forEach(bridgedModule -> {
- childHandler.setNewData(bridgedModule);
- });
- });
+ rooms.getOpt(childId)
+ .ifPresentOrElse(roomData -> childHandler.setNewData(roomData.ignoringForThingUpdate()), () -> {
+ modules.getOpt(childId)
+ .ifPresent(childData -> childHandler.setNewData(childData.ignoringForThingUpdate()));
+ modules.values().stream().filter(module -> childId.equals(module.getBridge()))
+ .forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
+ });
});
descriptionProvider.setStateOptions(new ChannelUID(thing.getUID(), GROUP_ENERGY, CHANNEL_PLANNING),
homeData.getThermSchedules().stream().map(p -> new StateOption(p.getId(), p.getName()))
protected void updateHomeStatus(HomeStatus homeStatus) {
NAObjectMap<Room> rooms = homeStatus.getRooms();
NAObjectMap<HomeStatusModule> modules = homeStatus.getModules();
- handler.getActiveChildren().forEach(childHandler -> {
+ handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
String childId = childHandler.getId();
rooms.getOpt(childId).ifPresentOrElse(roomData -> childHandler.setNewData(roomData), () -> {
- modules.getOpt(childId).ifPresentOrElse(childData -> {
- childHandler.setNewData(childData);
+ modules.getOpt(childId).ifPresent(moduleData -> {
+ childHandler.setNewData(moduleData);
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
- .forEach(bridgedModule -> {
- childHandler.setNewData(bridgedModule);
- });
-
- }, () -> {
- // This module is not present in the homestatus data, so it is considered as unreachable
- HomeStatusModule module = new HomeStatusModule();
- module.setReachable(false);
- childHandler.setNewData(module);
+ .forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
});
});
});
}
- public int getSetpointDefaultDuration() {
- return setPointDefaultDuration;
- }
-
- public void setRoomThermMode(String roomId, SetpointMode targetMode) {
+ public void setThermPoint(String roomId, SetpointMode mode, long endtime, double temp) {
getApi().ifPresent(api -> {
try {
- api.setThermpoint(handler.getId(), roomId, targetMode,
- targetMode == SetpointMode.MAX ? setpointEndTimeFromNow(setPointDefaultDuration) : 0, 0);
+ api.setThermpoint(energyId, roomId, mode, endtime, temp);
handler.expireData();
} catch (NetatmoException e) {
- logger.warn("Error setting room thermostat mode '{}' : {}", targetMode, e.getMessage());
+ logger.warn("Error setting room thermostat mode '{}' : {}", mode, e.getMessage());
}
});
}
- public void setRoomThermTemp(String roomId, double temperature, long endtime, SetpointMode mode) {
- getApi().ifPresent(api -> {
- try {
- api.setThermpoint(handler.getId(), roomId, mode, endtime, temperature);
- handler.expireData();
- } catch (NetatmoException e) {
- logger.warn("Error setting room thermostat mode '{}' : {}", mode, e.getMessage());
- }
- });
+ public void setRoomThermTemp(String roomId, SetpointMode mode, long endtime, double temp) {
+ setThermPoint(roomId, mode, endtime, temp);
+ }
+
+ public void setRoomThermMode(String roomId, SetpointMode targetMode) {
+ setThermPoint(roomId, targetMode, targetMode == SetpointMode.MAX ? setpointEndTimeFromNow() : 0, 0);
}
- public void setRoomThermTemp(String roomId, double temperature) {
- setRoomThermTemp(roomId, temperature, setpointEndTimeFromNow(setPointDefaultDuration), SetpointMode.MANUAL);
+ public void setRoomThermTemp(String roomId, double temp) {
+ setThermPoint(roomId, SetpointMode.MANUAL, setpointEndTimeFromNow(), temp);
}
@Override
try {
switch (channelName) {
case CHANNEL_PLANNING:
- api.switchSchedule(handler.getId(), command.toString());
+ api.switchSchedule(energyId, command.toString());
break;
case CHANNEL_SETPOINT_MODE:
SetpointMode targetMode = SetpointMode.valueOf(command.toString());
logger.info("Switch to 'Manual' is done by setting a setpoint temp, command ignored");
return;
}
- api.setThermMode(handler.getId(), targetMode.apiDescriptor);
+ api.setThermMode(energyId, targetMode.apiDescriptor);
break;
}
handler.expireData();
});
}
- private static long setpointEndTimeFromNow(int duration_min) {
- return ZonedDateTime.now().plusMinutes(duration_min).toEpochSecond();
+ private long setpointEndTimeFromNow() {
+ return ZonedDateTime.now().plusMinutes(setPointDefaultDuration).toEpochSecond();
}
}
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.openhab.binding.netatmo.internal.api.NetatmoException;
import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
import org.openhab.binding.netatmo.internal.api.dto.HomeData;
-import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
-import org.openhab.binding.netatmo.internal.api.dto.HomeDataPerson;
import org.openhab.binding.netatmo.internal.api.dto.Location;
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.config.HomeConfiguration;
import org.openhab.binding.netatmo.internal.handler.CommonInterface;
import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
import org.slf4j.Logger;
*/
@NonNullByDefault
public class HomeCapability extends RestCapability<HomeApi> {
- private final Logger logger = LoggerFactory.getLogger(HomeCapability.class);
+ private final Logger logger = LoggerFactory.getLogger(HomeCapability.class);
+ private final Set<FeatureArea> featureAreas = new HashSet<>();
private final NetatmoDescriptionProvider descriptionProvider;
-
- private NAObjectMap<HomeDataPerson> persons = new NAObjectMap<>();
- private NAObjectMap<HomeDataModule> modules = new NAObjectMap<>();
-
- private Set<FeatureArea> featuresArea = Set.of();
+ private Set<String> homeIds = Set.of();
public HomeCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider) {
super(handler, HomeApi.class);
this.descriptionProvider = descriptionProvider;
}
+ @Override
+ public void initialize() {
+ super.initialize();
+ HomeConfiguration config = handler.getConfiguration().as(HomeConfiguration.class);
+ homeIds = Set.of(config.getId(), config.energyId, config.securityId);
+ }
+
@Override
protected void updateHomeData(HomeData home) {
- featuresArea = home.getFeatures();
- if (hasFeature(FeatureArea.SECURITY) && !handler.getCapabilities().containsKey(SecurityCapability.class)) {
+ if (hasArea(FeatureArea.SECURITY) && !handler.getCapabilities().containsKey(SecurityCapability.class)) {
handler.getCapabilities().put(new SecurityCapability(handler));
}
- if (hasFeature(FeatureArea.ENERGY) && !handler.getCapabilities().containsKey(EnergyCapability.class)) {
+ if (hasArea(FeatureArea.ENERGY) && !handler.getCapabilities().containsKey(EnergyCapability.class)) {
handler.getCapabilities().put(new EnergyCapability(handler, descriptionProvider));
}
if (firstLaunch) {
home.getCountry().map(country -> properties.put(PROPERTY_COUNTRY, country));
home.getTimezone().map(tz -> properties.put(PROPERTY_TIMEZONE, tz));
properties.put(GROUP_LOCATION, ((Location) home).getLocation().toString());
- properties.put(PROPERTY_FEATURE, featuresArea.stream().map(f -> f.name()).collect(Collectors.joining(",")));
+ properties.put(PROPERTY_FEATURE,
+ featureAreas.stream().map(FeatureArea::name).collect(Collectors.joining(",")));
}
}
@Override
protected void afterNewData(@Nullable NAObject newData) {
super.afterNewData(newData);
- if (firstLaunch && !hasFeature(FeatureArea.SECURITY)) {
+ if (firstLaunch && !hasArea(FeatureArea.SECURITY)) {
handler.removeChannels(thing.getChannelsOfGroup(GROUP_SECURITY));
}
- if (firstLaunch && !hasFeature(FeatureArea.ENERGY)) {
+ if (firstLaunch && !hasArea(FeatureArea.ENERGY)) {
handler.removeChannels(thing.getChannelsOfGroup(GROUP_ENERGY));
}
}
- private boolean hasFeature(FeatureArea seeked) {
- return featuresArea.contains(seeked);
- }
-
- public NAObjectMap<HomeDataPerson> getPersons() {
- return persons;
- }
-
- public NAObjectMap<HomeDataModule> getModules() {
- return modules;
+ private boolean hasArea(FeatureArea searched) {
+ return featureAreas.contains(searched);
}
@Override
protected List<NAObject> updateReadings(HomeApi api) {
List<NAObject> result = new ArrayList<>();
- try {
- HomeData homeData = api.getHomeData(handler.getId());
- if (homeData != null) {
- result.add(homeData);
- persons = homeData.getPersons();
- modules = homeData.getModules();
- }
- HomeStatus homeStatus = api.getHomeStatus(handler.getId());
- if (homeStatus != null) {
- result.add(homeStatus);
+ homeIds.stream().filter(id -> !id.isEmpty()).forEach(id -> {
+ try {
+ HomeData homeData = api.getHomeData(id);
+ if (homeData != null) {
+ result.add(homeData);
+ featureAreas.addAll(homeData.getFeatures());
+ }
+ HomeStatus homeStatus = api.getHomeStatus(id);
+ if (homeStatus != null) {
+ result.add(homeStatus);
+ }
+ } catch (NetatmoException e) {
+ logger.warn("Error getting Home informations : {}", e.getMessage());
}
- } catch (NetatmoException e) {
- logger.warn("Error getting Home informations : {}", e.getMessage());
- }
+ });
return result;
}
}
@Override
protected void beforeNewData() {
super.beforeNewData();
- homeCapability.ifPresent(cap -> {
+ securityCapability.ifPresent(cap -> {
Stream<HomeDataModule> cameras = cap.getModules().values().stream()
.filter(module -> module.getType() == ModuleType.WELCOME);
descriptionProvider.setStateOptions(cameraChannelUID,
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.netatmo.internal.api.NetatmoException;
import org.openhab.binding.netatmo.internal.api.SecurityApi;
+import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FloodLightMode;
import org.openhab.binding.netatmo.internal.api.dto.HomeData;
import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
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.config.HomeConfiguration;
import org.openhab.binding.netatmo.internal.deserialization.NAObjectMap;
import org.openhab.binding.netatmo.internal.handler.CommonInterface;
import org.slf4j.Logger;
private final Map<String, HomeEvent> eventBuffer = new HashMap<>();
private @Nullable ZonedDateTime freshestEventTime;
+ private NAObjectMap<HomeDataPerson> persons = new NAObjectMap<>();
+ private NAObjectMap<HomeDataModule> modules = new NAObjectMap<>();
+ private String securityId = "";
+
SecurityCapability(CommonInterface handler) {
super(handler, SecurityApi.class);
}
public void initialize() {
super.initialize();
freshestEventTime = null;
+ securityId = handler.getConfiguration().as(HomeConfiguration.class).getIdForArea(FeatureArea.SECURITY);
}
@Override
protected void updateHomeData(HomeData homeData) {
- NAObjectMap<HomeDataPerson> persons = homeData.getPersons();
- NAObjectMap<HomeDataModule> modules = homeData.getModules();
- handler.getActiveChildren().forEach(childHandler -> {
+ persons = homeData.getPersons();
+ modules = homeData.getModules();
+ handler.getActiveChildren(FeatureArea.SECURITY).forEach(childHandler -> {
String childId = childHandler.getId();
- persons.getOpt(childId).ifPresentOrElse(personData -> {
- personData.setIgnoredForThingUpdate(true);
- childHandler.setNewData(personData);
- }, () -> {
- modules.getOpt(childId).ifPresent(childData -> {
- childData.setIgnoredForThingUpdate(true);
- childHandler.setNewData(childData);
- });
- modules.values().stream().filter(module -> childId.equals(module.getBridge()))
- .forEach(bridgedModule -> {
- childHandler.setNewData(bridgedModule);
- });
- });
+ persons.getOpt(childId)
+ .ifPresentOrElse(personData -> childHandler.setNewData(personData.ignoringForThingUpdate()), () -> {
+ modules.getOpt(childId)
+ .ifPresent(childData -> childHandler.setNewData(childData.ignoringForThingUpdate()));
+ modules.values().stream().filter(module -> childId.equals(module.getBridge()))
+ .forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
+ });
});
}
protected void updateHomeStatus(HomeStatus homeStatus) {
NAObjectMap<HomeStatusPerson> persons = homeStatus.getPersons();
NAObjectMap<HomeStatusModule> modules = homeStatus.getModules();
- handler.getActiveChildren().forEach(childHandler -> {
+ handler.getActiveChildren(FeatureArea.SECURITY).forEach(childHandler -> {
String childId = childHandler.getId();
persons.getOpt(childId).ifPresentOrElse(personData -> childHandler.setNewData(personData), () -> {
- modules.getOpt(childId).ifPresentOrElse(childData -> {
+ modules.getOpt(childId).ifPresent(childData -> {
childHandler.setNewData(childData);
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
- .forEach(bridgedModule -> {
- childHandler.setNewData(bridgedModule);
- });
-
- }, () -> {
- // This module is not present in the homestatus data, so it is considered as unreachable
- HomeStatusModule module = new HomeStatusModule();
- module.setReachable(false);
- childHandler.setNewData(module);
+ .forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
});
});
});
@Override
protected void updateHomeEvent(HomeEvent homeEvent) {
- String personId = homeEvent.getPersonId();
- if (personId != null) {
- handler.getActiveChildren().stream().filter(handler -> personId.equals(handler.getId())).findFirst()
- .ifPresent(handler -> {
- homeEvent.setIgnoredForThingUpdate(true);
- handler.setNewData(homeEvent);
- });
+ addEventIfKnownObject(homeEvent, homeEvent.getPersonId());
+ addEventIfKnownObject(homeEvent, homeEvent.getCameraId());
+ }
+
+ private void addEventIfKnownObject(HomeEvent homeEvent, @Nullable String objectId) {
+ if (objectId == null) {
+ return;
}
- String cameraId = homeEvent.getCameraId();
- handler.getActiveChildren().stream().filter(handler -> cameraId.equals(handler.getId())).findFirst()
- .ifPresent(handler -> {
- homeEvent.setIgnoredForThingUpdate(true);
- handler.setNewData(homeEvent);
- });
+ handler.getActiveChildren(FeatureArea.SECURITY).filter(child -> child.getId().equals(objectId))
+ .forEach(child -> child.setNewData(homeEvent.ignoringForThingUpdate()));
}
@Override
protected List<NAObject> updateReadings(SecurityApi api) {
List<NAObject> result = new ArrayList<>();
try {
- for (HomeEvent event : api.getHomeEvents(handler.getId(), freshestEventTime)) {
+ for (HomeEvent event : api.getHomeEvents(securityId, freshestEventTime)) {
HomeEvent previousEvent = eventBuffer.get(event.getCameraId());
if (previousEvent == null || previousEvent.getTime().isBefore(event.getTime())) {
eventBuffer.put(event.getCameraId(), event);
}
}
} catch (NetatmoException e) {
- logger.warn("Error retrieving last events for home '{}' : {}", handler.getId(), e.getMessage());
+ logger.warn("Error retrieving last events for home '{}' : {}", securityId, e.getMessage());
}
return result;
}
+ public NAObjectMap<HomeDataPerson> getPersons() {
+ return persons;
+ }
+
+ public NAObjectMap<HomeDataModule> getModules() {
+ return modules;
+ }
+
public @Nullable HomeEvent getLastPersonEvent(String personId) {
HomeEvent event = eventBuffer.get(personId);
if (event == null) {
private Collection<HomeEvent> requestDeviceEvents(String moduleId, String deviceType) {
return getApi().map(api -> {
try {
- return api.getDeviceEvents(handler.getId(), moduleId, deviceType);
+ return api.getDeviceEvents(securityId, moduleId, deviceType);
} catch (NetatmoException e) {
logger.warn("Error retrieving last events of camera '{}' : {}", moduleId, e.getMessage());
return null;
private Collection<HomeEvent> requestPersonEvents(String personId) {
return getApi().map(api -> {
try {
- return api.getPersonEvents(handler.getId(), personId);
+ return api.getPersonEvents(securityId, personId);
} catch (NetatmoException e) {
logger.warn("Error retrieving last events of person '{}' : {}", personId, e.getMessage());
return null;
public void setPersonAway(String personId, boolean away) {
getApi().ifPresent(api -> {
try {
- api.setPersonAwayStatus(handler.getId(), personId, away);
+ api.setPersonAwayStatus(securityId, personId, away);
handler.expireData();
} catch (NetatmoException e) {
logger.warn("Error setting person away/at home '{}' : {}", personId, e.getMessage());
}
public @Nullable String ping(String vpnUrl) {
- return getApi().map(api -> {
- return api.ping(vpnUrl);
- }).orElse(null);
+ return getApi().map(api -> api.ping(vpnUrl)).orElse(null);
}
public void changeStatus(@Nullable String localURL, boolean status) {
public void changeFloodlightMode(String cameraId, FloodLightMode mode) {
getApi().ifPresent(api -> {
try {
- api.changeFloodLightMode(handler.getId(), cameraId, mode);
+ api.changeFloodLightMode(securityId, cameraId, mode);
handler.expireData();
} catch (NetatmoException e) {
logger.warn("Error changing Presence floodlight mode '{}' : {}", mode, e.getMessage());
</config-description>
<config-description uri="netatmo:home">
- <parameter name="id" type="text" required="true">
+ <parameter name="id" type="text" required="false">
<label>@text/config.thingId.label</label>
<description>@text/config.thingId.description</description>
</parameter>
+ <parameter name="securityId" type="text" required="false">
+ <label>@text/config.securityId.label</label>
+ <description>@text/config.securityId.description</description>
+ <advanced>true</advanced>
+ </parameter>
+
+ <parameter name="energyId" type="text" required="false">
+ <label>@text/config.energyId.label</label>
+ <description>@text/config.energyId.description</description>
+ <advanced>true</advanced>
+ </parameter>
+
<parameter name="refreshInterval" type="integer" min="20" unit="s">
<label>@text/config.refreshInterval.label</label>
<description>@text/config.refreshInterval.description</description>
config.equipmentId.description = ID of the device (MAC address).
config.thingId.label = Thing ID
config.thingId.description = Unique identifier of the thing defined by Netatmo.
+config.securityId.label = Security ID
+config.securityId.description = Unique identifier of the home handling security devices.
+config.energyId.label = Energy ID
+config.energyId.description = Unique identifier of the home handling energy devices.
config.refreshInterval.label = Refresh Interval
config.refreshInterval.description = The refresh interval to poll Netatmo API (in seconds).