diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/NetatmoBindingProvider.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/NetatmoBindingProvider.java
index 6fee6bdff7b..82a997bed40 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/NetatmoBindingProvider.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/NetatmoBindingProvider.java
@@ -10,6 +10,7 @@
import org.openhab.core.binding.BindingProvider;
import org.openhab.binding.netatmo.internal.NetatmoMeasureType;
+import org.openhab.binding.netatmo.internal.NetatmoScale;
/**
* This interface is implemented by classes that can provide mapping information
@@ -19,6 +20,7 @@
* taken into account.
*
* @author Andreas Brenk
+ * @author Rob Nielsen
* @since 1.4.0
*/
public interface NetatmoBindingProvider extends BindingProvider {
@@ -62,4 +64,13 @@ public interface NetatmoBindingProvider extends BindingProvider {
*/
String getModuleId(String itemName);
+ /**
+ * Returns the scale to use when querying the Netatmo measure of the given
+ * {@code itemName}.
+ *
+ * @param itemName
+ * @return the Netatmo scale of the Item identified by {@code itemName} if
+ * it has a Netatmo binding, null otherwise
+ */
+ NetatmoScale getNetatmoScale(String itemName);
}
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBinding.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBinding.java
index 2bc3eec0834..15fe9b7f9ee 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBinding.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBinding.java
@@ -12,9 +12,11 @@
import static org.openhab.binding.netatmo.internal.messages.MeasurementRequest.createKey;
import java.math.BigDecimal;
+import java.util.Calendar;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
+import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -118,12 +120,17 @@ protected void execute() {
}
DeviceMeasureValueMap deviceMeasureValueMap = processMeasurements(oauthCredentials);
+ if (deviceMeasureValueMap == null) {
+ return;
+ }
+
for (final NetatmoBindingProvider provider : this.providers) {
for (final String itemName : provider.getItemNames()) {
final String deviceId = provider.getDeviceId(itemName);
final String moduleId = provider.getModuleId(itemName);
final NetatmoMeasureType measureType = provider
.getMeasureType(itemName);
+ final NetatmoScale scale = provider.getNetatmoScale(itemName);
State state = null;
switch (measureType) {
@@ -157,22 +164,60 @@ protected void execute() {
case NOISE:
case PRESSURE:
case RAIN:
- final String requestKey = createKey(deviceId,
- moduleId);
- BigDecimal value = deviceMeasureValueMap.get(
- requestKey).get(measureType.getMeasure());
- // Protect that sometimes Netatmo returns null where
- // numeric value is awaited (issue #1848)
- if (value != null) {
- if (measureType == NetatmoMeasureType.TEMPERATURE) {
- value = unitSystem.convertTemp(value);
- } else if (measureType == NetatmoMeasureType.RAIN) {
- value = unitSystem.convertRain(value);
- } else if (measureType == NetatmoMeasureType.PRESSURE) {
- value = pressureUnit.convertPressure(value);
- }
+ case MIN_TEMP:
+ case MAX_TEMP:
+ case MIN_HUM:
+ case MAX_HUM:
+ case MIN_PRESSURE:
+ case MAX_PRESSURE:
+ case MIN_NOISE:
+ case MAX_NOISE:
+ case MIN_CO2:
+ case MAX_CO2:
+ case SUM_RAIN:
+ {
+ BigDecimal value = getValue(
+ deviceMeasureValueMap, measureType,
+ createKey(deviceId, moduleId, scale));
+ // Protect that sometimes Netatmo returns null where
+ // numeric value is awaited (issue #1848)
+ if (value != null) {
+ if (NetatmoMeasureType
+ .isTemperature(measureType)) {
+ value = unitSystem.convertTemp(value);
+ } else if (NetatmoMeasureType
+ .isRain(measureType)) {
+ value = unitSystem.convertRain(value);
+ } else if (NetatmoMeasureType
+ .isPressure(measureType)) {
+ value = pressureUnit.convertPressure(value);
+ }
- state = new DecimalType(value);
+ state = new DecimalType(value);
+ }
+ }
+ break;
+ case DATE_MIN_TEMP:
+ case DATE_MAX_TEMP:
+ case DATE_MIN_HUM:
+ case DATE_MAX_HUM:
+ case DATE_MIN_PRESSURE:
+ case DATE_MAX_PRESSURE:
+ case DATE_MIN_NOISE:
+ case DATE_MAX_NOISE:
+ case DATE_MIN_CO2:
+ case DATE_MAX_CO2:
+ {
+ final BigDecimal value = getValue(
+ deviceMeasureValueMap, measureType,
+ createKey(deviceId, moduleId, scale));
+ if (value != null) {
+ final Calendar calendar = GregorianCalendar
+ .getInstance();
+ calendar.setTimeInMillis(value.longValue() * 1000);
+
+ state = new DateTimeType(calendar);
+ }
}
break;
case BATTERYVP:
@@ -206,13 +251,16 @@ protected void execute() {
for (Device device : oauthCredentials.deviceListResponse
.getDevices()) {
if (stationPosition == null) {
+ DecimalType altitude = DecimalType.ZERO;
+ if (device.getAltitude() != null) {
+ altitude = new DecimalType(Math.round(unitSystem.
+ convertAltitude(device.getAltitude())));
+ }
stationPosition = new PointType(
new DecimalType(
- device.getLatitude()),
- new DecimalType(device
- .getLongitude()),
- new DecimalType(Math.round(unitSystem.
- convertAltitude(device.getAltitude()))));
+ new BigDecimal(device.getLatitude()).setScale(6, BigDecimal.ROUND_HALF_UP)),
+ new DecimalType(new BigDecimal(device.getLongitude()).setScale(6, BigDecimal.ROUND_HALF_UP)),
+ altitude);
}
if (device.getId().equals(deviceId)) {
switch (measureType) {
@@ -253,6 +301,13 @@ protected void execute() {
}
}
+ private BigDecimal getValue(DeviceMeasureValueMap deviceMeasureValueMap,
+ final NetatmoMeasureType measureType, final String requestKey) {
+ Map map = deviceMeasureValueMap.get(requestKey);
+
+ return map != null ? map.get(measureType.getMeasure()) : null;
+ }
+
static class DeviceMeasureValueMap extends
HashMap> {
@@ -276,14 +331,20 @@ private DeviceMeasureValueMap processMeasurements(
if (response.isError()) {
final NetatmoError error = response.getError();
- if (error.isAccessTokenExpired()) {
+ if (error.isAccessTokenExpired() || error.isTokenNotVaid()) {
+ logger.debug("Token is expired or is not valid, refreshing: code = {} message = {}",
+ error.getCode(), error.getMessage());
+
oauthCredentials.refreshAccessToken();
execute();
+
+ return null;
} else {
+ logger.error("Error sending measurement request: code = {} message = {}",
+ error.getCode(), error.getMessage());
+
throw new NetatmoException(error.getMessage());
}
-
- break; // abort processing measurement requests
} else {
processMeasurementResponse(request, response,
deviceMeasureValueMap);
@@ -301,10 +362,16 @@ private void processDeviceList(OAuthCredentials oauthCredentials) {
final NetatmoError error = oauthCredentials.deviceListResponse
.getError();
- if (error.isAccessTokenExpired()) {
+ if (error.isAccessTokenExpired() || error.isTokenNotVaid()) {
+ logger.debug("Token is expired or is not valid, refreshing: code = {} message = {}",
+ error.getCode(), error.getMessage());
+
oauthCredentials.refreshAccessToken();
execute();
} else {
+ logger.error("Error processing device list: code = {} message = {}",
+ error.getCode(), error.getMessage());
+
throw new NetatmoException(error.getMessage());
}
@@ -415,15 +482,9 @@ private Collection createMeasurementRequests() {
for (final NetatmoBindingProvider provider : this.providers) {
for (final String itemName : provider.getItemNames()) {
-
- final String userid = provider.getUserid(itemName);
- final String deviceId = provider.getDeviceId(itemName);
- final String moduleId = provider.getModuleId(itemName);
final NetatmoMeasureType measureType = provider
.getMeasureType(itemName);
- final String requestKey = createKey(deviceId, moduleId);
-
switch (measureType) {
case TEMPERATURE:
case CO2:
@@ -431,16 +492,30 @@ private Collection createMeasurementRequests() {
case NOISE:
case PRESSURE:
case RAIN:
- OAuthCredentials oauthCredentials = getOAuthCredentials(userid);
- if (oauthCredentials != null) {
- if (!requests.containsKey(requestKey)) {
- requests.put(requestKey, new MeasurementRequest(
- oauthCredentials.accessToken, deviceId,
- moduleId));
- }
- requests.get(requestKey).addMeasure(measureType);
- break;
- }
+ case MIN_TEMP:
+ case MAX_TEMP:
+ case MIN_HUM:
+ case MAX_HUM:
+ case MIN_PRESSURE:
+ case MAX_PRESSURE:
+ case MIN_NOISE:
+ case MAX_NOISE:
+ case MIN_CO2:
+ case MAX_CO2:
+ case SUM_RAIN:
+ case DATE_MIN_TEMP:
+ case DATE_MAX_TEMP:
+ case DATE_MIN_HUM:
+ case DATE_MAX_HUM:
+ case DATE_MIN_PRESSURE:
+ case DATE_MAX_PRESSURE:
+ case DATE_MIN_NOISE:
+ case DATE_MAX_NOISE:
+ case DATE_MIN_CO2:
+ case DATE_MAX_CO2:
+ final NetatmoScale scale = provider.getNetatmoScale(itemName);
+ addMeasurement(requests, provider, itemName, measureType, scale);
+ break;
default:
break;
}
@@ -450,12 +525,40 @@ private Collection createMeasurementRequests() {
return requests.values();
}
+ private void addMeasurement(final Map requests,
+ final NetatmoBindingProvider provider, final String itemName,
+ final NetatmoMeasureType measureType, final NetatmoScale scale) {
+
+ final String userid = provider.getUserid(itemName);
+ final OAuthCredentials oauthCredentials = getOAuthCredentials(userid);
+
+ if (oauthCredentials != null) {
+ final String deviceId = provider.getDeviceId(itemName);
+ final String moduleId = provider.getModuleId(itemName);
+ final String requestKey = createKey(deviceId, moduleId, scale);
+
+ if (!requests.containsKey(requestKey)) {
+ requests.put(requestKey, new MeasurementRequest(
+ oauthCredentials.accessToken, deviceId,
+ moduleId, scale));
+ }
+ requests.get(requestKey).addMeasure(measureType);
+ }
+ }
+
private void processMeasurementResponse(final MeasurementRequest request,
final MeasurementResponse response,
DeviceMeasureValueMap deviceMeasureValueMap) {
final List values = response.getBody().get(0).getValues()
.get(0);
- final Map valueMap = new HashMap();
+
+ Map valueMap = deviceMeasureValueMap.get(request.getKey());
+ if (valueMap == null) {
+ valueMap = new HashMap();
+
+ deviceMeasureValueMap.put(request.getKey(), valueMap);
+ deviceMeasureValueMap.timeStamp = new DateTimeType(response.getTimeStamp());
+ }
int index = 0;
for (final String measure : request.getMeasures()) {
@@ -463,10 +566,6 @@ private void processMeasurementResponse(final MeasurementRequest request,
valueMap.put(measure, value);
index++;
}
-
- deviceMeasureValueMap.put(request.getKey(), valueMap);
- deviceMeasureValueMap.timeStamp = new DateTimeType(
- response.getTimeStamp());
}
/**
@@ -639,6 +738,14 @@ public void refreshAccessToken() {
final RefreshTokenResponse response = request.execute();
logger.debug("Response: {}", response);
+ if (response == null) {
+ throw new NetatmoException("Could not refresh access token! If you see "
+ + "'Fatal transport error: javax.net.ssl.SSLHandshakeException' "
+ + "above. You need to install the StartCom CA certificate and restart openHAB. "
+ + "See https://github.com/openhab/openhab/wiki/Netatmo-Binding#missing-certificate-authority "
+ + "for more information.");
+ }
+
this.accessToken = response.getAccessToken();
deviceListRequest = new DeviceListRequest(this.accessToken);
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoGenericBindingProvider.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoGenericBindingProvider.java
index 6b43bb0a1df..e514064f8f7 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoGenericBindingProvider.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoGenericBindingProvider.java
@@ -60,6 +60,7 @@
* @author Andreas Brenk
* @author Thomas.Eichstaedt-Engelen
* @author Gaël L'hopital
+ * @author Rob Nielsen
* @since 1.4.0
*/
public class NetatmoGenericBindingProvider extends
@@ -133,6 +134,16 @@ public String getModuleId(final String itemName) {
return config != null ? config.moduleId : null;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public NetatmoScale getNetatmoScale(String itemName) {
+ final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs
+ .get(itemName);
+ return config != null ? config.netatmoScale : null;
+ }
+
/**
* {@inheritDoc}
*/
@@ -147,27 +158,48 @@ public void processBindingConfiguration(final String context,
final NetatmoBindingConfig config = new NetatmoBindingConfig();
final String[] configParts = bindingConfig.split("#");
+ String measureTypeString;
switch (configParts.length) {
case 2:
config.deviceId = configParts[0];
- config.measureType = NetatmoMeasureType.fromString(configParts[1]);
+ measureTypeString = configParts[1];
break;
case 3:
config.deviceId = configParts[0];
config.moduleId = configParts[1];
- config.measureType = NetatmoMeasureType.fromString(configParts[2]);
+ measureTypeString = configParts[2];
break;
case 4:
config.userid = configParts[0];
config.deviceId = configParts[1];
config.moduleId = configParts[2];
- config.measureType = NetatmoMeasureType.fromString(configParts[3]);
+ measureTypeString = configParts[3];
break;
default:
throw new BindingConfigParseException(
"A Netatmo binding configuration must consist of two, three or four parts - please verify your *.items file");
}
+ /*
+ * use a ',' when including scale so that it does not break backwards
+ * compatibility with case 4 above.
+ */
+ final String[] measureTypeParts = measureTypeString.split(",");
+ switch (measureTypeParts.length) {
+ case 1:
+ config.measureType = NetatmoMeasureType.fromString(measureTypeParts[0]);
+ config.netatmoScale = config.measureType.getDefaultScale();
+ break;
+ case 2:
+ config.measureType = NetatmoMeasureType.fromString(measureTypeParts[0]);
+ config.netatmoScale = NetatmoScale.fromString(measureTypeParts[1]);
+ break;
+ default:
+ throw new BindingConfigParseException(
+ "The last part of the Netatmo binding configuration must be 'type' or 'type,scale'"
+ + " - please verify your *.items file");
+ }
+
logger.debug("Adding binding: {}", config);
addBindingConfig(item, config);
@@ -179,6 +211,7 @@ private static class NetatmoBindingConfig implements BindingConfig {
String deviceId;
String moduleId;
NetatmoMeasureType measureType;
+ NetatmoScale netatmoScale;
@Override
public String toString() {
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoMeasureType.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoMeasureType.java
index af764d59fb9..60804e9de3e 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoMeasureType.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoMeasureType.java
@@ -12,22 +12,40 @@
/**
* @author Gaël L'hopital
+ * @author Rob Nielsen
* @since 1.6.0
*
* This enum holds all the different measures and states available to be
* retrieved by the Netatmo binding
*/
public enum NetatmoMeasureType {
- CO2("CO2"), TEMPERATURE("Temperature"), HUMIDITY("Humidity"), NOISE("Noise"), PRESSURE(
- "Pressure"), RAIN("Rain"), WIFISTATUS("WifiStatus"), ALTITUDE(
- "Altitude"), LATITUDE("Latitude"), LONGITUDE("Longitude"), RFSTATUS(
- "RfStatus"), BATTERYVP("BatteryVp"), TIMESTAMP("TimeStamp"), MODULENAME(
- "ModuleName"), STATIONNAME("StationName"), COORDINATE("Coordinate");
+ CO2("CO2", NetatmoScale.MAX), TEMPERATURE("Temperature", NetatmoScale.MAX),
+ HUMIDITY("Humidity", NetatmoScale.MAX), NOISE("Noise", NetatmoScale.MAX),
+ PRESSURE("Pressure", NetatmoScale.MAX), RAIN("Rain", NetatmoScale.MAX),
+ WIFISTATUS("WifiStatus", NetatmoScale.MAX), ALTITUDE("Altitude",NetatmoScale.MAX),
+ LATITUDE("Latitude", NetatmoScale.MAX), LONGITUDE("Longitude", NetatmoScale.MAX),
+ RFSTATUS("RfStatus", NetatmoScale.MAX), BATTERYVP("BatteryVp", NetatmoScale.MAX),
+ TIMESTAMP("TimeStamp", NetatmoScale.MAX), MODULENAME("ModuleName",NetatmoScale.MAX),
+ STATIONNAME("StationName", NetatmoScale.MAX), COORDINATE("Coordinate", NetatmoScale.MAX),
+ MIN_TEMP("min_temp", NetatmoScale.ONE_DAY), MAX_TEMP("max_temp", NetatmoScale.ONE_DAY),
+ MIN_HUM("min_hum", NetatmoScale.ONE_DAY), MAX_HUM("max_hum", NetatmoScale.ONE_DAY),
+ MIN_PRESSURE("min_pressure", NetatmoScale.ONE_DAY), MAX_PRESSURE("max_pressure", NetatmoScale.ONE_DAY),
+ MIN_NOISE("min_noise", NetatmoScale.ONE_DAY), MAX_NOISE("max_noise", NetatmoScale.ONE_DAY),
+ MIN_CO2("min_co2", NetatmoScale.ONE_DAY), MAX_CO2("max_co2", NetatmoScale.ONE_DAY),
+ SUM_RAIN("sum_rain", NetatmoScale.ONE_DAY), DATE_MIN_TEMP("date_min_temp", NetatmoScale.ONE_DAY),
+ DATE_MAX_TEMP("date_max_temp", NetatmoScale.ONE_DAY), DATE_MIN_HUM("date_min_hum", NetatmoScale.ONE_DAY),
+ DATE_MAX_HUM("date_max_hum", NetatmoScale.ONE_DAY), DATE_MIN_PRESSURE("date_min_pressure", NetatmoScale.ONE_DAY),
+ DATE_MAX_PRESSURE("date_max_pressure", NetatmoScale.ONE_DAY), DATE_MIN_NOISE("date_min_noise", NetatmoScale.ONE_DAY),
+ DATE_MAX_NOISE("date_max_noise", NetatmoScale.ONE_DAY), DATE_MIN_CO2("date_min_co2", NetatmoScale.ONE_DAY),
+ DATE_MAX_CO2("date_max_co2", NetatmoScale.ONE_DAY);
- String measure;
+ final String measure;
- private NetatmoMeasureType(String measure) {
+ final NetatmoScale defaultScale;
+
+ private NetatmoMeasureType(String measure, NetatmoScale defaultScale) {
this.measure = measure;
+ this.defaultScale = defaultScale;
}
public String getMeasure() {
@@ -44,4 +62,25 @@ public static NetatmoMeasureType fromString(String measure) {
}
throw new IllegalArgumentException("Invalid measure: " + measure);
}
+
+ public NetatmoScale getDefaultScale() {
+ return defaultScale;
+ }
+
+ public static boolean isPressure(NetatmoMeasureType measureType) {
+ return measureType == NetatmoMeasureType.PRESSURE
+ || measureType == NetatmoMeasureType.MIN_PRESSURE
+ || measureType == NetatmoMeasureType.MAX_PRESSURE;
+ }
+
+ public static boolean isRain(NetatmoMeasureType measureType) {
+ return measureType == NetatmoMeasureType.RAIN
+ || measureType == NetatmoMeasureType.SUM_RAIN;
+ }
+
+ public static boolean isTemperature(NetatmoMeasureType measureType) {
+ return measureType == NetatmoMeasureType.TEMPERATURE
+ || measureType == NetatmoMeasureType.MIN_TEMP
+ || measureType == NetatmoMeasureType.MAX_TEMP;
+ }
}
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoPressureUnit.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoPressureUnit.java
index 2ddb18d2565..95e99e9f959 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoPressureUnit.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoPressureUnit.java
@@ -23,9 +23,10 @@ public enum NetatmoPressureUnit {
MBAR("mbar"), INHG("inHg"), MMHG("mmHg");
public static final NetatmoPressureUnit DEFAULT_PRESSURE_UNIT = NetatmoPressureUnit.MBAR;
- private static final BigDecimal MBAR_TO_INHG = new BigDecimal(0.02952998751);
- private static final BigDecimal MBAR_TO_MMHG = new BigDecimal(0.750061683);
+ private static final BigDecimal MBAR_TO_INHG = new BigDecimal("0.0295");
+
+ private static final BigDecimal MBAR_TO_MMHG = new BigDecimal("0.7500");
String pressureUnit;
@@ -50,6 +51,16 @@ public static NetatmoPressureUnit fromString(String pressureUnit) {
+ pressureUnit);
}
+ /**
+ * Convert to appropriate measurement.
+ *
+ * The Barometer is accurate to +-1 mbar or +- 0.03 inHg
+ *
+ * @param value
+ * pressure in mbars
+ *
+ * @return value in proper measurement
+ */
public BigDecimal convertPressure(BigDecimal value) {
if (this == DEFAULT_PRESSURE_UNIT) {
return value;
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoScale.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoScale.java
new file mode 100644
index 00000000000..cf5e6d40171
--- /dev/null
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoScale.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2010-2015, openHAB.org and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.openhab.binding.netatmo.internal;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * @author Rob Nielsen
+ * @since 1.8.0
+ *
+ * This enum holds all the different scales for the Netatmo binding
+ * when using the Netatmo getMeasure api
+ */
+public enum NetatmoScale {
+ MAX("max"), THIRTY_MIN("30min"), ONE_HOUR("1hour"), THREE_HOURS("3hours"),
+ ONE_DAY("1day"), ONE_WEEK("1week"), ONE_MONTH("1month");
+
+ String scale;
+
+ private NetatmoScale(String scale) {
+ this.scale = scale;
+ }
+
+ public String getScale() {
+ return scale;
+ }
+
+ public static NetatmoScale fromString(String scale) {
+ if (!StringUtils.isEmpty(scale)) {
+ for (NetatmoScale unitSystemType : NetatmoScale.values()) {
+ if (unitSystemType.getScale().equalsIgnoreCase(scale)) {
+ return unitSystemType;
+ }
+ }
+ }
+ throw new IllegalArgumentException("Invalid scale: " + scale);
+ }
+}
\ No newline at end of file
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoUnitSystem.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoUnitSystem.java
index 8ffe4b23e49..22b1f37e779 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoUnitSystem.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoUnitSystem.java
@@ -26,11 +26,11 @@ public enum NetatmoUnitSystem {
private static final double METERS_TO_FEET = 3.2808399;
- private static final BigDecimal MM_TO_INCHES = new BigDecimal(0.0393700787);
+ private static final BigDecimal MM_TO_INCHES = new BigDecimal("0.0394");
- private static final BigDecimal ONE_POINT_EIGHT = new BigDecimal(1.8);
+ private static final BigDecimal ONE_POINT_EIGHT = new BigDecimal("1.8");
- private static final BigDecimal THIRTY_TWO = new BigDecimal(32);
+ private static final BigDecimal THIRTY_TWO = new BigDecimal("32");
String unitSystem;
@@ -53,6 +53,14 @@ public static NetatmoUnitSystem fromString(String unitSystem) {
throw new IllegalArgumentException("Invalid unitSystem: " + unitSystem);
}
+ /**
+ * Convert to appropriate measurement.
+ *
+ * @param value
+ * altitude in Meters
+ *
+ * @return value in the proper measurement
+ */
public double convertAltitude(double value) {
if (this == DEFAULT_UNIT_SYSTEM) {
return value;
@@ -61,6 +69,17 @@ public double convertAltitude(double value) {
return value * METERS_TO_FEET;
}
+ /**
+ * Convert to appropriate measurement.
+ *
+ * The Rain gauge is accurate to 1 mm/h or 0.04 in/h, and the range starts
+ * at 0.2 mm/h or 0.01 in/h.
+ *
+ * @param value
+ * rain in Millimeters
+ *
+ * @return value in the proper measurement
+ */
public BigDecimal convertRain(BigDecimal value) {
if (this == DEFAULT_UNIT_SYSTEM) {
return value;
@@ -68,7 +87,17 @@ public BigDecimal convertRain(BigDecimal value) {
return value.multiply(MM_TO_INCHES);
}
-
+
+ /**
+ * Convert to appropriate measurement.
+ *
+ * The Thermometer is accurate to +- 0.3°C or +- 0.54°F
+ *
+ * @param value
+ * temperature in Celsius
+ *
+ * @return value the in proper measurement
+ */
public BigDecimal convertTemp(BigDecimal value) {
if (this == DEFAULT_UNIT_SYSTEM) {
return value;
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/DeviceListRequest.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/DeviceListRequest.java
index 85e441b7548..8a15f565c24 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/DeviceListRequest.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/DeviceListRequest.java
@@ -14,6 +14,8 @@
import org.apache.commons.httpclient.URIException;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.openhab.binding.netatmo.internal.NetatmoException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A devicelist request returns the list of devices owned by the user, and their
@@ -28,6 +30,8 @@ public class DeviceListRequest extends AbstractRequest {
private static final String RESOURCE_URL = API_BASE_URL + "devicelist";
+ private static final Logger logger = LoggerFactory.getLogger(DeviceListRequest.class);
+
private final String accessToken;
/**
@@ -46,6 +50,9 @@ public DeviceListRequest(final String accessToken) {
@Override
public DeviceListResponse execute() {
final String url = prepare();
+
+ logger.debug(url);
+
String json = null;
try {
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/MeasurementRequest.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/MeasurementRequest.java
index c43e6587112..817e5d05bac 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/MeasurementRequest.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/MeasurementRequest.java
@@ -19,12 +19,16 @@
import org.apache.commons.lang.builder.ToStringBuilder;
import org.openhab.binding.netatmo.internal.NetatmoException;
import org.openhab.binding.netatmo.internal.NetatmoMeasureType;
+import org.openhab.binding.netatmo.internal.NetatmoScale;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Queries the Netatmo API for the measures of a single device or module.
*
* @author Andreas Brenk
* @author Gaël L'hopital
+ * @author Rob Nielsen
* @since 1.4.0
* @see getmeasure
*/
@@ -32,6 +36,8 @@ public class MeasurementRequest extends AbstractRequest {
private static final String RESOURCE_URL = API_BASE_URL + "getmeasure";
+ private static final Logger logger = LoggerFactory.getLogger(MeasurementRequest.class);
+
/**
* @param deviceId
* mandatory, must not be null
@@ -39,12 +45,13 @@ public class MeasurementRequest extends AbstractRequest {
* optional, may be null
* @return a unique key suitable to store a request in a map
*/
- public static String createKey(final String deviceId, final String moduleId) {
+ public static String createKey(final String deviceId, final String moduleId, final NetatmoScale scale) {
+ final String s = ":" + scale.getScale();
if (moduleId == null) {
- return "device:" + deviceId;
+ return "device:" + deviceId + s;
} else {
- return "module:" + moduleId;
+ return "module:" + moduleId + s;
}
}
@@ -54,10 +61,13 @@ public static String createKey(final String deviceId, final String moduleId) {
private final String moduleId;
+ private final NetatmoScale scale;
+
private final SortedSet measures = new TreeSet();
/**
- * Creates a request for the measurements of a device or module.
+ * Creates a request for the measurements of a device or module
+ * using the default scale.
*
* If you don't specify a moduleId you will retrieve the device's
* measurements. If you do specify a moduleId you will retrieve the module's
@@ -70,12 +80,33 @@ public static String createKey(final String deviceId, final String moduleId) {
*/
public MeasurementRequest(final String accessToken, final String deviceId,
final String moduleId) {
+ this(accessToken, deviceId, moduleId, NetatmoScale.MAX);
+ }
+
+ /**
+ * Creates a request for the measurements of a device or module
+ * using the scale specified.
+ *
+ * If you don't specify a moduleId you will retrieve the device's
+ * measurements. If you do specify a moduleId you will retrieve the module's
+ * measurements.
+ *
+ * @param accessToken
+ * @param deviceId
+ * @param moduleId
+ * optional, may be null
+ * @param scale
+ */
+ public MeasurementRequest(final String accessToken, final String deviceId,
+ final String moduleId, final NetatmoScale scale) {
assert accessToken != null : "accessToken must not be null!";
assert deviceId != null : "deviceId must not be null!";
+ assert scale != null : "scale must not be null!";
this.accessToken = accessToken;
this.deviceId = deviceId;
this.moduleId = moduleId;
+ this.scale = scale;
}
/**
@@ -90,6 +121,9 @@ public void addMeasure(final NetatmoMeasureType measureType) {
@Override
public MeasurementResponse execute() {
final String url = buildQueryString();
+
+ logger.debug(url);
+
String json = null;
try {
@@ -109,7 +143,7 @@ public MeasurementResponse execute() {
* @see #createKey(String, String)
*/
public String getKey() {
- return createKey(this.deviceId, this.moduleId);
+ return createKey(this.deviceId, this.moduleId, this.scale);
}
public SortedSet getMeasures() {
@@ -139,7 +173,7 @@ private String buildQueryString() {
final StringBuilder urlBuilder = new StringBuilder(RESOURCE_URL);
urlBuilder.append("?access_token=");
urlBuilder.append(this.accessToken);
- urlBuilder.append("&scale=max");
+ urlBuilder.append("&scale=" + scale.getScale());
urlBuilder.append("&date_end=last");
urlBuilder.append("&device_id=");
urlBuilder.append(this.deviceId);
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/NetatmoError.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/NetatmoError.java
index b3b7b74f0d8..ba090a4f3be 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/NetatmoError.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/NetatmoError.java
@@ -56,6 +56,10 @@ public String getMessage() {
return this.message;
}
+ public boolean isTokenNotVaid() {
+ return this.code == 2;
+ }
+
public boolean isAccessTokenExpired() {
return this.code == 3;
}
diff --git a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/RefreshTokenRequest.java b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/RefreshTokenRequest.java
index 15b9764c518..c3c87afd16d 100644
--- a/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/RefreshTokenRequest.java
+++ b/bundles/binding/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/messages/RefreshTokenRequest.java
@@ -54,6 +54,9 @@ public RefreshTokenResponse execute() {
this.clientId, this.clientSecret);
json = executeQuery(content);
+ if (json == null) {
+ return null;
+ }
final RefreshTokenResponse response = JSON.readValue(json,
RefreshTokenResponse.class);