Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[netatmo] Null annotations Part 3 of 3 #8057

Merged
merged 4 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions bundles/org.openhab.binding.netatmo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ See http://www.netatmo.com/ for details on their product.

## Binding Configuration

The binding has no configuration options itself, all configuration is done at 'Things' level but before, you will have to grant openHAB to access Netatmo API.
The binding has the following configuration options:

| Parameter | Name | Description |
|---------------------|----------------------|-----------------------------------|
| backgroundDiscovery | Background Discovery | If set to true, the device and its associated modules are updated in the discovery inbox at each API call run to refresh device data. Default is false. |

Before setting up your 'Things', you will have to grant openHAB to access Netatmo API.
Here is the procedure:

### 1. Application Creation
Expand Down Expand Up @@ -503,10 +509,9 @@ All these channels are read only.
### Welcome and Presence Camera

Warnings:
- The URL of the live snapshot is a fixed URL so the value of the channel cameraLivePictureUrl / welcomeCameraLivePictureUrl will never be updated once first set by the binding.
So to get a refreshed picture, you need to use the refresh parameter in your sitemap image element.
- Some features like the video surveillance are accessed via the local network, so it may be helpful to set a static IP address
for the camera within your local network.

- The URL of the live snapshot is a fixed URL so the value of the channel cameraLivePictureUrl / welcomeCameraLivePictureUrl will never be updated once first set by the binding. So to get a refreshed picture, you need to use the refresh parameter in your sitemap image element.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put each sentence on its own line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was done to avoid a warning in the checks (blank line required after a list item, something like that).
Either 2 lines to help maintenance but a warning, or one line and no warning.
Let me know what you prefer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just leave as is then. I've prefer to avoid the warning even if it might be misguided.

- Some features like the video surveillance are accessed via the local network, so it may be helpful to set a static IP address for the camera within your local network.

**Supported channels for the Welcome Camera thing:**

Expand All @@ -523,9 +528,8 @@ for the camera within your local network.
**Supported channels for the Presence Camera thing:**

Warnings:
- The floodlight auto-mode (cameraFloodlightAutoMode) isn't updated it is changed by another application. Therefore the
binding handles its own state of the auto-mode. This has the advantage that the user can define its own floodlight
switch off behaviour.

- The floodlight auto-mode (cameraFloodlightAutoMode) isn't updated it is changed by another application. Therefore the binding handles its own state of the auto-mode. This has the advantage that the user can define its own floodlight switch off behaviour.

| Channel ID | Item Type | Read/Write | Description |
|-----------------------------|-----------|------------|--------------------------------------------------------------|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;

