[netatmo] Compatibility with OpenHAB 3 (Update to newer Swagger version and code generation libraries replaced) (#8274) (#8652)
Swagger upgrade for the Netatmo binding (required to use the OAS 3 Swagger annotations, the old annotations dependencies were removed with OpenHAB 3) - Swagger-Codegen updated to the latest version (to generate the OAS 3 Swagger annotations) - Retrofit replaced by the default code generation (Retrofit 1 code generation is broken with newer swagger-codegen versions and an update to Retrofit 2 is also incompatible and would require more dependencies) - NULL handling for collections introduced (newer versions of the Swagger codegen return NULL for empty collections instead of an empty collection ...) - The binding is now working completely again (compiles and starts), but there are still some TODOs Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> sven.strohschein@gmail.com>pull/8653/head
parent
d2e5f71009
commit
f24f4971d6
|
@ -19,6 +19,11 @@ commons-codec
|
||||||
* Project; https://commons.apache.org/proper/commons-codec
|
* Project; https://commons.apache.org/proper/commons-codec
|
||||||
* Source: https://commons.apache.org/proper/commons-codec
|
* Source: https://commons.apache.org/proper/commons-codec
|
||||||
|
|
||||||
|
gson-fire
|
||||||
|
* License: Apache 2.0 License
|
||||||
|
* Project: http://gsonfire.io
|
||||||
|
* Source: https://github.com/julman99/gson-fire
|
||||||
|
|
||||||
json
|
json
|
||||||
* License: JSON License
|
* License: JSON License
|
||||||
* Project: https://www.json.org
|
* Project: https://www.json.org
|
||||||
|
@ -43,8 +48,3 @@ netatmo-swagger-decl
|
||||||
* License: MIT License
|
* License: MIT License
|
||||||
* Project: https://dev.netatmo.com
|
* Project: https://dev.netatmo.com
|
||||||
* Source: https://github.com/cbornet/netatmo-swagger-decl
|
* Source: https://github.com/cbornet/netatmo-swagger-decl
|
||||||
|
|
||||||
retrofit
|
|
||||||
* License: Apache 2.0 License
|
|
||||||
* Project: https://square.github.io/retrofit
|
|
||||||
* Source: https://github.com/square/retrofit
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<name>openHAB Add-ons :: Bundles :: Netatmo Binding</name>
|
<name>openHAB Add-ons :: Bundles :: Netatmo Binding</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<dep.noembedding>com.squareup.okhttp.okhttp,com.squareup.okio.okio-1.3.0,com.squareup.retrofit.retrofit,org.apache.oltu.oauth2.client,org.apache.oltu.oauth2.common</dep.noembedding>
|
<bnd.importpackage>!android.*,!com.android.org.*,!org.apache.harmony.*,!sun.*,!org.apache.oltu.*</bnd.importpackage>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -26,21 +26,39 @@
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.osgiify</groupId>
|
<groupId>com.squareup.okhttp</groupId>
|
||||||
<artifactId>com.squareup.okhttp.okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
<version>2.3.0</version>
|
<version>2.7.5</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.google.android</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp</groupId>
|
||||||
|
<artifactId>logging-interceptor</artifactId>
|
||||||
|
<version>2.7.5</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.google.android</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>1.6.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.osgiify</groupId>
|
<groupId>io.gsonfire</groupId>
|
||||||
<artifactId>com.squareup.okio.okio-1.3.0</artifactId>
|
<artifactId>gson-fire</artifactId>
|
||||||
<version>1.3.0</version>
|
<version>1.8.4</version>
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openhab.osgiify</groupId>
|
|
||||||
<artifactId>com.squareup.retrofit.retrofit</artifactId>
|
|
||||||
<version>1.9.0</version>
|
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -55,14 +73,20 @@
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
<version>1.8</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>io.swagger</groupId>
|
<groupId>io.swagger.codegen.v3</groupId>
|
||||||
<artifactId>swagger-codegen-maven-plugin</artifactId>
|
<artifactId>swagger-codegen-maven-plugin</artifactId>
|
||||||
<version>2.1.6</version>
|
<version>3.0.21</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<goals>
|
<goals>
|
||||||
|
@ -71,9 +95,13 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<inputSpec>https://raw.githubusercontent.com/cbornet/netatmo-swagger-decl/35e27745fb0d432bc6c8b5ec7a83ed2a09944cea/spec/swagger.yaml</inputSpec>
|
<inputSpec>https://raw.githubusercontent.com/cbornet/netatmo-swagger-decl/35e27745fb0d432bc6c8b5ec7a83ed2a09944cea/spec/swagger.yaml</inputSpec>
|
||||||
<language>java</language>
|
<language>java</language>
|
||||||
<library>retrofit</library>
|
<generateApiTests>false</generateApiTests>
|
||||||
|
<generateModelTests>false</generateModelTests>
|
||||||
<configOptions>
|
<configOptions>
|
||||||
<sourceFolder>src/main/java</sourceFolder>
|
<sourceFolder>src/main/java</sourceFolder>
|
||||||
|
<java8>true</java8>
|
||||||
|
<dateLibrary>java8-localdatetime</dateLibrary>
|
||||||
|
<useRuntimeException>true</useRuntimeException>
|
||||||
</configOptions>
|
</configOptions>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
|
|
@ -5,11 +5,6 @@
|
||||||
<feature name="openhab-binding-netatmo" description="Netatmo Binding" version="${project.version}">
|
<feature name="openhab-binding-netatmo" description="Netatmo Binding" version="${project.version}">
|
||||||
<feature>openhab-runtime-base</feature>
|
<feature>openhab-runtime-base</feature>
|
||||||
<bundle dependency="true">mvn:org.openhab.osgiify/org.json.json/20131018</bundle>
|
<bundle dependency="true">mvn:org.openhab.osgiify/org.json.json/20131018</bundle>
|
||||||
<bundle dependency="true">mvn:org.openhab.osgiify/com.squareup.okhttp.okhttp/2.3.0</bundle>
|
|
||||||
<bundle dependency="true">mvn:org.openhab.osgiify/com.squareup.okio.okio-1.3.0/1.3.0</bundle>
|
|
||||||
<bundle dependency="true">mvn:org.openhab.osgiify/com.squareup.retrofit.retrofit/1.9.0</bundle>
|
|
||||||
<bundle dependency="true">mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.client/1.0.0</bundle>
|
|
||||||
<bundle dependency="true">mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.common/1.0.0</bundle>
|
|
||||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.netatmo/${project.version}</bundle>
|
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.netatmo/${project.version}</bundle>
|
||||||
</feature>
|
</feature>
|
||||||
</features>
|
</features>
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2020 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;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link APIUtils} provides util methods for the usage of the generated API classes.
|
||||||
|
*
|
||||||
|
* @author Sven Strohschein - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public final class APIUtils {
|
||||||
|
|
||||||
|
private APIUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Stream<T> nonNullStream(Collection<T> collection) {
|
||||||
|
return Optional.ofNullable(collection).stream().flatMap(Collection::stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> nonNullList(List<T> list) {
|
||||||
|
return Optional.ofNullable(list).orElse(Collections.emptyList());
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,6 @@ import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.openhab.binding.netatmo.internal.ChannelTypeUtils;
|
import org.openhab.binding.netatmo.internal.ChannelTypeUtils;
|
||||||
|
@ -53,10 +52,11 @@ public abstract class CameraHandler extends NetatmoModuleHandler<NAWelcomeCamera
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(CameraHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(CameraHandler.class);
|
||||||
|
|
||||||
private @Nullable CameraAddress cameraAddress;
|
private Optional<CameraAddress> cameraAddress;
|
||||||
|
|
||||||
protected CameraHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
|
protected CameraHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
|
||||||
super(thing, timeZoneProvider);
|
super(thing, timeZoneProvider);
|
||||||
|
cameraAddress = Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -114,7 +114,7 @@ public abstract class CameraHandler extends NetatmoModuleHandler<NAWelcomeCamera
|
||||||
}
|
}
|
||||||
|
|
||||||
protected State getIsLocalState() {
|
protected State getIsLocalState() {
|
||||||
return getModule().map(m -> toOnOffType(m.getIsLocal())).orElse(UnDefType.UNDEF);
|
return getModule().map(m -> toOnOffType(m.isIsLocal())).orElse(UnDefType.UNDEF);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected State getLivePictureURLState() {
|
protected State getLivePictureURLState() {
|
||||||
|
@ -181,7 +181,7 @@ public abstract class CameraHandler extends NetatmoModuleHandler<NAWelcomeCamera
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLocal() {
|
private boolean isLocal() {
|
||||||
return getModule().map(NAWelcomeCamera::getIsLocal).orElse(false);
|
return getModule().map(NAWelcomeCamera::isIsLocal).orElse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void switchVideoSurveillance(boolean isOn) {
|
private void switchVideoSurveillance(boolean isOn) {
|
||||||
|
@ -201,20 +201,20 @@ public abstract class CameraHandler extends NetatmoModuleHandler<NAWelcomeCamera
|
||||||
|
|
||||||
protected Optional<String> getLocalCameraURL() {
|
protected Optional<String> getLocalCameraURL() {
|
||||||
Optional<String> vpnURLOptional = getVpnUrl();
|
Optional<String> vpnURLOptional = getVpnUrl();
|
||||||
CameraAddress address = cameraAddress;
|
Optional<CameraAddress> address = cameraAddress;
|
||||||
if (vpnURLOptional.isPresent()) {
|
if (vpnURLOptional.isPresent()) {
|
||||||
final String vpnURL = vpnURLOptional.get();
|
final String vpnURL = vpnURLOptional.get();
|
||||||
|
|
||||||
// The local address is (re-)requested when it wasn't already determined or when the vpn address was
|
// The local address is (re-)requested when it wasn't already determined or when the vpn address was
|
||||||
// changed.
|
// changed.
|
||||||
if (address == null || address.isVpnURLChanged(vpnURL)) {
|
if (!address.isPresent() || address.get().isVpnURLChanged(vpnURL)) {
|
||||||
Optional<JSONObject> json = executeGETRequestJSON(vpnURL + PING_URL_PATH);
|
Optional<JSONObject> json = executeGETRequestJSON(vpnURL + PING_URL_PATH);
|
||||||
address = json.map(j -> j.optString("local_url", null))
|
address = json.map(j -> j.optString("local_url", null))
|
||||||
.map(localURL -> new CameraAddress(vpnURL, localURL)).orElse(null);
|
.map(localURL -> new CameraAddress(vpnURL, localURL));
|
||||||
cameraAddress = address;
|
cameraAddress = address;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Optional.ofNullable(address).map(CameraAddress::getLocalURL);
|
return address.map(CameraAddress::getLocalURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<JSONObject> executeGETRequestJSON(String url) {
|
private Optional<JSONObject> executeGETRequestJSON(String url) {
|
||||||
|
|
|
@ -12,9 +12,11 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.discovery;
|
package org.openhab.binding.netatmo.internal.discovery;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
@ -71,28 +73,28 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl
|
||||||
public void startScan() {
|
public void startScan() {
|
||||||
if (netatmoBridgeHandler.configuration.readStation) {
|
if (netatmoBridgeHandler.configuration.readStation) {
|
||||||
netatmoBridgeHandler.getStationsDataBody(null).ifPresent(dataBody -> {
|
netatmoBridgeHandler.getStationsDataBody(null).ifPresent(dataBody -> {
|
||||||
dataBody.getDevices().forEach(station -> {
|
nonNullList(dataBody.getDevices()).forEach(station -> {
|
||||||
discoverWeatherStation(station);
|
discoverWeatherStation(station);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (netatmoBridgeHandler.configuration.readHealthyHomeCoach) {
|
if (netatmoBridgeHandler.configuration.readHealthyHomeCoach) {
|
||||||
netatmoBridgeHandler.getHomecoachDataBody(null).ifPresent(dataBody -> {
|
netatmoBridgeHandler.getHomecoachDataBody(null).ifPresent(dataBody -> {
|
||||||
dataBody.getDevices().forEach(homecoach -> {
|
nonNullList(dataBody.getDevices()).forEach(homecoach -> {
|
||||||
discoverHomeCoach(homecoach);
|
discoverHomeCoach(homecoach);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (netatmoBridgeHandler.configuration.readThermostat) {
|
if (netatmoBridgeHandler.configuration.readThermostat) {
|
||||||
netatmoBridgeHandler.getThermostatsDataBody(null).ifPresent(dataBody -> {
|
netatmoBridgeHandler.getThermostatsDataBody(null).ifPresent(dataBody -> {
|
||||||
dataBody.getDevices().forEach(plug -> {
|
nonNullList(dataBody.getDevices()).forEach(plug -> {
|
||||||
discoverThermostat(plug);
|
discoverThermostat(plug);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (netatmoBridgeHandler.configuration.readWelcome || netatmoBridgeHandler.configuration.readPresence) {
|
if (netatmoBridgeHandler.configuration.readWelcome || netatmoBridgeHandler.configuration.readPresence) {
|
||||||
netatmoBridgeHandler.getWelcomeDataBody(null).ifPresent(dataBody -> {
|
netatmoBridgeHandler.getWelcomeDataBody(null).ifPresent(dataBody -> {
|
||||||
dataBody.getHomes().forEach(home -> {
|
nonNullList(dataBody.getHomes()).forEach(home -> {
|
||||||
discoverWelcomeHome(home);
|
discoverWelcomeHome(home);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -123,7 +125,7 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl
|
||||||
|
|
||||||
private void discoverThermostat(NAPlug plug) {
|
private void discoverThermostat(NAPlug plug) {
|
||||||
onDeviceAddedInternal(plug.getId(), null, plug.getType(), plug.getStationName(), plug.getFirmware());
|
onDeviceAddedInternal(plug.getId(), null, plug.getType(), plug.getStationName(), plug.getFirmware());
|
||||||
plug.getModules().forEach(thermostat -> {
|
nonNullList(plug.getModules()).forEach(thermostat -> {
|
||||||
onDeviceAddedInternal(thermostat.getId(), plug.getId(), thermostat.getType(), thermostat.getModuleName(),
|
onDeviceAddedInternal(thermostat.getId(), plug.getId(), thermostat.getType(), thermostat.getModuleName(),
|
||||||
thermostat.getFirmware());
|
thermostat.getFirmware());
|
||||||
});
|
});
|
||||||
|
@ -135,11 +137,11 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl
|
||||||
}
|
}
|
||||||
|
|
||||||
private void discoverWeatherStation(NAMain station) {
|
private void discoverWeatherStation(NAMain station) {
|
||||||
final boolean isFavorite = station.getFavorite() != null && station.getFavorite();
|
final boolean isFavorite = station.isFavorite() != null && station.isFavorite();
|
||||||
final String weatherStationName = createWeatherStationName(station, isFavorite);
|
final String weatherStationName = createWeatherStationName(station, isFavorite);
|
||||||
|
|
||||||
onDeviceAddedInternal(station.getId(), null, station.getType(), weatherStationName, station.getFirmware());
|
onDeviceAddedInternal(station.getId(), null, station.getType(), weatherStationName, station.getFirmware());
|
||||||
station.getModules().forEach(module -> {
|
nonNullList(station.getModules()).forEach(module -> {
|
||||||
onDeviceAddedInternal(module.getId(), station.getId(), module.getType(),
|
onDeviceAddedInternal(module.getId(), station.getId(), module.getType(),
|
||||||
createWeatherModuleName(station, module, isFavorite), module.getFirmware());
|
createWeatherModuleName(station, module, isFavorite), module.getFirmware());
|
||||||
});
|
});
|
||||||
|
@ -148,15 +150,16 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl
|
||||||
private void discoverWelcomeHome(NAWelcomeHome home) {
|
private void discoverWelcomeHome(NAWelcomeHome home) {
|
||||||
// I observed that Thermostat homes are also reported here by Netatmo API
|
// I observed that Thermostat homes are also reported here by Netatmo API
|
||||||
// So I ignore homes that have an empty list of cameras
|
// So I ignore homes that have an empty list of cameras
|
||||||
if (!home.getCameras().isEmpty()) {
|
List<NAWelcomeCamera> cameras = nonNullList(home.getCameras());
|
||||||
|
if (!cameras.isEmpty()) {
|
||||||
onDeviceAddedInternal(home.getId(), null, WELCOME_HOME_THING_TYPE.getId(), home.getName(), null);
|
onDeviceAddedInternal(home.getId(), null, WELCOME_HOME_THING_TYPE.getId(), home.getName(), null);
|
||||||
// Discover Cameras
|
// Discover Cameras
|
||||||
home.getCameras().forEach(camera -> {
|
cameras.forEach(camera -> {
|
||||||
onDeviceAddedInternal(camera.getId(), home.getId(), camera.getType(), camera.getName(), null);
|
onDeviceAddedInternal(camera.getId(), home.getId(), camera.getType(), camera.getName(), null);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Discover Known Persons
|
// Discover Known Persons
|
||||||
home.getPersons().stream().filter(person -> person.getPseudo() != null).forEach(person -> {
|
nonNullStream(home.getPersons()).filter(person -> person.getPseudo() != null).forEach(person -> {
|
||||||
onDeviceAddedInternal(person.getId(), home.getId(), WELCOME_PERSON_THING_TYPE.getId(),
|
onDeviceAddedInternal(person.getId(), home.getId(), WELCOME_PERSON_THING_TYPE.getId(),
|
||||||
person.getPseudo(), null);
|
person.getPseudo(), null);
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.handler;
|
package org.openhab.binding.netatmo.internal.handler;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.MEASURABLE_CHANNELS;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.MEASURABLE_CHANNELS;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -24,7 +25,7 @@ import org.openhab.binding.netatmo.internal.ChannelTypeUtils;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
|
||||||
import io.swagger.client.CollectionFormats.CSVParams;
|
import io.swagger.client.model.NAMeasureBodyElem;
|
||||||
import io.swagger.client.model.NAMeasureResponse;
|
import io.swagger.client.model.NAMeasureResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,10 +65,11 @@ public class MeasurableChannels {
|
||||||
int index = measuredChannels.indexOf(channelId);
|
int index = measuredChannels.indexOf(channelId);
|
||||||
NAMeasureResponse theMeasures = measures;
|
NAMeasureResponse theMeasures = measures;
|
||||||
if (index != -1 && theMeasures != null) {
|
if (index != -1 && theMeasures != null) {
|
||||||
if (!theMeasures.getBody().isEmpty()) {
|
List<NAMeasureBodyElem> body = nonNullList(theMeasures.getBody());
|
||||||
List<List<Float>> valueList = theMeasures.getBody().get(0).getValue();
|
if (!body.isEmpty()) {
|
||||||
|
List<List<Float>> valueList = nonNullList(body.get(0).getValue());
|
||||||
if (!valueList.isEmpty()) {
|
if (!valueList.isEmpty()) {
|
||||||
List<Float> values = valueList.get(0);
|
List<Float> values = nonNullList(valueList.get(0));
|
||||||
if (values.size() >= index) {
|
if (values.size() >= index) {
|
||||||
Float value = values.get(index);
|
Float value = values.get(index);
|
||||||
return Optional.of(ChannelTypeUtils.toDecimalType(value));
|
return Optional.of(ChannelTypeUtils.toDecimalType(value));
|
||||||
|
@ -78,9 +80,9 @@ public class MeasurableChannels {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<CSVParams> getAsCsv() {
|
public Optional<List<String>> getMeasuredChannels() {
|
||||||
if (!measuredChannels.isEmpty()) {
|
if (!measuredChannels.isEmpty()) {
|
||||||
return Optional.of(new CSVParams(measuredChannels));
|
return Optional.of(measuredChannels);
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,13 @@ package org.openhab.binding.netatmo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
@ -26,7 +28,13 @@ import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.apache.oltu.oauth2.client.OAuthClient;
|
||||||
|
import org.apache.oltu.oauth2.client.URLConnectionClient;
|
||||||
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
|
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
|
||||||
|
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
|
||||||
|
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
|
||||||
|
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
|
||||||
|
import org.apache.oltu.oauth2.common.message.types.GrantType;
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.netatmo.internal.config.NetatmoBridgeConfiguration;
|
import org.openhab.binding.netatmo.internal.config.NetatmoBridgeConfiguration;
|
||||||
|
@ -44,25 +52,20 @@ import org.openhab.core.types.Command;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.squareup.okhttp.OkHttpClient;
|
|
||||||
|
|
||||||
import io.swagger.client.ApiClient;
|
import io.swagger.client.ApiClient;
|
||||||
import io.swagger.client.CollectionFormats.CSVParams;
|
import io.swagger.client.ApiException;
|
||||||
import io.swagger.client.api.HealthyhomecoachApi;
|
import io.swagger.client.api.HealthyhomecoachApi;
|
||||||
import io.swagger.client.api.PartnerApi;
|
import io.swagger.client.api.PartnerApi;
|
||||||
import io.swagger.client.api.StationApi;
|
import io.swagger.client.api.StationApi;
|
||||||
import io.swagger.client.api.ThermostatApi;
|
import io.swagger.client.api.ThermostatApi;
|
||||||
import io.swagger.client.api.WelcomeApi;
|
import io.swagger.client.api.WelcomeApi;
|
||||||
|
import io.swagger.client.auth.Authentication;
|
||||||
import io.swagger.client.auth.OAuth;
|
import io.swagger.client.auth.OAuth;
|
||||||
import io.swagger.client.auth.OAuthFlow;
|
|
||||||
import io.swagger.client.model.NAHealthyHomeCoachDataBody;
|
import io.swagger.client.model.NAHealthyHomeCoachDataBody;
|
||||||
import io.swagger.client.model.NAMeasureBodyElem;
|
import io.swagger.client.model.NAMeasureBodyElem;
|
||||||
import io.swagger.client.model.NAStationDataBody;
|
import io.swagger.client.model.NAStationDataBody;
|
||||||
import io.swagger.client.model.NAThermostatDataBody;
|
import io.swagger.client.model.NAThermostatDataBody;
|
||||||
import io.swagger.client.model.NAWelcomeHomeData;
|
import io.swagger.client.model.NAWelcomeHomeData;
|
||||||
import retrofit.RestAdapter.LogLevel;
|
|
||||||
import retrofit.RetrofitError;
|
|
||||||
import retrofit.RetrofitError.Kind;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link NetatmoBridgeHandler} is the handler for a Netatmo API and connects it
|
* {@link NetatmoBridgeHandler} is the handler for a Netatmo API and connects it
|
||||||
|
@ -79,25 +82,34 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler {
|
||||||
|
|
||||||
public NetatmoBridgeConfiguration configuration = new NetatmoBridgeConfiguration();
|
public NetatmoBridgeConfiguration configuration = new NetatmoBridgeConfiguration();
|
||||||
private @Nullable ScheduledFuture<?> refreshJob;
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
private @Nullable APIMap apiMap;
|
private @Nullable APICreator apiCreator;
|
||||||
private @Nullable WelcomeWebHookServlet webHookServlet;
|
private @Nullable WelcomeWebHookServlet webHookServlet;
|
||||||
private List<NetatmoDataListener> dataListeners = new CopyOnWriteArrayList<>();
|
private List<NetatmoDataListener> dataListeners = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
private class APIMap extends HashMap<Class<?>, Object> {
|
private static class APICreator {
|
||||||
private static final long serialVersionUID = -2024031764691952343L;
|
|
||||||
private ApiClient apiClient;
|
|
||||||
|
|
||||||
public APIMap(ApiClient apiClient) {
|
private final ApiClient apiClient;
|
||||||
|
private final Map<Class<?>, Object> apiMap;
|
||||||
|
|
||||||
|
private APICreator(ApiClient apiClient) {
|
||||||
super();
|
super();
|
||||||
this.apiClient = apiClient;
|
this.apiClient = apiClient;
|
||||||
|
apiMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(Class<?> apiClass) {
|
@SuppressWarnings("unchecked")
|
||||||
if (!super.containsKey(apiClass)) {
|
public <T> T getAPI(Class<T> apiClass) {
|
||||||
Object api = apiClient.createService(apiClass);
|
T api = (T) apiMap.get(apiClass);
|
||||||
super.put(apiClass, api);
|
if (api == null) {
|
||||||
|
try {
|
||||||
|
api = apiClass.getDeclaredConstructor(ApiClient.class).newInstance(apiClient);
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException
|
||||||
|
| NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("Error on executing API class constructor!", e);
|
||||||
}
|
}
|
||||||
return super.get(apiClass);
|
apiMap.put(apiClass, api);
|
||||||
|
}
|
||||||
|
return api;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,14 +148,8 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler {
|
||||||
// I use a connection to Netatmo API using PartnerAPI to ensure that API is reachable
|
// I use a connection to Netatmo API using PartnerAPI to ensure that API is reachable
|
||||||
getPartnerApi().partnerdevices();
|
getPartnerApi().partnerdevices();
|
||||||
connectionSucceed();
|
connectionSucceed();
|
||||||
} catch (RetrofitError e) {
|
} catch (ApiException e) {
|
||||||
if (e.getKind() == Kind.NETWORK) {
|
switch (e.getCode()) {
|
||||||
logger.warn("Network error while connecting to Netatmo API, will retry in {} s",
|
|
||||||
configuration.reconnectInterval);
|
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
|
||||||
"Netatmo Access Failed, will retry in " + configuration.reconnectInterval + " seconds.");
|
|
||||||
} else {
|
|
||||||
switch (e.getResponse().getStatus()) {
|
|
||||||
case 404: // If no partner station has been associated - likely to happen - we'll have this
|
case 404: // If no partner station has been associated - likely to happen - we'll have this
|
||||||
// error
|
// error
|
||||||
// but it means connection to API is OK
|
// but it means connection to API is OK
|
||||||
|
@ -165,8 +171,6 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler {
|
||||||
}
|
}
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
"Unable to connect Netatmo API : " + e.getLocalizedMessage());
|
"Unable to connect Netatmo API : " + e.getLocalizedMessage());
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
logger.warn("Unable to connect Netatmo API : {}", e.getMessage(), e);
|
logger.warn("Unable to connect Netatmo API : {}", e.getMessage(), e);
|
||||||
|
@ -177,22 +181,31 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler {
|
||||||
}, 2, configuration.reconnectInterval, TimeUnit.SECONDS);
|
}, 2, configuration.reconnectInterval, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeApiClient() throws RetrofitError {
|
private void initializeApiClient() {
|
||||||
|
try {
|
||||||
ApiClient apiClient = new ApiClient();
|
ApiClient apiClient = new ApiClient();
|
||||||
|
|
||||||
OAuth auth = new OAuth(new OkHttpClient(),
|
OAuthClientRequest oAuthRequest = OAuthClientRequest.tokenLocation("https://api.netatmo.net/oauth2/token")
|
||||||
OAuthClientRequest.tokenLocation("https://api.netatmo.net/oauth2/token"));
|
.setClientId(configuration.clientId).setClientSecret(configuration.clientSecret)
|
||||||
auth.setFlow(OAuthFlow.password);
|
.setUsername(configuration.username).setPassword(configuration.password).setScope(getApiScope())
|
||||||
auth.setAuthenticationRequestBuilder(OAuthClientRequest.authorizationLocation(""));
|
.setGrantType(GrantType.PASSWORD).buildBodyMessage();
|
||||||
|
|
||||||
apiClient.getApiAuthorizations().put("password_oauth", auth);
|
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
|
||||||
apiClient.getTokenEndPoint().setClientId(configuration.clientId).setClientSecret(configuration.clientSecret)
|
|
||||||
.setUsername(configuration.username).setPassword(configuration.password).setScope(getApiScope());
|
|
||||||
|
|
||||||
apiClient.configureFromOkclient(new OkHttpClient());
|
OAuthJSONAccessTokenResponse accessTokenResponse = oAuthClient.accessToken(oAuthRequest,
|
||||||
apiClient.getAdapterBuilder().setLogLevel(logger.isDebugEnabled() ? LogLevel.FULL : LogLevel.NONE);
|
OAuthJSONAccessTokenResponse.class);
|
||||||
|
String accessToken = accessTokenResponse.getAccessToken();
|
||||||
|
|
||||||
apiMap = new APIMap(apiClient);
|
for (Authentication authentication : apiClient.getAuthentications().values()) {
|
||||||
|
if (authentication instanceof OAuth) {
|
||||||
|
((OAuth) authentication).setAccessToken(accessToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apiCreator = new APICreator(apiClient);
|
||||||
|
} catch (OAuthSystemException | OAuthProblemException e) {
|
||||||
|
throw new RuntimeException("Error on trying to get an access token!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getApiScope() {
|
private String getApiScope() {
|
||||||
|
@ -231,28 +244,23 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable PartnerApi getPartnerApi() {
|
public @Nullable PartnerApi getPartnerApi() {
|
||||||
APIMap map = apiMap;
|
return apiCreator != null ? apiCreator.getAPI(PartnerApi.class) : null;
|
||||||
return map != null ? (PartnerApi) map.get(PartnerApi.class) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<StationApi> getStationApi() {
|
public Optional<StationApi> getStationApi() {
|
||||||
APIMap map = apiMap;
|
return apiCreator != null ? Optional.of(apiCreator.getAPI(StationApi.class)) : Optional.empty();
|
||||||
return map != null ? Optional.of((StationApi) map.get(StationApi.class)) : Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<HealthyhomecoachApi> getHomeCoachApi() {
|
public Optional<HealthyhomecoachApi> getHomeCoachApi() {
|
||||||
APIMap map = apiMap;
|
return apiCreator != null ? Optional.of(apiCreator.getAPI(HealthyhomecoachApi.class)) : Optional.empty();
|
||||||
return map != null ? Optional.of((HealthyhomecoachApi) map.get(HealthyhomecoachApi.class)) : Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ThermostatApi> getThermostatApi() {
|
public Optional<ThermostatApi> getThermostatApi() {
|
||||||
APIMap map = apiMap;
|
return apiCreator != null ? Optional.of(apiCreator.getAPI(ThermostatApi.class)) : Optional.empty();
|
||||||
return map != null ? Optional.of((ThermostatApi) map.get(ThermostatApi.class)) : Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<WelcomeApi> getWelcomeApi() {
|
public Optional<WelcomeApi> getWelcomeApi() {
|
||||||
APIMap map = apiMap;
|
return apiCreator != null ? Optional.of(apiCreator.getAPI(WelcomeApi.class)) : Optional.empty();
|
||||||
return map != null ? Optional.of((WelcomeApi) map.get(WelcomeApi.class)) : Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -283,8 +291,8 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler {
|
||||||
|
|
||||||
public List<Float> getStationMeasureResponses(String equipmentId, @Nullable String moduleId, String scale,
|
public List<Float> getStationMeasureResponses(String equipmentId, @Nullable String moduleId, String scale,
|
||||||
List<String> types) {
|
List<String> types) {
|
||||||
List<NAMeasureBodyElem> data = getStationApi().map(api -> api
|
List<NAMeasureBodyElem> data = getStationApi()
|
||||||
.getmeasure(equipmentId, scale, new CSVParams(types), moduleId, null, "last", 1, true, false).getBody())
|
.map(api -> api.getmeasure(equipmentId, scale, types, moduleId, null, "last", 1, true, false).getBody())
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
NAMeasureBodyElem element = (data != null && data.size() > 0) ? data.get(0) : null;
|
NAMeasureBodyElem element = (data != null && data.size() > 0) ? data.get(0) : null;
|
||||||
|
|
|
@ -39,8 +39,8 @@ import org.openhab.core.types.UnDefType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import io.swagger.client.ApiException;
|
||||||
import io.swagger.client.model.NAPlace;
|
import io.swagger.client.model.NAPlace;
|
||||||
import retrofit.RetrofitError;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link NetatmoDeviceHandler} is the handler for a given
|
* {@link NetatmoDeviceHandler} is the handler for a given
|
||||||
|
@ -125,7 +125,7 @@ public abstract class NetatmoDeviceHandler<DEVICE> extends AbstractNetatmoThingH
|
||||||
Optional<DEVICE> newDeviceReading = Optional.empty();
|
Optional<DEVICE> newDeviceReading = Optional.empty();
|
||||||
try {
|
try {
|
||||||
newDeviceReading = updateReadings();
|
newDeviceReading = updateReadings();
|
||||||
} catch (RetrofitError e) {
|
} catch (ApiException e) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
// we also attach the stack trace
|
// we also attach the stack trace
|
||||||
logger.error("Unable to connect Netatmo API : {}", e.getMessage(), e);
|
logger.error("Unable to connect Netatmo API : {}", e.getMessage(), e);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.homecoach;
|
package org.openhab.binding.netatmo.internal.homecoach;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ public class NAHealthyHomeCoachHandler extends NetatmoDeviceHandler<NAHealthyHom
|
||||||
@Override
|
@Override
|
||||||
protected Optional<NAHealthyHomeCoach> updateReadings() {
|
protected Optional<NAHealthyHomeCoach> updateReadings() {
|
||||||
return getBridgeHandler().flatMap(handler -> handler.getHomecoachDataBody(getId()))
|
return getBridgeHandler().flatMap(handler -> handler.getHomecoachDataBody(getId()))
|
||||||
.map(dataBody -> dataBody.getDevices().stream()
|
.map(dataBody -> nonNullStream(dataBody.getDevices())
|
||||||
.filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
|
.filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ public class NAHealthyHomeCoachHandler extends NetatmoDeviceHandler<NAHealthyHom
|
||||||
if (dashboardData != null) {
|
if (dashboardData != null) {
|
||||||
switch (channelId) {
|
switch (channelId) {
|
||||||
case CHANNEL_CO2:
|
case CHANNEL_CO2:
|
||||||
return toQuantityType(dashboardData.getCO2(), API_CO2_UNIT);
|
return toQuantityType(dashboardData.getCo2(), API_CO2_UNIT);
|
||||||
case CHANNEL_TEMPERATURE:
|
case CHANNEL_TEMPERATURE:
|
||||||
return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
|
return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
|
||||||
case CHANNEL_HEALTH_INDEX:
|
case CHANNEL_HEALTH_INDEX:
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.station;
|
package org.openhab.binding.netatmo.internal.station;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
|
@ -51,10 +52,10 @@ public class NAMainHandler extends NetatmoDeviceHandler<NAMain> {
|
||||||
@Override
|
@Override
|
||||||
protected Optional<NAMain> updateReadings() {
|
protected Optional<NAMain> updateReadings() {
|
||||||
Optional<NAMain> result = getBridgeHandler().flatMap(handler -> handler.getStationsDataBody(getId()))
|
Optional<NAMain> result = getBridgeHandler().flatMap(handler -> handler.getStationsDataBody(getId()))
|
||||||
.map(dataBody -> dataBody.getDevices().stream()
|
.map(dataBody -> nonNullStream(dataBody.getDevices())
|
||||||
.filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
|
.filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
|
||||||
result.ifPresent(device -> {
|
result.ifPresent(device -> {
|
||||||
device.getModules().forEach(child -> childs.put(child.getId(), child));
|
nonNullList(device.getModules()).forEach(child -> childs.put(child.getId(), child));
|
||||||
});
|
});
|
||||||
|
|
||||||
updateMeasurements();
|
updateMeasurements();
|
||||||
|
@ -166,7 +167,7 @@ public class NAMainHandler extends NetatmoDeviceHandler<NAMain> {
|
||||||
if (dashboardData != null) {
|
if (dashboardData != null) {
|
||||||
switch (channelId) {
|
switch (channelId) {
|
||||||
case CHANNEL_CO2:
|
case CHANNEL_CO2:
|
||||||
return toQuantityType(dashboardData.getCO2(), API_CO2_UNIT);
|
return toQuantityType(dashboardData.getCo2(), API_CO2_UNIT);
|
||||||
case CHANNEL_TEMPERATURE:
|
case CHANNEL_TEMPERATURE:
|
||||||
return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
|
return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
|
||||||
case CHANNEL_MIN_TEMP:
|
case CHANNEL_MIN_TEMP:
|
||||||
|
@ -288,7 +289,7 @@ public class NAMainHandler extends NetatmoDeviceHandler<NAMain> {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Optional<NAMain> device = getDevice();
|
Optional<NAMain> device = getDevice();
|
||||||
if (device.isPresent()) {
|
if (device.isPresent()) {
|
||||||
Boolean reachable = device.get().getReachable();
|
Boolean reachable = device.get().isReachable();
|
||||||
result = reachable != null ? reachable.booleanValue() : false;
|
result = reachable != null ? reachable.booleanValue() : false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -177,7 +177,7 @@ public class NAModule1Handler extends NetatmoModuleHandler<NAStationModule> {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Optional<NAStationModule> module = getModule();
|
Optional<NAStationModule> module = getModule();
|
||||||
if (module.isPresent()) {
|
if (module.isPresent()) {
|
||||||
Boolean reachable = module.get().getReachable();
|
Boolean reachable = module.get().isReachable();
|
||||||
result = reachable != null ? reachable.booleanValue() : false;
|
result = reachable != null ? reachable.booleanValue() : false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class NAModule2Handler extends NetatmoModuleHandler<NAStationModule> {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Optional<NAStationModule> module = getModule();
|
Optional<NAStationModule> module = getModule();
|
||||||
if (module.isPresent()) {
|
if (module.isPresent()) {
|
||||||
Boolean reachable = module.get().getReachable();
|
Boolean reachable = module.get().isReachable();
|
||||||
result = reachable != null ? reachable.booleanValue() : false;
|
result = reachable != null ? reachable.booleanValue() : false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class NAModule3Handler extends NetatmoModuleHandler<NAStationModule> {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Optional<NAStationModule> module = getModule();
|
Optional<NAStationModule> module = getModule();
|
||||||
if (module.isPresent()) {
|
if (module.isPresent()) {
|
||||||
Boolean reachable = module.get().getReachable();
|
Boolean reachable = module.get().isReachable();
|
||||||
result = reachable != null ? reachable.booleanValue() : false;
|
result = reachable != null ? reachable.booleanValue() : false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -123,7 +123,7 @@ public class NAModule4Handler extends NetatmoModuleHandler<NAStationModule> {
|
||||||
case CHANNEL_TEMP_TREND:
|
case CHANNEL_TEMP_TREND:
|
||||||
return toStringType(dashboardData.getTempTrend());
|
return toStringType(dashboardData.getTempTrend());
|
||||||
case CHANNEL_CO2:
|
case CHANNEL_CO2:
|
||||||
return toQuantityType(dashboardData.getCO2(), API_CO2_UNIT);
|
return toQuantityType(dashboardData.getCo2(), API_CO2_UNIT);
|
||||||
case CHANNEL_TEMPERATURE:
|
case CHANNEL_TEMPERATURE:
|
||||||
return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
|
return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT);
|
||||||
case CHANNEL_DATE_MIN_TEMP:
|
case CHANNEL_DATE_MIN_TEMP:
|
||||||
|
@ -204,7 +204,7 @@ public class NAModule4Handler extends NetatmoModuleHandler<NAStationModule> {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Optional<NAStationModule> module = getModule();
|
Optional<NAStationModule> module = getModule();
|
||||||
if (module.isPresent()) {
|
if (module.isPresent()) {
|
||||||
Boolean reachable = module.get().getReachable();
|
Boolean reachable = module.get().isReachable();
|
||||||
result = reachable != null ? reachable.booleanValue() : false;
|
result = reachable != null ? reachable.booleanValue() : false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.thermostat;
|
package org.openhab.binding.netatmo.internal.thermostat;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
|
@ -47,10 +48,10 @@ public class NAPlugHandler extends NetatmoDeviceHandler<NAPlug> {
|
||||||
@Override
|
@Override
|
||||||
protected Optional<NAPlug> updateReadings() {
|
protected Optional<NAPlug> updateReadings() {
|
||||||
Optional<NAPlug> result = getBridgeHandler().flatMap(handler -> handler.getThermostatsDataBody(getId()))
|
Optional<NAPlug> result = getBridgeHandler().flatMap(handler -> handler.getThermostatsDataBody(getId()))
|
||||||
.map(dataBody -> dataBody.getDevices().stream()
|
.map(dataBody -> nonNullStream(dataBody.getDevices())
|
||||||
.filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
|
.filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
|
||||||
result.ifPresent(device -> {
|
result.ifPresent(device -> {
|
||||||
device.getModules().forEach(child -> childs.put(child.getId(), child));
|
nonNullList(device.getModules()).forEach(child -> childs.put(child.getId(), child));
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.thermostat;
|
package org.openhab.binding.netatmo.internal.thermostat;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
@Override
|
@Override
|
||||||
public void updateChannels(Object moduleObject) {
|
public void updateChannels(Object moduleObject) {
|
||||||
if (isRefreshRequired()) {
|
if (isRefreshRequired()) {
|
||||||
measurableChannels.getAsCsv().ifPresent(csvParams -> {
|
measurableChannels.getMeasuredChannels().ifPresent(csvParams -> {
|
||||||
getApi().ifPresent(api -> {
|
getApi().ifPresent(api -> {
|
||||||
NAMeasureResponse measures = api.getmeasure(getParentId(), "max", csvParams, getId(), null, null, 1,
|
NAMeasureResponse measures = api.getmeasure(getParentId(), "max", csvParams, getId(), null, null, 1,
|
||||||
true, true);
|
true, true);
|
||||||
|
@ -96,7 +97,7 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
|
|
||||||
private void updateStateDescription(NAThermostat thermostat) {
|
private void updateStateDescription(NAThermostat thermostat) {
|
||||||
List<StateOption> options = new ArrayList<>();
|
List<StateOption> options = new ArrayList<>();
|
||||||
for (NAThermProgram planning : thermostat.getThermProgramList()) {
|
for (NAThermProgram planning : nonNullList(thermostat.getThermProgramList())) {
|
||||||
options.add(new StateOption(planning.getProgramId(), planning.getName()));
|
options.add(new StateOption(planning.getProgramId(), planning.getName()));
|
||||||
}
|
}
|
||||||
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_PLANNING), options);
|
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_PLANNING), options);
|
||||||
|
@ -125,7 +126,7 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
if (setpoint != null) {
|
if (setpoint != null) {
|
||||||
Integer endTime = setpoint.getSetpointEndtime();
|
Integer endTime = setpoint.getSetpointEndtime();
|
||||||
if (endTime == null) {
|
if (endTime == null) {
|
||||||
endTime = getNextProgramTime(thermostat.get().getThermProgramList());
|
endTime = getNextProgramTime(nonNullList(thermostat.get().getThermProgramList()));
|
||||||
}
|
}
|
||||||
return toDateTimeType(endTime, timeZoneProvider.getTimeZone());
|
return toDateTimeType(endTime, timeZoneProvider.getTimeZone());
|
||||||
}
|
}
|
||||||
|
@ -138,8 +139,8 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
case CHANNEL_PLANNING: {
|
case CHANNEL_PLANNING: {
|
||||||
String currentPlanning = "-";
|
String currentPlanning = "-";
|
||||||
if (thermostat.isPresent()) {
|
if (thermostat.isPresent()) {
|
||||||
for (NAThermProgram program : thermostat.get().getThermProgramList()) {
|
for (NAThermProgram program : nonNullList(thermostat.get().getThermProgramList())) {
|
||||||
if (program.getSelected() == Boolean.TRUE) {
|
if (program.isSelected() == Boolean.TRUE) {
|
||||||
currentPlanning = program.getProgramId();
|
currentPlanning = program.getProgramId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,8 +165,8 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
if (setPoint != null) {
|
if (setPoint != null) {
|
||||||
String currentMode = setPoint.getSetpointMode();
|
String currentMode = setPoint.getSetpointMode();
|
||||||
|
|
||||||
NAThermProgram currentProgram = thermostat.get().getThermProgramList().stream()
|
NAThermProgram currentProgram = nonNullStream(thermostat.get().getThermProgramList())
|
||||||
.filter(p -> p.getSelected() != null && p.getSelected()).findFirst().get();
|
.filter(p -> p.isSelected() != null && p.isSelected()).findFirst().get();
|
||||||
switch (currentMode) {
|
switch (currentMode) {
|
||||||
case CHANNEL_SETPOINT_MODE_MANUAL:
|
case CHANNEL_SETPOINT_MODE_MANUAL:
|
||||||
return toDecimalType(setPoint.getSetpointTemp());
|
return toDecimalType(setPoint.getSetpointTemp());
|
||||||
|
@ -177,7 +178,7 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
return toDecimalType(zone1.getTemp());
|
return toDecimalType(zone1.getTemp());
|
||||||
case CHANNEL_SETPOINT_MODE_PROGRAM:
|
case CHANNEL_SETPOINT_MODE_PROGRAM:
|
||||||
NATimeTableItem currentProgramMode = getCurrentProgramMode(
|
NATimeTableItem currentProgramMode = getCurrentProgramMode(
|
||||||
thermostat.get().getThermProgramList());
|
nonNullList(thermostat.get().getThermProgramList()));
|
||||||
if (currentProgramMode != null) {
|
if (currentProgramMode != null) {
|
||||||
NAZone zone2 = getZone(currentProgram.getZones(), currentProgramMode.getId());
|
NAZone zone2 = getZone(currentProgram.getZones(), currentProgramMode.getId());
|
||||||
return toDecimalType(zone2.getTemp());
|
return toDecimalType(zone2.getTemp());
|
||||||
|
@ -192,7 +193,7 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private NAZone getZone(List<NAZone> zones, int searchedId) {
|
private NAZone getZone(List<NAZone> zones, int searchedId) {
|
||||||
return zones.stream().filter(z -> z.getId() == searchedId).findFirst().get();
|
return nonNullStream(zones).filter(z -> z.getId() == searchedId).findFirst().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getNetatmoProgramBaseTime() {
|
private long getNetatmoProgramBaseTime() {
|
||||||
|
@ -210,10 +211,10 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
long diff = (now.getTimeInMillis() - getNetatmoProgramBaseTime()) / 1000 / 60;
|
long diff = (now.getTimeInMillis() - getNetatmoProgramBaseTime()) / 1000 / 60;
|
||||||
|
|
||||||
Optional<NAThermProgram> currentProgram = thermProgramList.stream()
|
Optional<NAThermProgram> currentProgram = thermProgramList.stream()
|
||||||
.filter(p -> p.getSelected() != null && p.getSelected()).findFirst();
|
.filter(p -> p.isSelected() != null && p.isSelected()).findFirst();
|
||||||
|
|
||||||
if (currentProgram.isPresent()) {
|
if (currentProgram.isPresent()) {
|
||||||
Stream<NATimeTableItem> pastPrograms = currentProgram.get().getTimetable().stream()
|
Stream<NATimeTableItem> pastPrograms = nonNullStream(currentProgram.get().getTimetable())
|
||||||
.filter(t -> t.getMOffset() < diff);
|
.filter(t -> t.getMOffset() < diff);
|
||||||
Optional<NATimeTableItem> program = pastPrograms.reduce((first, second) -> second);
|
Optional<NATimeTableItem> program = pastPrograms.reduce((first, second) -> second);
|
||||||
if (program.isPresent()) {
|
if (program.isPresent()) {
|
||||||
|
@ -231,12 +232,13 @@ public class NATherm1Handler extends NetatmoModuleHandler<NAThermostat> {
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
for (NAThermProgram thermProgram : thermProgramList) {
|
for (NAThermProgram thermProgram : thermProgramList) {
|
||||||
if (thermProgram.getSelected() != null && thermProgram.getSelected()) {
|
if (thermProgram.isSelected() != null && thermProgram.isSelected()) {
|
||||||
// By default we'll use the first slot of next week - this case will be true if
|
// By default we'll use the first slot of next week - this case will be true if
|
||||||
// we are in the last schedule of the week so below loop will not exit by break
|
// we are in the last schedule of the week so below loop will not exit by break
|
||||||
int next = thermProgram.getTimetable().get(0).getMOffset() + (7 * 24 * 60);
|
List<NATimeTableItem> timetable = thermProgram.getTimetable();
|
||||||
|
int next = timetable.get(0).getMOffset() + (7 * 24 * 60);
|
||||||
|
|
||||||
for (NATimeTableItem timeTable : thermProgram.getTimetable()) {
|
for (NATimeTableItem timeTable : timetable) {
|
||||||
if (timeTable.getMOffset() > diff) {
|
if (timeTable.getMOffset() > diff) {
|
||||||
next = timeTable.getMOffset();
|
next = timeTable.getMOffset();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.welcome;
|
package org.openhab.binding.netatmo.internal.welcome;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
|
@ -68,29 +69,30 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler<NAWelcomeHome> {
|
||||||
@Override
|
@Override
|
||||||
protected Optional<NAWelcomeHome> updateReadings() {
|
protected Optional<NAWelcomeHome> updateReadings() {
|
||||||
Optional<NAWelcomeHome> result = getBridgeHandler().flatMap(handler -> handler.getWelcomeDataBody(getId()))
|
Optional<NAWelcomeHome> result = getBridgeHandler().flatMap(handler -> handler.getWelcomeDataBody(getId()))
|
||||||
.map(dataBody -> dataBody.getHomes().stream().filter(device -> device.getId().equalsIgnoreCase(getId()))
|
.map(dataBody -> nonNullStream(dataBody.getHomes())
|
||||||
.findFirst().orElse(null));
|
.filter(device -> device.getId().equalsIgnoreCase(getId())).findFirst().orElse(null));
|
||||||
// data time stamp is updated to now as WelcomeDataBody does not provide any information according to this need
|
// data time stamp is updated to now as WelcomeDataBody does not provide any information according to this need
|
||||||
dataTimeStamp = (int) (Calendar.getInstance().getTimeInMillis() / 1000);
|
dataTimeStamp = (int) (Calendar.getInstance().getTimeInMillis() / 1000);
|
||||||
result.ifPresent(home -> {
|
result.ifPresent(home -> {
|
||||||
home.getCameras().forEach(camera -> childs.put(camera.getId(), camera));
|
nonNullList(home.getCameras()).forEach(camera -> childs.put(camera.getId(), camera));
|
||||||
|
|
||||||
// Check how many persons are at home
|
// Check how many persons are at home
|
||||||
iPersons = 0;
|
iPersons = 0;
|
||||||
iUnknowns = 0;
|
iUnknowns = 0;
|
||||||
|
|
||||||
logger.debug("welcome home '{}' calculate Persons at home count", getId());
|
logger.debug("welcome home '{}' calculate Persons at home count", getId());
|
||||||
home.getPersons().forEach(person -> {
|
nonNullList(home.getPersons()).forEach(person -> {
|
||||||
iPersons += person.getOutOfSight() ? 0 : 1;
|
iPersons += person.isOutOfSight() ? 0 : 1;
|
||||||
if (person.getPseudo() != null) {
|
if (person.getPseudo() != null) {
|
||||||
childs.put(person.getId(), person);
|
childs.put(person.getId(), person);
|
||||||
} else {
|
} else {
|
||||||
iUnknowns += person.getOutOfSight() ? 0 : 1;
|
iUnknowns += person.isOutOfSight() ? 0 : 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
NAWelcomeEvent previousLastEvent = lastEvent;
|
NAWelcomeEvent previousLastEvent = lastEvent;
|
||||||
lastEvent = home.getEvents().stream().max(Comparator.comparingInt(NAWelcomeEvent::getTime)).orElse(null);
|
lastEvent = nonNullStream(home.getEvents()).max(Comparator.comparingInt(NAWelcomeEvent::getTime))
|
||||||
|
.orElse(null);
|
||||||
isNewLastEvent = previousLastEvent != null && !previousLastEvent.equals(lastEvent);
|
isNewLastEvent = previousLastEvent != null && !previousLastEvent.equals(lastEvent);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
@ -150,7 +152,7 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler<NAWelcomeHome> {
|
||||||
return lastEvt.map(e -> e.getVideoId() != null ? toStringType(e.getVideoStatus()) : UnDefType.UNDEF)
|
return lastEvt.map(e -> e.getVideoId() != null ? toStringType(e.getVideoStatus()) : UnDefType.UNDEF)
|
||||||
.orElse(UnDefType.UNDEF);
|
.orElse(UnDefType.UNDEF);
|
||||||
case CHANNEL_WELCOME_EVENT_ISARRIVAL:
|
case CHANNEL_WELCOME_EVENT_ISARRIVAL:
|
||||||
return lastEvt.map(e -> toOnOffType(e.getIsArrival())).orElse(UnDefType.UNDEF);
|
return lastEvt.map(e -> toOnOffType(e.isIsArrival())).orElse(UnDefType.UNDEF);
|
||||||
case CHANNEL_WELCOME_EVENT_MESSAGE:
|
case CHANNEL_WELCOME_EVENT_MESSAGE:
|
||||||
return findEventMessage().map(m -> (State) new StringType(m.replace("<b>", "").replace("</b>", "")))
|
return findEventMessage().map(m -> (State) new StringType(m.replace("<b>", "").replace("</b>", "")))
|
||||||
.orElse(UnDefType.UNDEF);
|
.orElse(UnDefType.UNDEF);
|
||||||
|
@ -192,7 +194,7 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler<NAWelcomeHome> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event.getEventList().forEach(subEvent -> {
|
nonNullList(event.getEventList()).forEach(subEvent -> {
|
||||||
String detectedObjectType = subEvent.getType().name();
|
String detectedObjectType = subEvent.getType().name();
|
||||||
detectedObjectTypes.add(detectedObjectType);
|
detectedObjectTypes.add(detectedObjectType);
|
||||||
});
|
});
|
||||||
|
@ -258,7 +260,7 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler<NAWelcomeHome> {
|
||||||
|
|
||||||
private Optional<NAWelcomeSubEvent> findFirstSubEvent(NAWelcomeEvent event) {
|
private Optional<NAWelcomeSubEvent> findFirstSubEvent(NAWelcomeEvent event) {
|
||||||
return Optional.ofNullable(event).map(NAWelcomeEvent::getEventList)
|
return Optional.ofNullable(event).map(NAWelcomeEvent::getEventList)
|
||||||
.flatMap(subEvents -> subEvents.stream().findFirst());
|
.flatMap(subEvents -> nonNullStream(subEvents).findFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<NAWelcomeEvent> getLastEvent() {
|
private Optional<NAWelcomeEvent> getLastEvent() {
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.netatmo.internal.welcome;
|
package org.openhab.binding.netatmo.internal.welcome;
|
||||||
|
|
||||||
|
import static org.openhab.binding.netatmo.internal.APIUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
|
||||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
@ -58,8 +58,7 @@ public class NAWelcomePersonHandler extends NetatmoModuleHandler<NAWelcomePerson
|
||||||
NAWelcomeEventResponse eventResponse = api.getlasteventof(getParentId(), getId(), 10);
|
NAWelcomeEventResponse eventResponse = api.getlasteventof(getParentId(), getId(), 10);
|
||||||
|
|
||||||
// Search the last event for this person
|
// Search the last event for this person
|
||||||
List<NAWelcomeEvent> rawEventList = eventResponse.getBody().getEventsList();
|
nonNullList(eventResponse.getBody().getEventsList()).forEach(event -> {
|
||||||
rawEventList.forEach(event -> {
|
|
||||||
if (event.getPersonId() != null && event.getPersonId().equalsIgnoreCase(getId())
|
if (event.getPersonId() != null && event.getPersonId().equalsIgnoreCase(getId())
|
||||||
&& (lastEvent == null || lastEvent.getTime() < event.getTime())) {
|
&& (lastEvent == null || lastEvent.getTime() < event.getTime())) {
|
||||||
lastEvent = event;
|
lastEvent = event;
|
||||||
|
@ -81,8 +80,7 @@ public class NAWelcomePersonHandler extends NetatmoModuleHandler<NAWelcomePerson
|
||||||
return getModule().map(m -> toDateTimeType(m.getLastSeen(), timeZoneProvider.getTimeZone()))
|
return getModule().map(m -> toDateTimeType(m.getLastSeen(), timeZoneProvider.getTimeZone()))
|
||||||
.orElse(UnDefType.UNDEF);
|
.orElse(UnDefType.UNDEF);
|
||||||
case CHANNEL_WELCOME_PERSON_ATHOME:
|
case CHANNEL_WELCOME_PERSON_ATHOME:
|
||||||
return getModule()
|
return getModule().map(m -> m.isOutOfSight() != null ? toOnOffType(!m.isOutOfSight()) : UnDefType.UNDEF)
|
||||||
.map(m -> m.getOutOfSight() != null ? toOnOffType(!m.getOutOfSight()) : UnDefType.UNDEF)
|
|
||||||
.orElse(UnDefType.UNDEF);
|
.orElse(UnDefType.UNDEF);
|
||||||
case CHANNEL_WELCOME_PERSON_AVATAR_URL:
|
case CHANNEL_WELCOME_PERSON_AVATAR_URL:
|
||||||
return toStringType(getAvatarURL());
|
return toStringType(getAvatarURL());
|
||||||
|
|
|
@ -191,6 +191,7 @@
|
||||||
<module>org.openhab.binding.neeo</module>
|
<module>org.openhab.binding.neeo</module>
|
||||||
<module>org.openhab.binding.neohub</module>
|
<module>org.openhab.binding.neohub</module>
|
||||||
<module>org.openhab.binding.nest</module>
|
<module>org.openhab.binding.nest</module>
|
||||||
|
<module>org.openhab.binding.netatmo</module>
|
||||||
<module>org.openhab.binding.network</module>
|
<module>org.openhab.binding.network</module>
|
||||||
<module>org.openhab.binding.networkupstools</module>
|
<module>org.openhab.binding.networkupstools</module>
|
||||||
<module>org.openhab.binding.nibeheatpump</module>
|
<module>org.openhab.binding.nibeheatpump</module>
|
||||||
|
|
Loading…
Reference in New Issue