/**
* Copyright (c) 2010-2016 by the respective copyright holders.
*
* 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.openhab.binding.netatmo.NetatmoBindingProvider;
import org.openhab.binding.netatmo.internal.camera.NetatmoCameraAttributes;
import org.openhab.binding.netatmo.internal.weather.NetatmoMeasureType;
import org.openhab.binding.netatmo.internal.weather.NetatmoScale;
import org.openhab.core.binding.BindingConfig;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.DateTimeItem;
import org.openhab.core.library.items.LocationItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.model.item.binding.AbstractGenericBindingProvider;
import org.openhab.model.item.binding.BindingConfigParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is responsible for parsing the binding configuration.
*
* <p>
* Valid bindings for the main device are
* <ul>
* <li><code>{ netatmo="[weather=]<device_id>#Measurement" }</code></li>
* <ul>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Temperature" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Humidity" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Co2" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Pressure" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Noise" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#WifiStatus" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Altitude" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Latitude" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#Longitude" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#TimeStamp" }</code></li>
* </ul>
* </li>
* </ul>
* <p>
* * Valid bindings for a module are
* <ul>
* <li>
* <code>{ netatmo="[weather=]<device_id>#<module_id>#Measurement" }</code></li>
* <ul>
* <li>
* <code>{ netatmo="[weather=]00:00:00:00:00:00#00:00:00:00:00:00#Temperature" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#00:00:00:00:00:00#Humidity" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#00:00:00:00:00:00#Co2" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#00:00:00:00:00:00#Rain" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#00:00:00:00:00:00#RfStatus" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#00:00:00:00:00:00#BatteryVp" }</code></li>
* <li><code>{ netatmo="[weather=]00:00:00:00:00:00#00:00:00:00:00:00#TimeStamp" }</code></li>
* </ul>
* </li>
* </ul>
* <b>Netatmo camera:</b>
* Valid bindings for a netatmo camera home are:
* <ul>
* <li>
* <code>{ netatmo="camera=<home_id>#attribute" }</code></li>
* <ul>
* <li><code>{ netatmo="camera=000000000000000000000000#Name" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#PlaceCountry" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#PlaceTimezone" }</code></li>
* </ul>
* </li>
* </ul>
*
*
* Valid bindings for a netatmo camera person are:
* <ul>
* <li>
* <code>{ netatmo="camera=<home_id>#<person_id>#attribute" }</code></li>
* <ul>
* <li><code>{ netatmo="camera=000000000000000000000000#00000000-0000-0000-0000-000000000000#Pseudo" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#00000000-0000-0000-0000-000000000000#LastSeen" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#00000000-0000-0000-0000-000000000000#OutOfSight" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#00000000-0000-0000-0000-000000000000#FaceId" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#00000000-0000-0000-0000-000000000000#FaceKey" }</code></li>
* </ul>
* </li>
* </ul>
*
* Valid bindings for netatmo camera unknown persons are:
* <ul>
* <li>
* <code>{ netatmo="camera=<home_id>#<UNKNOWN>#attribute" }</code></li>
* <ul>
* <li><code>{ netatmo="camera=000000000000000000000000#UNKNOWN#HomeCount" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#UNKNOWN#AwayCount" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#UNKNOWN#LastSeenList" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#UNKNOWN#OutOfSightList" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#UNKNOWN#FaceIdList" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#UNKNOWN#FaceKeyList" }</code></li>
* </ul>
* </li>
* </ul>
*
* Valid bindings for netatmo camera are:
* <ul>
* <li>
* <code>{ netatmo="camera=<home_id>#<camera_id>#attribute" }</code></li>
* <ul>
* <li><code>{ netatmo="camera=000000000000000000000000#00:00:00:00:00:00#Status" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#00:00:00:00:00:00#SdStatus" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#00:00:00:00:00:00#AlimStatus" }</code></li>
* <li><code>{ netatmo="camera=000000000000000000000000#00:00:00:00:00:00#Name" }</code></li>
* </ul>
* </li>
* </ul>
*
* Valid bindings for netatmo camera event is -> NOT IMPLEMENTED NOW: TODO
* <ul>
* <li>
* <code>{ netatmo="camera=<home_id>#<event_id>#attribute" }</code></li>
* <ul>
* </ul>
* </li>
* </ul>
*
*
* @author Andreas Brenk
* @author Thomas.Eichstaedt-Engelen
* @author Gaƫl L'hopital
* @author Rob Nielsen
* @author Ing. Peter Weiss
* @since 1.4.0
*/
public class NetatmoGenericBindingProvider extends AbstractGenericBindingProvider implements NetatmoBindingProvider {
private static Logger logger = LoggerFactory.getLogger(NetatmoGenericBindingProvider.class);
public static String NETATMO_WEATHER = "weather";
public static String NETATMO_CAMERA = "camera";
/**
* {@inheritDoc}
*/
@Override
public String getBindingType() {
return "netatmo";
}
/**
* @{inheritDoc
*/
@Override
public void validateItemType(final Item item, final String bindingConfig) throws BindingConfigParseException {
if (!(item instanceof NumberItem || item instanceof DateTimeItem || item instanceof LocationItem
|| item instanceof StringItem || item instanceof SwitchItem)) {
throw new BindingConfigParseException("item '" + item.getName() + "' is of type '"
+ item.getClass().getSimpleName()
+ "', only NumberItems, DateTimeItems, StringItems, Switch and LocationItems are allowed - please check your *.items configuration");
}
}
/**
* {@inheritDoc}
*/
@Override
public String getUserid(final String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? config.userid : null;
}
/**
* {@inheritDoc}
*/
@Override
public String getDeviceId(final String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? config.deviceId : null;
}
/**
* {@inheritDoc}
*/
@Override
public NetatmoMeasureType getMeasureType(String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? config.measureType : null;
}
/**
* {@inheritDoc}
*/
@Override
public String getModuleId(final String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(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}
*/
@Override
public String getHomeId(String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? config.homeId : null;
}
/**
* {@inheritDoc}
*/
@Override
public String getPersonId(String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? config.personId : null;
}
/**
* {@inheritDoc}
*/
@Override
public NetatmoCameraAttributes getAttribute(String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? config.attribute : null;
}
/**
* {@inheritDoc}
*/
@Override
public String getCameraId(String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? config.cameraId : null;
}
/**
* {@inheritDoc}
*/
@Override
public String getItemType(String itemName) {
final NetatmoBindingConfig config = (NetatmoBindingConfig) this.bindingConfigs.get(itemName);
return config != null ? (config.bWeather ? NETATMO_WEATHER : (config.bCamera ? NETATMO_CAMERA : null)) : null;
}
/**
* {@inheritDoc}
*/
@Override
public void processBindingConfiguration(final String context, final Item item, final String bindingConfig)
throws BindingConfigParseException {
logger.debug("Processing binding configuration: '{}'", bindingConfig);
super.processBindingConfiguration(context, item, bindingConfig);
final NetatmoBindingConfig config = new NetatmoBindingConfig();
final String[] configParts = bindingConfig.split("#");
String deviceType = NETATMO_WEATHER; // Default value for backward compatibility
if (configParts.length > 0) {
final String[] sPart = configParts[0].split("=");
switch (sPart.length) {
case 1:
break;
case 2:
deviceType = sPart[0];
if (!(NETATMO_CAMERA.equals(deviceType) || NETATMO_WEATHER.equals(deviceType))) {
throw new BindingConfigParseException(
"The choosen name of the devicetype for the netatmo binding configuration is unknown - please verify your *.items file");
}
configParts[0] = sPart[1];
break;
default:
throw new BindingConfigParseException(
"A netatmo binding configuration must start with the devicetype followed by '=', without weatherstation is default - please verify your *.items file");
}
}
if (NETATMO_WEATHER.equals(deviceType)) {
config.bWeather = true;
String measureTypeString;
switch (configParts.length) {
case 2:
config.deviceId = configParts[0].toLowerCase();
measureTypeString = configParts[1];
break;
case 3:
config.deviceId = configParts[0].toLowerCase();
config.moduleId = configParts[1].toLowerCase();
measureTypeString = configParts[2];
break;
case 4:
config.userid = configParts[0];
config.deviceId = configParts[1].toLowerCase();
config.moduleId = configParts[2].toLowerCase();
measureTypeString = configParts[3];
break;
default:
throw new BindingConfigParseException(
"A Netatmo weather station 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");
}
} else if (NETATMO_CAMERA.equals(deviceType)) {
config.bCamera = true;
switch (configParts.length) {
case 2:
config.homeId = configParts[0];
config.attribute = NetatmoCameraAttributes.fromString(configParts[1]);
break;
case 3:
config.homeId = configParts[0];
// Check Format (Mac Adress with : is a camera, else it's a person)
String sTmp = configParts[1];
final String[] sItem = sTmp.split(":");
if (sItem.length == 6) {
config.cameraId = sTmp;
} else {
config.personId = sTmp;
}
config.attribute = NetatmoCameraAttributes.fromString(configParts[2]);
break;
default:
throw new BindingConfigParseException(
"A Netatmo camera binding configuration must consist of two or three parts - please verify your *.items file");
}
} else {
throw new BindingConfigParseException(
"The choosen name of the devicetype for the netatmo binding configuration is unknown - please verify your *.items file");
}
logger.debug("Adding binding: {}", config);
addBindingConfig(item, config);
}
private static class NetatmoBindingConfig implements BindingConfig {
String userid;
String deviceId;
String moduleId;
NetatmoMeasureType measureType;
NetatmoScale netatmoScale;
// Netatmo camera
String homeId;
String personId;
String cameraId;
NetatmoCameraAttributes attribute;
boolean bWeather = false;
boolean bCamera = false;
@Override
public String toString() {
String sReturn = "NetatmoBindingConfig";
if (bWeather) {
sReturn += " weather=true [userid=" + this.userid + ", deviceId=" + this.deviceId + ", moduleId="
+ this.moduleId + ", measure="
+ (this.measureType != null ? this.measureType.getMeasure() : null) + "]";
}
if (bCamera) {
sReturn += " camera=true [homeId=" + this.homeId + ", personId=" + this.personId + ", cameraId="
+ this.cameraId + ", attribute=" + this.attribute + "]";
}
return sReturn;
}
}
}