import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
Expand Down Expand Up @@ -47,6 +48,7 @@
import org.openhab.binding.netatmo.internal.welcome.NAWelcomeHomeHandler;
import org.openhab.binding.netatmo.internal.welcome.NAWelcomePersonHandler;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
Expand All @@ -69,6 +71,7 @@ public class NetatmoHandlerFactory extends BaseThingHandlerFactory {
private final HttpService httpService;
private final NATherm1StateDescriptionProvider stateDescriptionProvider;
private final TimeZoneProvider timeZoneProvider;
private boolean backgroundDiscovery;

@Activate
public NetatmoHandlerFactory(final @Reference HttpService httpService,
Expand All @@ -79,6 +82,19 @@ public NetatmoHandlerFactory(final @Reference HttpService httpService,
this.timeZoneProvider = timeZoneProvider;
}

@Override
protected void activate(ComponentContext componentContext) {
super.activate(componentContext);
Dictionary<String, Object> properties = componentContext.getProperties();
Object property = properties.get("backgroundDiscovery");
if (property instanceof Boolean) {
backgroundDiscovery = ((Boolean) property).booleanValue();
} else {
backgroundDiscovery = false;
}
logger.debug("backgroundDiscovery {}", backgroundDiscovery);
}

@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID));
Expand Down Expand Up @@ -134,7 +150,10 @@ protected void removeHandler(ThingHandler thingHandler) {
private synchronized void registerDeviceDiscoveryService(NetatmoBridgeHandler netatmoBridgeHandler) {
if (bundleContext != null) {
NetatmoModuleDiscoveryService discoveryService = new NetatmoModuleDiscoveryService(netatmoBridgeHandler);
discoveryService.activate(null);
Map<String, @Nullable Object> configProperties = new HashMap<>();
configProperties.put(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY,
Boolean.valueOf(backgroundDiscovery));
discoveryService.activate(configProperties);
discoveryServiceRegs.put(netatmoBridgeHandler.getThing().getUID(), bundleContext
.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
*/
package org.openhab.binding.netatmo.internal.camera;

import java.util.Objects;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

import java.util.Objects;

/**
* {@link CameraAddress} handles the data to address a camera (VPN and local address).
*
* @author Sven Strohschein
* @author Sven Strohschein - Initial contribution
*/
@NonNullByDefault
public class CameraAddress {
Expand All @@ -43,6 +43,7 @@ public String getLocalURL() {

/**
* Checks if the VPN URL was changed / isn't equal to the given VPN-URL.
*
* @param vpnURL old / known VPN URL
* @return true, when the VPN URL isn't equal given VPN URL, otherwise false
*/
Expand All @@ -52,8 +53,12 @@ public boolean isVpnURLChanged(String vpnURL) {

@Override
public boolean equals(@Nullable Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
CameraAddress that = (CameraAddress) object;
return vpnURL.equals(that.vpnURL) && localURL.equals(that.localURL);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
*/
package org.openhab.binding.netatmo.internal.camera;

import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*;
import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.toOnOffType;
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;

import org.eclipse.jdt.annotation.NonNull;
import java.io.IOException;
import java.util.Optional;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.i18n.TimeZoneProvider;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.thing.ChannelUID;
Expand All @@ -29,19 +32,16 @@
import org.json.JSONObject;
import org.openhab.binding.netatmo.internal.ChannelTypeUtils;
import org.openhab.binding.netatmo.internal.handler.NetatmoModuleHandler;

import io.swagger.client.model.NAWelcomeCamera;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Optional;
import io.swagger.client.model.NAWelcomeCamera;

/**
* {@link CameraHandler} is the class used to handle Camera Data
*
* @author Sven Strohschein (partly moved code from NAWelcomeCameraHandler to introduce inheritance, see
* NAWelcomeCameraHandler)
* @author Sven Strohschein - Initial contribution (partly moved code from NAWelcomeCameraHandler to introduce
* inheritance, see NAWelcomeCameraHandler)
*
*/
@NonNullByDefault
Expand All @@ -53,7 +53,7 @@ public abstract class CameraHandler extends NetatmoModuleHandler<NAWelcomeCamera

private final Logger logger = LoggerFactory.getLogger(CameraHandler.class);

private Optional<CameraAddress> cameraAddress = Optional.empty();
private @Nullable CameraAddress cameraAddress;

protected CameraHandler(Thing thing, final TimeZoneProvider timeZoneProvider) {
super(thing, timeZoneProvider);
Expand All @@ -65,9 +65,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
switch (channelId) {
case CHANNEL_CAMERA_STATUS:
case CHANNEL_WELCOME_CAMERA_STATUS:
if(command == OnOffType.ON) {
if (command == OnOffType.ON) {
switchVideoSurveillance(true);
} else if(command == OnOffType.OFF) {
} else if (command == OnOffType.OFF) {
switchVideoSurveillance(false);
}
break;
Expand All @@ -81,7 +81,7 @@ protected void updateProperties(NAWelcomeCamera moduleData) {
}

@Override
protected State getNAThingProperty(@NonNull String channelId) {
protected State getNAThingProperty(String channelId) {
switch (channelId) {
case CHANNEL_CAMERA_STATUS:
return getStatusState();
Expand Down Expand Up @@ -188,7 +188,7 @@ private void switchVideoSurveillance(boolean isOn) {
Optional<String> localCameraURL = getLocalCameraURL();
if (localCameraURL.isPresent()) {
String url = localCameraURL.get() + STATUS_CHANGE_URL_PATH + "?status=";
if(isOn) {
if (isOn) {
url += "on";
} else {
url += "off";
Expand All @@ -201,17 +201,20 @@ private void switchVideoSurveillance(boolean isOn) {

protected Optional<String> getLocalCameraURL() {
Optional<String> vpnURLOptional = getVpnUrl();
CameraAddress 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 (!cameraAddress.isPresent() || cameraAddress.get().isVpnURLChanged(vpnURL)) {
// 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)) {
Optional<JSONObject> json = executeGETRequestJSON(vpnURL + PING_URL_PATH);
cameraAddress = json.map(j -> j.optString("local_url", null))
.map(localURL -> new CameraAddress(vpnURL, localURL));
address = json.map(j -> j.optString("local_url", null))
.map(localURL -> new CameraAddress(vpnURL, localURL)).orElse(null);
cameraAddress = address;
}
}
return cameraAddress.map(CameraAddress::getLocalURL);
return Optional.ofNullable(address).map(CameraAddress::getLocalURL);
}

private Optional<JSONObject> executeGETRequestJSON(String url) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,9 @@
import org.openhab.binding.netatmo.internal.handler.NetatmoDataListener;

import io.swagger.client.model.NAHealthyHomeCoach;
import io.swagger.client.model.NAHealthyHomeCoachDataBody;
import io.swagger.client.model.NAMain;
import io.swagger.client.model.NAPlug;
import io.swagger.client.model.NAStationDataBody;
import io.swagger.client.model.NAThermostatDataBody;
import io.swagger.client.model.NAWelcomeHome;
import io.swagger.client.model.NAWelcomeHomeData;

/**
* The {@link NetatmoModuleDiscoveryService} searches for available Netatmo
Expand Down Expand Up @@ -70,42 +66,41 @@ public void deactivate() {
@Override
public void startScan() {
if (netatmoBridgeHandler.configuration.readStation) {
NAStationDataBody stationDataBody = netatmoBridgeHandler.getStationsDataBody(null);
if (stationDataBody != null) {
stationDataBody.getDevices().forEach(station -> {
netatmoBridgeHandler.getStationsDataBody(null).ifPresent(dataBody -> {
dataBody.getDevices().forEach(station -> {
discoverWeatherStation(station);
});
}
});
}
if (netatmoBridgeHandler.configuration.readHealthyHomeCoach) {
NAHealthyHomeCoachDataBody homecoachDataBody = netatmoBridgeHandler.getHomecoachDataBody(null);
if (homecoachDataBody != null) {
homecoachDataBody.getDevices().forEach(homecoach -> {
netatmoBridgeHandler.getHomecoachDataBody(null).ifPresent(dataBody -> {
dataBody.getDevices().forEach(homecoach -> {
discoverHomeCoach(homecoach);
});
}
});
}
if (netatmoBridgeHandler.configuration.readThermostat) {
NAThermostatDataBody thermostatsDataBody = netatmoBridgeHandler.getThermostatsDataBody(null);
if (thermostatsDataBody != null) {
thermostatsDataBody.getDevices().forEach(plug -> {
netatmoBridgeHandler.getThermostatsDataBody(null).ifPresent(dataBody -> {
dataBody.getDevices().forEach(plug -> {
discoverThermostat(plug);
});
}
});
}
if (netatmoBridgeHandler.configuration.readWelcome || netatmoBridgeHandler.configuration.readPresence) {
NAWelcomeHomeData welcomeHomeData = netatmoBridgeHandler.getWelcomeDataBody(null);
if (welcomeHomeData != null) {
welcomeHomeData.getHomes().forEach(home -> {
netatmoBridgeHandler.getWelcomeDataBody(null).ifPresent(dataBody -> {
dataBody.getHomes().forEach(home -> {
discoverWelcomeHome(home);
});
}
});
}
stopScan();
}

@Override
public void onDataRefreshed(Object data) {
if (!isBackgroundDiscoveryEnabled()) {
return;
}
if (data instanceof NAMain) {
discoverWeatherStation((NAMain) data);
} else if (data instanceof NAPlug) {
Expand Down
Loading