/**
* 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.ihc.internal;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.openhab.binding.ihc.ws.IhcEnumValue;
import org.openhab.binding.ihc.ws.datatypes.WSBooleanValue;
import org.openhab.binding.ihc.ws.datatypes.WSDateValue;
import org.openhab.binding.ihc.ws.datatypes.WSEnumValue;
import org.openhab.binding.ihc.ws.datatypes.WSFloatingPointValue;
import org.openhab.binding.ihc.ws.datatypes.WSIntegerValue;
import org.openhab.binding.ihc.ws.datatypes.WSResourceValue;
import org.openhab.binding.ihc.ws.datatypes.WSTimeValue;
import org.openhab.binding.ihc.ws.datatypes.WSTimerValue;
import org.openhab.binding.ihc.ws.datatypes.WSWeekdayValue;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.ContactItem;
import org.openhab.core.library.items.DateTimeItem;
import org.openhab.core.library.items.DimmerItem;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.RollershutterItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.openhab.core.types.UnDefType;
public class IhcDataConverter {
/**
* Convert IHC data type to openHAB data type.
*
* @param itemType
* OpenHAB data type class
* @param value
* IHC data value
*
* @return openHAB {@link State}
*/
public static State convertResourceValueToState(Class<? extends Item> itemType, WSResourceValue value)
throws NumberFormatException {
org.openhab.core.types.State state = UnDefType.UNDEF;
if (itemType == NumberItem.class) {
if (value.getClass() == WSFloatingPointValue.class) {
// state = new
// DecimalType(((WSFloatingPointValue)value).getFloatingPointValue());
// Controller might send floating point value with >10 decimals
// (22.299999237060546875), so round value to have max 2
// decimals
double d = ((WSFloatingPointValue) value).getFloatingPointValue();
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
state = new DecimalType(bd);
}
else if (value.getClass() == WSBooleanValue.class) {
state = new DecimalType(((WSBooleanValue) value).isValue() ? 1 : 0);
}
else if (value.getClass() == WSIntegerValue.class) {
state = new DecimalType(((WSIntegerValue) value).getInteger());
}
else if (value.getClass() == WSTimerValue.class) {
state = new DecimalType(((WSTimerValue) value).getMilliseconds());
}
else if (value.getClass() == WSEnumValue.class) {
state = new DecimalType(((WSEnumValue) value).getEnumValueID());
}
else if (value.getClass() == WSWeekdayValue.class) {
state = new DecimalType(((WSWeekdayValue) value).getWeekdayNumber());
}
else {
throw new NumberFormatException("Can't convert " + value.getClass().toString() + " to NumberItem");
}
} else if (itemType == DimmerItem.class) {
// Dimmer item extends SwitchItem, so it need to be handled before
// SwitchItem
if (value.getClass() == WSIntegerValue.class) {
state = new PercentType(((WSIntegerValue) value).getInteger());
} else {
throw new NumberFormatException("Can't convert " + value.getClass().toString() + " to NumberItem");
}
} else if (itemType == SwitchItem.class) {
if (value.getClass() == WSBooleanValue.class) {
if (((WSBooleanValue) value).isValue()) {
state = OnOffType.ON;
} else {
state = OnOffType.OFF;
}
} else {
throw new NumberFormatException("Can't convert " + value.getClass().toString() + " to SwitchItem");
}
} else if (itemType == ContactItem.class) {
if (value.getClass() == WSBooleanValue.class) {
if (((WSBooleanValue) value).isValue()) {
state = OpenClosedType.OPEN;
} else {
state = OpenClosedType.CLOSED;
}
} else {
throw new NumberFormatException("Can't convert " + value.getClass().toString() + " to ContactItem");
}
} else if (itemType == DateTimeItem.class) {
if (value.getClass() == WSDateValue.class) {
Calendar cal = WSDateTimeToCalendar((WSDateValue) value, null);
state = new DateTimeType(cal);
} else if (value.getClass() == WSTimeValue.class) {
Calendar cal = WSDateTimeToCalendar(null, (WSTimeValue) value);
state = new DateTimeType(cal);
} else {
throw new NumberFormatException("Can't convert " + value.getClass().toString() + " to DateTimeItem");
}
} else if (itemType == StringItem.class) {
if (value.getClass() == WSEnumValue.class) {
state = new StringType(((WSEnumValue) value).getEnumName());
} else {
throw new NumberFormatException("Can't convert " + value.getClass().toString() + " to StringItem");
}
} else if (itemType == RollershutterItem.class) {
if (value.getClass() == WSIntegerValue.class) {
state = new PercentType(((WSIntegerValue) value).getInteger());
} else {
throw new NumberFormatException("Can't convert " + value.getClass().toString() + " to NumberItem");
}
}
return state;
}
private static Calendar WSDateTimeToCalendar(WSDateValue date, WSTimeValue time) {
Calendar cal = new GregorianCalendar(1900, 01, 01);
if (date != null) {
short year = date.getYear();
short month = date.getMonth();
short day = date.getDay();
cal.set(year, month - 1, day, 0, 0, 0);
}
if (time != null) {
int hour = time.getHours();
int minute = time.getMinutes();
int second = time.getSeconds();
cal.set(1900, 0, 1, hour, minute, second);
}
return cal;
}
/**
* Convert openHAB data type to IHC data type.
*
* @param type
* openHAB data type
* @param value
*
* @param enumValues
*
* @return IHC data type
*/
public static WSResourceValue convertCommandToResourceValue(Type type, WSResourceValue value,
ArrayList<IhcEnumValue> enumValues) {
if (type instanceof DecimalType) {
if (value instanceof WSFloatingPointValue) {
double newVal = ((DecimalType) type).doubleValue();
double max = ((WSFloatingPointValue) value).getMaximumValue();
double min = ((WSFloatingPointValue) value).getMinimumValue();
if (newVal >= min && newVal <= max) {
((WSFloatingPointValue) value).setFloatingPointValue(newVal);
} else {
throw new NumberFormatException(
"Value is not between accetable limits (min=" + min + ", max=" + max + ")");
}
} else if (value instanceof WSBooleanValue) {
((WSBooleanValue) value).setValue(((DecimalType) type).intValue() > 0 ? true : false);
} else if (value instanceof WSIntegerValue) {
int newVal = ((DecimalType) type).intValue();
int max = ((WSIntegerValue) value).getMaximumValue();
int min = ((WSIntegerValue) value).getMinimumValue();
if (newVal >= min && newVal <= max) {
((WSIntegerValue) value).setInteger(newVal);
} else {
throw new NumberFormatException(
"Value is not between accetable limits (min=" + min + ", max=" + max + ")");
}
} else if (value instanceof WSTimerValue) {
((WSTimerValue) value).setMilliseconds(((DecimalType) type).longValue());
} else if (value instanceof WSWeekdayValue) {
((WSWeekdayValue) value).setWeekdayNumber(((DecimalType) type).intValue());
} else {
throw new NumberFormatException("Can't convert DecimalType to " + value.getClass());
}
} else if (type instanceof OnOffType) {
if (value instanceof WSBooleanValue) {
((WSBooleanValue) value).setValue(type == OnOffType.ON ? true : false);
} else if (value instanceof WSIntegerValue) {
int newVal = type == OnOffType.ON ? 100 : 0;
int max = ((WSIntegerValue) value).getMaximumValue();
int min = ((WSIntegerValue) value).getMinimumValue();
if (newVal >= min && newVal <= max) {
((WSIntegerValue) value).setInteger(newVal);
} else {
throw new NumberFormatException(
"Value is not between accetable limits (min=" + min + ", max=" + max + ")");
}
} else {
throw new NumberFormatException("Can't convert OnOffType to " + value.getClass());
}
} else if (type instanceof OpenClosedType) {
((WSBooleanValue) value).setValue(type == OpenClosedType.OPEN ? true : false);
} else if (type instanceof DateTimeType) {
if (value instanceof WSDateValue) {
Calendar c = ((DateTimeType) type).getCalendar();
short year = (short) c.get(Calendar.YEAR);
byte month = (byte) (c.get(Calendar.MONTH) + 1);
byte day = (byte) c.get(Calendar.DAY_OF_MONTH);
((WSDateValue) value).setYear(year);
((WSDateValue) value).setMonth(month);
((WSDateValue) value).setDay(day);
} else if (value instanceof WSTimeValue) {
Calendar c = ((DateTimeType) type).getCalendar();
int hours = c.get(Calendar.HOUR_OF_DAY);
int minutes = c.get(Calendar.MINUTE);
int seconds = c.get(Calendar.SECOND);
((WSTimeValue) value).setHours(hours);
((WSTimeValue) value).setMinutes(minutes);
((WSTimeValue) value).setSeconds(seconds);
} else {
throw new NumberFormatException("Can't convert DateTimeItem to " + value.getClass());
}
} else if (type instanceof StringType) {
if (value instanceof WSEnumValue) {
boolean found = false;
for (IhcEnumValue item : enumValues) {
if (item.name.equals(type.toString())) {
((WSEnumValue) value).setEnumValueID(item.id);
((WSEnumValue) value).setEnumName(type.toString());
found = true;
break;
}
}
if (found == false) {
throw new NumberFormatException("Can't find enum value for string " + type.toString());
}
} else {
throw new NumberFormatException("Can't convert StringType to " + value.getClass());
}
} else if (type instanceof PercentType) {
if (value instanceof WSIntegerValue) {
int newVal = ((DecimalType) type).intValue();
int max = ((WSIntegerValue) value).getMaximumValue();
int min = ((WSIntegerValue) value).getMinimumValue();
if (newVal >= min && newVal <= max) {
((WSIntegerValue) value).setInteger(newVal);
} else {
throw new NumberFormatException(
"Value is not between accetable limits (min=" + min + ", max=" + max + ")");
}
} else {
throw new NumberFormatException("Can't convert PercentType to " + value.getClass());
}
} else if (type instanceof UpDownType) {
if (value instanceof WSBooleanValue) {
((WSBooleanValue) value).setValue(type == UpDownType.DOWN ? true : false);
} else if (value instanceof WSIntegerValue) {
int newVal = type == UpDownType.DOWN ? 100 : 0;
int max = ((WSIntegerValue) value).getMaximumValue();
int min = ((WSIntegerValue) value).getMinimumValue();
if (newVal >= min && newVal <= max) {
((WSIntegerValue) value).setInteger(newVal);
} else {
throw new NumberFormatException(
"Value is not between accetable limits (min=" + min + ", max=" + max + ")");
}
} else {
throw new NumberFormatException("Can't convert UpDownType to " + value.getClass());
}
} else {
throw new NumberFormatException("Can't convert " + type.getClass().toString());
}
return value;
}
}