diff --git a/bundles/org.openhab.binding.netatmo/NOTICE b/bundles/org.openhab.binding.netatmo/NOTICE index 41d3f500d04..33e1210cf57 100644 --- a/bundles/org.openhab.binding.netatmo/NOTICE +++ b/bundles/org.openhab.binding.netatmo/NOTICE @@ -19,6 +19,11 @@ commons-codec * Project; 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 * License: JSON License * Project: https://www.json.org @@ -43,8 +48,3 @@ netatmo-swagger-decl * License: MIT License * Project: https://dev.netatmo.com * 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 diff --git a/bundles/org.openhab.binding.netatmo/pom.xml b/bundles/org.openhab.binding.netatmo/pom.xml index 63bfd013c8c..62686d0ac6e 100644 --- a/bundles/org.openhab.binding.netatmo/pom.xml +++ b/bundles/org.openhab.binding.netatmo/pom.xml @@ -15,7 +15,7 @@ openHAB Add-ons :: Bundles :: Netatmo Binding - 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 + !android.*,!com.android.org.*,!org.apache.harmony.*,!sun.*,!org.apache.oltu.* @@ -26,21 +26,39 @@ compile - org.openhab.osgiify - com.squareup.okhttp.okhttp - 2.3.0 + com.squareup.okhttp + okhttp + 2.7.5 + compile + + + com.google.android + * + + + + + com.squareup.okhttp + logging-interceptor + 2.7.5 + compile + + + com.google.android + * + + + + + com.squareup.okio + okio + 1.6.0 compile - org.openhab.osgiify - com.squareup.okio.okio-1.3.0 - 1.3.0 - compile - - - org.openhab.osgiify - com.squareup.retrofit.retrofit - 1.9.0 + io.gsonfire + gson-fire + 1.8.4 compile @@ -55,14 +73,20 @@ 1.0.0 compile + + commons-codec + commons-codec + 1.8 + compile + - io.swagger + io.swagger.codegen.v3 swagger-codegen-maven-plugin - 2.1.6 + 3.0.21 @@ -71,9 +95,13 @@ https://raw.githubusercontent.com/cbornet/netatmo-swagger-decl/35e27745fb0d432bc6c8b5ec7a83ed2a09944cea/spec/swagger.yaml java - retrofit + false + false src/main/java + true + java8-localdatetime + true diff --git a/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml.bak.xml b/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml similarity index 57% rename from bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml.bak.xml rename to bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml index fb52bfe4e9a..21b41c9cde3 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml.bak.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml @@ -5,11 +5,6 @@ openhab-runtime-base mvn:org.openhab.osgiify/org.json.json/20131018 - mvn:org.openhab.osgiify/com.squareup.okhttp.okhttp/2.3.0 - mvn:org.openhab.osgiify/com.squareup.okio.okio-1.3.0/1.3.0 - mvn:org.openhab.osgiify/com.squareup.retrofit.retrofit/1.9.0 - mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.client/1.0.0 - mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.common/1.0.0 mvn:org.openhab.addons.bundles/org.openhab.binding.netatmo/${project.version} diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/APIUtils.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/APIUtils.java new file mode 100644 index 00000000000..378adcc98af --- /dev/null +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/APIUtils.java @@ -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 Stream nonNullStream(Collection collection) { + return Optional.ofNullable(collection).stream().flatMap(Collection::stream); + } + + public static List nonNullList(List list) { + return Optional.ofNullable(list).orElse(Collections.emptyList()); + } +} diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/camera/CameraHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/camera/CameraHandler.java index 46230c7d809..ecc0ac32de8 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/camera/CameraHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/camera/CameraHandler.java @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; import org.openhab.binding.netatmo.internal.ChannelTypeUtils; @@ -53,10 +52,11 @@ public abstract class CameraHandler extends NetatmoModuleHandler cameraAddress; protected CameraHandler(Thing thing, final TimeZoneProvider timeZoneProvider) { super(thing, timeZoneProvider); + cameraAddress = Optional.empty(); } @Override @@ -114,7 +114,7 @@ public abstract class CameraHandler extends NetatmoModuleHandler toOnOffType(m.getIsLocal())).orElse(UnDefType.UNDEF); + return getModule().map(m -> toOnOffType(m.isIsLocal())).orElse(UnDefType.UNDEF); } protected State getLivePictureURLState() { @@ -181,7 +181,7 @@ public abstract class CameraHandler extends NetatmoModuleHandler getLocalCameraURL() { Optional vpnURLOptional = getVpnUrl(); - CameraAddress address = cameraAddress; + Optional address = cameraAddress; if (vpnURLOptional.isPresent()) { final String vpnURL = vpnURLOptional.get(); // The local address is (re-)requested when it wasn't already determined or when the vpn address was // changed. - if (address == null || address.isVpnURLChanged(vpnURL)) { + if (!address.isPresent() || address.get().isVpnURLChanged(vpnURL)) { Optional json = executeGETRequestJSON(vpnURL + PING_URL_PATH); 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; } } - return Optional.ofNullable(address).map(CameraAddress::getLocalURL); + return address.map(CameraAddress::getLocalURL); } private Optional executeGETRequestJSON(String url) { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java index a8224d79451..ee23eeddead 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java @@ -12,9 +12,11 @@ */ package org.openhab.binding.netatmo.internal.discovery; +import static org.openhab.binding.netatmo.internal.APIUtils.*; import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -71,28 +73,28 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl public void startScan() { if (netatmoBridgeHandler.configuration.readStation) { netatmoBridgeHandler.getStationsDataBody(null).ifPresent(dataBody -> { - dataBody.getDevices().forEach(station -> { + nonNullList(dataBody.getDevices()).forEach(station -> { discoverWeatherStation(station); }); }); } if (netatmoBridgeHandler.configuration.readHealthyHomeCoach) { netatmoBridgeHandler.getHomecoachDataBody(null).ifPresent(dataBody -> { - dataBody.getDevices().forEach(homecoach -> { + nonNullList(dataBody.getDevices()).forEach(homecoach -> { discoverHomeCoach(homecoach); }); }); } if (netatmoBridgeHandler.configuration.readThermostat) { netatmoBridgeHandler.getThermostatsDataBody(null).ifPresent(dataBody -> { - dataBody.getDevices().forEach(plug -> { + nonNullList(dataBody.getDevices()).forEach(plug -> { discoverThermostat(plug); }); }); } if (netatmoBridgeHandler.configuration.readWelcome || netatmoBridgeHandler.configuration.readPresence) { netatmoBridgeHandler.getWelcomeDataBody(null).ifPresent(dataBody -> { - dataBody.getHomes().forEach(home -> { + nonNullList(dataBody.getHomes()).forEach(home -> { discoverWelcomeHome(home); }); }); @@ -123,7 +125,7 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl private void discoverThermostat(NAPlug plug) { 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(), thermostat.getFirmware()); }); @@ -135,11 +137,11 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl } 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); 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(), createWeatherModuleName(station, module, isFavorite), module.getFirmware()); }); @@ -148,15 +150,16 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl private void discoverWelcomeHome(NAWelcomeHome home) { // I observed that Thermostat homes are also reported here by Netatmo API // So I ignore homes that have an empty list of cameras - if (!home.getCameras().isEmpty()) { + List cameras = nonNullList(home.getCameras()); + if (!cameras.isEmpty()) { onDeviceAddedInternal(home.getId(), null, WELCOME_HOME_THING_TYPE.getId(), home.getName(), null); // Discover Cameras - home.getCameras().forEach(camera -> { + cameras.forEach(camera -> { onDeviceAddedInternal(camera.getId(), home.getId(), camera.getType(), camera.getName(), null); }); // 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(), person.getPseudo(), null); }); diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/MeasurableChannels.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/MeasurableChannels.java index eead1771168..1df657b7954 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/MeasurableChannels.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/MeasurableChannels.java @@ -12,6 +12,7 @@ */ 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 java.util.ArrayList; @@ -24,7 +25,7 @@ import org.openhab.binding.netatmo.internal.ChannelTypeUtils; import org.openhab.core.thing.ChannelUID; import org.openhab.core.types.State; -import io.swagger.client.CollectionFormats.CSVParams; +import io.swagger.client.model.NAMeasureBodyElem; import io.swagger.client.model.NAMeasureResponse; /** @@ -64,10 +65,11 @@ public class MeasurableChannels { int index = measuredChannels.indexOf(channelId); NAMeasureResponse theMeasures = measures; if (index != -1 && theMeasures != null) { - if (!theMeasures.getBody().isEmpty()) { - List> valueList = theMeasures.getBody().get(0).getValue(); + List body = nonNullList(theMeasures.getBody()); + if (!body.isEmpty()) { + List> valueList = nonNullList(body.get(0).getValue()); if (!valueList.isEmpty()) { - List values = valueList.get(0); + List values = nonNullList(valueList.get(0)); if (values.size() >= index) { Float value = values.get(index); return Optional.of(ChannelTypeUtils.toDecimalType(value)); @@ -78,9 +80,9 @@ public class MeasurableChannels { return Optional.empty(); } - public Optional getAsCsv() { + public Optional> getMeasuredChannels() { if (!measuredChannels.isEmpty()) { - return Optional.of(new CSVParams(measuredChannels)); + return Optional.of(measuredChannels); } return Optional.empty(); } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java index 23043ba77e3..1cdfc31efe0 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java @@ -14,11 +14,13 @@ package org.openhab.binding.netatmo.internal.handler; import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; @@ -26,7 +28,13 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; 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.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.Nullable; 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.LoggerFactory; -import com.squareup.okhttp.OkHttpClient; - 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.PartnerApi; import io.swagger.client.api.StationApi; import io.swagger.client.api.ThermostatApi; import io.swagger.client.api.WelcomeApi; +import io.swagger.client.auth.Authentication; import io.swagger.client.auth.OAuth; -import io.swagger.client.auth.OAuthFlow; import io.swagger.client.model.NAHealthyHomeCoachDataBody; import io.swagger.client.model.NAMeasureBodyElem; import io.swagger.client.model.NAStationDataBody; import io.swagger.client.model.NAThermostatDataBody; 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 @@ -79,25 +82,34 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler { public NetatmoBridgeConfiguration configuration = new NetatmoBridgeConfiguration(); private @Nullable ScheduledFuture refreshJob; - private @Nullable APIMap apiMap; + private @Nullable APICreator apiCreator; private @Nullable WelcomeWebHookServlet webHookServlet; private List dataListeners = new CopyOnWriteArrayList<>(); - private class APIMap extends HashMap, Object> { - private static final long serialVersionUID = -2024031764691952343L; - private ApiClient apiClient; + private static class APICreator { - public APIMap(ApiClient apiClient) { + private final ApiClient apiClient; + private final Map, Object> apiMap; + + private APICreator(ApiClient apiClient) { super(); this.apiClient = apiClient; + apiMap = new HashMap<>(); } - public Object get(Class apiClass) { - if (!super.containsKey(apiClass)) { - Object api = apiClient.createService(apiClass); - super.put(apiClass, api); + @SuppressWarnings("unchecked") + public T getAPI(Class apiClass) { + T api = (T) apiMap.get(apiClass); + 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); + } + apiMap.put(apiClass, api); } - return super.get(apiClass); + return api; } } @@ -136,37 +148,29 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler { // I use a connection to Netatmo API using PartnerAPI to ensure that API is reachable getPartnerApi().partnerdevices(); connectionSucceed(); - } catch (RetrofitError e) { - if (e.getKind() == Kind.NETWORK) { - 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 - // error - // but it means connection to API is OK - connectionSucceed(); - break; - case 403: // Forbidden Access maybe too many requests ? Let's wait next cycle - logger.warn("Error 403 while connecting to Netatmo API, will retry in {} s", - configuration.reconnectInterval); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Netatmo Access Forbidden, will retry in " + configuration.reconnectInterval - + " seconds."); - break; - default: - if (logger.isDebugEnabled()) { - // we also attach the stack trace - logger.error("Unable to connect Netatmo API : {}", e.getMessage(), e); - } else { - logger.error("Unable to connect Netatmo API : {}", e.getMessage()); - } - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Unable to connect Netatmo API : " + e.getLocalizedMessage()); - return; - } + } catch (ApiException e) { + switch (e.getCode()) { + case 404: // If no partner station has been associated - likely to happen - we'll have this + // error + // but it means connection to API is OK + connectionSucceed(); + break; + case 403: // Forbidden Access maybe too many requests ? Let's wait next cycle + logger.warn("Error 403 while connecting to Netatmo API, will retry in {} s", + configuration.reconnectInterval); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Netatmo Access Forbidden, will retry in " + configuration.reconnectInterval + + " seconds."); + break; + default: + if (logger.isDebugEnabled()) { + // we also attach the stack trace + logger.error("Unable to connect Netatmo API : {}", e.getMessage(), e); + } else { + logger.error("Unable to connect Netatmo API : {}", e.getMessage()); + } + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Unable to connect Netatmo API : " + e.getLocalizedMessage()); } } catch (RuntimeException 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); } - private void initializeApiClient() throws RetrofitError { - ApiClient apiClient = new ApiClient(); + private void initializeApiClient() { + try { + ApiClient apiClient = new ApiClient(); - OAuth auth = new OAuth(new OkHttpClient(), - OAuthClientRequest.tokenLocation("https://api.netatmo.net/oauth2/token")); - auth.setFlow(OAuthFlow.password); - auth.setAuthenticationRequestBuilder(OAuthClientRequest.authorizationLocation("")); + OAuthClientRequest oAuthRequest = OAuthClientRequest.tokenLocation("https://api.netatmo.net/oauth2/token") + .setClientId(configuration.clientId).setClientSecret(configuration.clientSecret) + .setUsername(configuration.username).setPassword(configuration.password).setScope(getApiScope()) + .setGrantType(GrantType.PASSWORD).buildBodyMessage(); - apiClient.getApiAuthorizations().put("password_oauth", auth); - apiClient.getTokenEndPoint().setClientId(configuration.clientId).setClientSecret(configuration.clientSecret) - .setUsername(configuration.username).setPassword(configuration.password).setScope(getApiScope()); + OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient()); - apiClient.configureFromOkclient(new OkHttpClient()); - apiClient.getAdapterBuilder().setLogLevel(logger.isDebugEnabled() ? LogLevel.FULL : LogLevel.NONE); + OAuthJSONAccessTokenResponse accessTokenResponse = oAuthClient.accessToken(oAuthRequest, + 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() { @@ -231,28 +244,23 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler { } public @Nullable PartnerApi getPartnerApi() { - APIMap map = apiMap; - return map != null ? (PartnerApi) map.get(PartnerApi.class) : null; + return apiCreator != null ? apiCreator.getAPI(PartnerApi.class) : null; } public Optional getStationApi() { - APIMap map = apiMap; - return map != null ? Optional.of((StationApi) map.get(StationApi.class)) : Optional.empty(); + return apiCreator != null ? Optional.of(apiCreator.getAPI(StationApi.class)) : Optional.empty(); } public Optional getHomeCoachApi() { - APIMap map = apiMap; - return map != null ? Optional.of((HealthyhomecoachApi) map.get(HealthyhomecoachApi.class)) : Optional.empty(); + return apiCreator != null ? Optional.of(apiCreator.getAPI(HealthyhomecoachApi.class)) : Optional.empty(); } public Optional getThermostatApi() { - APIMap map = apiMap; - return map != null ? Optional.of((ThermostatApi) map.get(ThermostatApi.class)) : Optional.empty(); + return apiCreator != null ? Optional.of(apiCreator.getAPI(ThermostatApi.class)) : Optional.empty(); } public Optional getWelcomeApi() { - APIMap map = apiMap; - return map != null ? Optional.of((WelcomeApi) map.get(WelcomeApi.class)) : Optional.empty(); + return apiCreator != null ? Optional.of(apiCreator.getAPI(WelcomeApi.class)) : Optional.empty(); } @Override @@ -283,8 +291,8 @@ public class NetatmoBridgeHandler extends BaseBridgeHandler { public List getStationMeasureResponses(String equipmentId, @Nullable String moduleId, String scale, List types) { - List data = getStationApi().map(api -> api - .getmeasure(equipmentId, scale, new CSVParams(types), moduleId, null, "last", 1, true, false).getBody()) + List data = getStationApi() + .map(api -> api.getmeasure(equipmentId, scale, types, moduleId, null, "last", 1, true, false).getBody()) .orElse(null); updateStatus(ThingStatus.ONLINE); NAMeasureBodyElem element = (data != null && data.size() > 0) ? data.get(0) : null; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java index b68c43126a2..1d18b47bb19 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java @@ -39,8 +39,8 @@ import org.openhab.core.types.UnDefType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.swagger.client.ApiException; import io.swagger.client.model.NAPlace; -import retrofit.RetrofitError; /** * {@link NetatmoDeviceHandler} is the handler for a given @@ -125,7 +125,7 @@ public abstract class NetatmoDeviceHandler extends AbstractNetatmoThingH Optional newDeviceReading = Optional.empty(); try { newDeviceReading = updateReadings(); - } catch (RetrofitError e) { + } catch (ApiException e) { if (logger.isDebugEnabled()) { // we also attach the stack trace logger.error("Unable to connect Netatmo API : {}", e.getMessage(), e); diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java index aa9b5fc2327..f0cd32bb124 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java @@ -12,6 +12,7 @@ */ 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.NetatmoBindingConstants.*; @@ -43,7 +44,7 @@ public class NAHealthyHomeCoachHandler extends NetatmoDeviceHandler updateReadings() { 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)); } @@ -58,7 +59,7 @@ public class NAHealthyHomeCoachHandler extends NetatmoDeviceHandler { @Override protected Optional updateReadings() { Optional 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)); result.ifPresent(device -> { - device.getModules().forEach(child -> childs.put(child.getId(), child)); + nonNullList(device.getModules()).forEach(child -> childs.put(child.getId(), child)); }); updateMeasurements(); @@ -166,7 +167,7 @@ public class NAMainHandler extends NetatmoDeviceHandler { if (dashboardData != null) { switch (channelId) { case CHANNEL_CO2: - return toQuantityType(dashboardData.getCO2(), API_CO2_UNIT); + return toQuantityType(dashboardData.getCo2(), API_CO2_UNIT); case CHANNEL_TEMPERATURE: return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT); case CHANNEL_MIN_TEMP: @@ -288,7 +289,7 @@ public class NAMainHandler extends NetatmoDeviceHandler { boolean result = false; Optional device = getDevice(); if (device.isPresent()) { - Boolean reachable = device.get().getReachable(); + Boolean reachable = device.get().isReachable(); result = reachable != null ? reachable.booleanValue() : false; } return result; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule1Handler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule1Handler.java index af10763195c..dc65566858e 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule1Handler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule1Handler.java @@ -177,7 +177,7 @@ public class NAModule1Handler extends NetatmoModuleHandler { boolean result = false; Optional module = getModule(); if (module.isPresent()) { - Boolean reachable = module.get().getReachable(); + Boolean reachable = module.get().isReachable(); result = reachable != null ? reachable.booleanValue() : false; } return result; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule2Handler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule2Handler.java index 6071c01b6c0..43acf2563fb 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule2Handler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule2Handler.java @@ -73,7 +73,7 @@ public class NAModule2Handler extends NetatmoModuleHandler { boolean result = false; Optional module = getModule(); if (module.isPresent()) { - Boolean reachable = module.get().getReachable(); + Boolean reachable = module.get().isReachable(); result = reachable != null ? reachable.booleanValue() : false; } return result; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule3Handler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule3Handler.java index 06ca88cde27..ddce844e979 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule3Handler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule3Handler.java @@ -96,7 +96,7 @@ public class NAModule3Handler extends NetatmoModuleHandler { boolean result = false; Optional module = getModule(); if (module.isPresent()) { - Boolean reachable = module.get().getReachable(); + Boolean reachable = module.get().isReachable(); result = reachable != null ? reachable.booleanValue() : false; } return result; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule4Handler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule4Handler.java index 7d20bcc7712..a9bdeb2ac7b 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule4Handler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/station/NAModule4Handler.java @@ -123,7 +123,7 @@ public class NAModule4Handler extends NetatmoModuleHandler { case CHANNEL_TEMP_TREND: return toStringType(dashboardData.getTempTrend()); case CHANNEL_CO2: - return toQuantityType(dashboardData.getCO2(), API_CO2_UNIT); + return toQuantityType(dashboardData.getCo2(), API_CO2_UNIT); case CHANNEL_TEMPERATURE: return toQuantityType(dashboardData.getTemperature(), API_TEMPERATURE_UNIT); case CHANNEL_DATE_MIN_TEMP: @@ -204,7 +204,7 @@ public class NAModule4Handler extends NetatmoModuleHandler { boolean result = false; Optional module = getModule(); if (module.isPresent()) { - Boolean reachable = module.get().getReachable(); + Boolean reachable = module.get().isReachable(); result = reachable != null ? reachable.booleanValue() : false; } return result; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java index 757f02b1045..4c4e4514e3e 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java @@ -12,6 +12,7 @@ */ 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.NetatmoBindingConstants.*; @@ -47,10 +48,10 @@ public class NAPlugHandler extends NetatmoDeviceHandler { @Override protected Optional updateReadings() { Optional 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)); result.ifPresent(device -> { - device.getModules().forEach(child -> childs.put(child.getId(), child)); + nonNullList(device.getModules()).forEach(child -> childs.put(child.getId(), child)); }); return result; } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java index 9399a135b51..2f8c91c7acc 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java @@ -12,6 +12,7 @@ */ 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.NetatmoBindingConstants.*; @@ -80,7 +81,7 @@ public class NATherm1Handler extends NetatmoModuleHandler { @Override public void updateChannels(Object moduleObject) { if (isRefreshRequired()) { - measurableChannels.getAsCsv().ifPresent(csvParams -> { + measurableChannels.getMeasuredChannels().ifPresent(csvParams -> { getApi().ifPresent(api -> { NAMeasureResponse measures = api.getmeasure(getParentId(), "max", csvParams, getId(), null, null, 1, true, true); @@ -96,7 +97,7 @@ public class NATherm1Handler extends NetatmoModuleHandler { private void updateStateDescription(NAThermostat thermostat) { List options = new ArrayList<>(); - for (NAThermProgram planning : thermostat.getThermProgramList()) { + for (NAThermProgram planning : nonNullList(thermostat.getThermProgramList())) { options.add(new StateOption(planning.getProgramId(), planning.getName())); } stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_PLANNING), options); @@ -125,7 +126,7 @@ public class NATherm1Handler extends NetatmoModuleHandler { if (setpoint != null) { Integer endTime = setpoint.getSetpointEndtime(); if (endTime == null) { - endTime = getNextProgramTime(thermostat.get().getThermProgramList()); + endTime = getNextProgramTime(nonNullList(thermostat.get().getThermProgramList())); } return toDateTimeType(endTime, timeZoneProvider.getTimeZone()); } @@ -138,8 +139,8 @@ public class NATherm1Handler extends NetatmoModuleHandler { case CHANNEL_PLANNING: { String currentPlanning = "-"; if (thermostat.isPresent()) { - for (NAThermProgram program : thermostat.get().getThermProgramList()) { - if (program.getSelected() == Boolean.TRUE) { + for (NAThermProgram program : nonNullList(thermostat.get().getThermProgramList())) { + if (program.isSelected() == Boolean.TRUE) { currentPlanning = program.getProgramId(); } } @@ -164,8 +165,8 @@ public class NATherm1Handler extends NetatmoModuleHandler { if (setPoint != null) { String currentMode = setPoint.getSetpointMode(); - NAThermProgram currentProgram = thermostat.get().getThermProgramList().stream() - .filter(p -> p.getSelected() != null && p.getSelected()).findFirst().get(); + NAThermProgram currentProgram = nonNullStream(thermostat.get().getThermProgramList()) + .filter(p -> p.isSelected() != null && p.isSelected()).findFirst().get(); switch (currentMode) { case CHANNEL_SETPOINT_MODE_MANUAL: return toDecimalType(setPoint.getSetpointTemp()); @@ -177,7 +178,7 @@ public class NATherm1Handler extends NetatmoModuleHandler { return toDecimalType(zone1.getTemp()); case CHANNEL_SETPOINT_MODE_PROGRAM: NATimeTableItem currentProgramMode = getCurrentProgramMode( - thermostat.get().getThermProgramList()); + nonNullList(thermostat.get().getThermProgramList())); if (currentProgramMode != null) { NAZone zone2 = getZone(currentProgram.getZones(), currentProgramMode.getId()); return toDecimalType(zone2.getTemp()); @@ -192,7 +193,7 @@ public class NATherm1Handler extends NetatmoModuleHandler { } private NAZone getZone(List 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() { @@ -210,10 +211,10 @@ public class NATherm1Handler extends NetatmoModuleHandler { long diff = (now.getTimeInMillis() - getNetatmoProgramBaseTime()) / 1000 / 60; Optional currentProgram = thermProgramList.stream() - .filter(p -> p.getSelected() != null && p.getSelected()).findFirst(); + .filter(p -> p.isSelected() != null && p.isSelected()).findFirst(); if (currentProgram.isPresent()) { - Stream pastPrograms = currentProgram.get().getTimetable().stream() + Stream pastPrograms = nonNullStream(currentProgram.get().getTimetable()) .filter(t -> t.getMOffset() < diff); Optional program = pastPrograms.reduce((first, second) -> second); if (program.isPresent()) { @@ -231,12 +232,13 @@ public class NATherm1Handler extends NetatmoModuleHandler { int result = -1; 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 // 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 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) { next = timeTable.getMOffset(); break; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java index 9a269e75a54..7b3b926a5b0 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java @@ -12,6 +12,7 @@ */ 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.NetatmoBindingConstants.*; @@ -68,29 +69,30 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler { @Override protected Optional updateReadings() { Optional result = getBridgeHandler().flatMap(handler -> handler.getWelcomeDataBody(getId())) - .map(dataBody -> dataBody.getHomes().stream().filter(device -> device.getId().equalsIgnoreCase(getId())) - .findFirst().orElse(null)); + .map(dataBody -> nonNullStream(dataBody.getHomes()) + .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 dataTimeStamp = (int) (Calendar.getInstance().getTimeInMillis() / 1000); 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 iPersons = 0; iUnknowns = 0; logger.debug("welcome home '{}' calculate Persons at home count", getId()); - home.getPersons().forEach(person -> { - iPersons += person.getOutOfSight() ? 0 : 1; + nonNullList(home.getPersons()).forEach(person -> { + iPersons += person.isOutOfSight() ? 0 : 1; if (person.getPseudo() != null) { childs.put(person.getId(), person); } else { - iUnknowns += person.getOutOfSight() ? 0 : 1; + iUnknowns += person.isOutOfSight() ? 0 : 1; } }); 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); }); return result; @@ -150,7 +152,7 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler { return lastEvt.map(e -> e.getVideoId() != null ? toStringType(e.getVideoStatus()) : UnDefType.UNDEF) .orElse(UnDefType.UNDEF); 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: return findEventMessage().map(m -> (State) new StringType(m.replace("", "").replace("", ""))) .orElse(UnDefType.UNDEF); @@ -192,7 +194,7 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler { } } - event.getEventList().forEach(subEvent -> { + nonNullList(event.getEventList()).forEach(subEvent -> { String detectedObjectType = subEvent.getType().name(); detectedObjectTypes.add(detectedObjectType); }); @@ -258,7 +260,7 @@ public class NAWelcomeHomeHandler extends NetatmoDeviceHandler { private Optional findFirstSubEvent(NAWelcomeEvent event) { return Optional.ofNullable(event).map(NAWelcomeEvent::getEventList) - .flatMap(subEvents -> subEvents.stream().findFirst()); + .flatMap(subEvents -> nonNullStream(subEvents).findFirst()); } private Optional getLastEvent() { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java index fd2ba848848..3026a8752d0 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java @@ -12,10 +12,10 @@ */ 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.NetatmoBindingConstants.*; -import java.util.List; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -58,8 +58,7 @@ public class NAWelcomePersonHandler extends NetatmoModuleHandler rawEventList = eventResponse.getBody().getEventsList(); - rawEventList.forEach(event -> { + nonNullList(eventResponse.getBody().getEventsList()).forEach(event -> { if (event.getPersonId() != null && event.getPersonId().equalsIgnoreCase(getId()) && (lastEvent == null || lastEvent.getTime() < event.getTime())) { lastEvent = event; @@ -81,8 +80,7 @@ public class NAWelcomePersonHandler extends NetatmoModuleHandler toDateTimeType(m.getLastSeen(), timeZoneProvider.getTimeZone())) .orElse(UnDefType.UNDEF); case CHANNEL_WELCOME_PERSON_ATHOME: - return getModule() - .map(m -> m.getOutOfSight() != null ? toOnOffType(!m.getOutOfSight()) : UnDefType.UNDEF) + return getModule().map(m -> m.isOutOfSight() != null ? toOnOffType(!m.isOutOfSight()) : UnDefType.UNDEF) .orElse(UnDefType.UNDEF); case CHANNEL_WELCOME_PERSON_AVATAR_URL: return toStringType(getAvatarURL()); diff --git a/bundles/pom.xml b/bundles/pom.xml index 84131e525de..61f5045e813 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -191,6 +191,7 @@ org.openhab.binding.neeo org.openhab.binding.neohub org.openhab.binding.nest + org.openhab.binding.netatmo org.openhab.binding.network org.openhab.binding.networkupstools org.openhab.binding.nibeheatpump