/**
* 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.digitalstrom.internal.client.entity.impl;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.openhab.binding.digitalstrom.internal.client.constants.DeviceConstants;
import org.openhab.binding.digitalstrom.internal.client.constants.JSONApiResponseKeysEnum;
import org.openhab.binding.digitalstrom.internal.client.constants.OutputModeEnum;
import org.openhab.binding.digitalstrom.internal.client.entity.DSID;
import org.openhab.binding.digitalstrom.internal.client.entity.Device;
import org.openhab.binding.digitalstrom.internal.client.entity.DeviceSceneSpec;
import org.openhab.binding.digitalstrom.internal.client.events.DeviceListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Alexander Betker
* @author Alex Maier
* @since 1.3.0
*/
public class JSONDeviceImpl implements Device {
private static final Logger logger = LoggerFactory.getLogger(JSONDeviceImpl.class);
private DSID dsid = null;
private String name = null;
private int zoneId = 0;
private boolean isPresent = false;
private boolean isOn = false;
private OutputModeEnum outputMode = null;
private int outputValue = 0;
private int maxOutputValue = DeviceConstants.DEFAULT_MAX_OUTPUTVALUE;
private int minOutputValue = 0;
private int slatPosition = 0;
private int maxSlatPosition = DeviceConstants.MAX_SLAT_POSITION;
private int minSlatPosition = DeviceConstants.MIN_SLAT_POSITION;
private int powerConsumption = 0;
private int energyMeterValue = 0;
private int electricMeterValue = 0;
private int temperatureSensorValue = 0;
private int humiditySensorValue = 0;
private List<Short> groupList = new LinkedList<Short>();
private List<DeviceListener> deviceListenerList = Collections.synchronizedList(new LinkedList<DeviceListener>());
private Map<Short, DeviceSceneSpec> sceneConfigMap = Collections
.synchronizedMap(new HashMap<Short, DeviceSceneSpec>());
private Map<Short, Short> sceneOutputMap = Collections.synchronizedMap(new HashMap<Short, Short>());
public JSONDeviceImpl(JSONObject object) {
if (object.get(JSONApiResponseKeysEnum.DEVICE_NAME.getKey()) != null) {
this.name = object.get(JSONApiResponseKeysEnum.DEVICE_NAME.getKey()).toString();
}
if (object.get(JSONApiResponseKeysEnum.DEVICE_ID.getKey()) != null) {
this.dsid = new DSID(object.get(JSONApiResponseKeysEnum.DEVICE_ID.getKey()).toString());
} else if (object.get(JSONApiResponseKeysEnum.DEVICE_ID_QUERY.getKey()) != null) {
this.dsid = new DSID(object.get(JSONApiResponseKeysEnum.DEVICE_ID_QUERY.getKey()).toString());
}
if (object.get(JSONApiResponseKeysEnum.DEVICE_ON.getKey()) != null) {
this.isOn = object.get(JSONApiResponseKeysEnum.DEVICE_ON.getKey()).toString().equals("true");
}
if (object.get(JSONApiResponseKeysEnum.DEVICE_IS_PRESENT.getKey()) != null) {
this.isPresent = object.get(JSONApiResponseKeysEnum.DEVICE_IS_PRESENT.getKey()).toString().equals("true");
} else if (object.get(JSONApiResponseKeysEnum.DEVICE_IS_PRESENT_QUERY.getKey()) != null) {
this.isPresent = object.get(JSONApiResponseKeysEnum.DEVICE_IS_PRESENT_QUERY.getKey()).toString()
.equals("true");
}
String zoneStr = null;
if (object.get(JSONApiResponseKeysEnum.DEVICE_ZONE_ID.getKey()) != null) {
zoneStr = object.get(JSONApiResponseKeysEnum.DEVICE_ZONE_ID.getKey()).toString();
} else if (object.get(JSONApiResponseKeysEnum.DEVICE_ZONE_ID_QUERY.getKey()) != null) {
zoneStr = object.get(JSONApiResponseKeysEnum.DEVICE_ZONE_ID_QUERY.getKey()).toString();
}
if (zoneStr != null) {
try {
this.zoneId = Integer.parseInt(zoneStr);
} catch (java.lang.NumberFormatException e) {
logger.error("NumberFormatException by parsing zoneId: " + zoneStr);
}
}
if (object.get(JSONApiResponseKeysEnum.DEVICE_GROUPS.getKey()) instanceof JSONArray) {
JSONArray array = (JSONArray) object.get(JSONApiResponseKeysEnum.DEVICE_GROUPS.getKey());
for (int i = 0; i < array.size(); i++) {
if (array.get(i) != null) {
String value = array.get(i).toString();
short tmp = -1;
try {
tmp = Short.parseShort(value);
} catch (java.lang.NumberFormatException e) {
logger.error("NumberFormatException by parsing groups: " + value);
}
if (tmp != -1) {
this.groupList.add(tmp);
}
}
}
}
if (object.get(JSONApiResponseKeysEnum.DEVICE_OUTPUT_MODE.getKey()) != null) {
int tmp = -1;
try {
tmp = Integer.parseInt(object.get(JSONApiResponseKeysEnum.DEVICE_OUTPUT_MODE.getKey()).toString());
} catch (java.lang.NumberFormatException e) {
logger.error("NumberFormatException by parsing outputmode: "
+ object.get(JSONApiResponseKeysEnum.DEVICE_OUTPUT_MODE.getKey()).toString());
}
if (tmp != -1) {
if (OutputModeEnum.containsMode(tmp)) {
outputMode = OutputModeEnum.getMode(tmp);
}
}
}
init();
}
private void init() {
if (groupList.contains((short) 1)) {
maxOutputValue = DeviceConstants.MAX_OUTPUT_VALUE_LIGHT;
if (this.isDimmable()) {
minOutputValue = DeviceConstants.MIN_DIMM_VALUE;
}
} else {
maxOutputValue = DeviceConstants.DEFAULT_MAX_OUTPUTVALUE;
minOutputValue = 0;
}
if (isOn) {
setOutputValue(DeviceConstants.DEFAULT_MAX_OUTPUTVALUE);
}
}
@Override
public DSID getDSID() {
return dsid;
}
@Override
public String getName() {
return name;
}
@Override
public synchronized void setName(String name) {
this.name = name;
}
@Override
public List<Short> getGroups() {
return groupList;
}
@Override
public int getZoneId() {
return zoneId;
}
@Override
public boolean isPresent() {
return isPresent;
}
@Override
public boolean isOn() {
return isOn;
}
@Override
public void setIsOn(boolean flag) {
// if device is off set power consumption and energy meter value to 0
if (flag == false) {
this.powerConsumption = 0;
this.energyMeterValue = 0;
}
this.isOn = flag;
}
@Override
public synchronized void setOutputValue(int value) {
if (value <= 0) {
outputValue = 0;
setIsOn(false);
} else if (value > maxOutputValue) {
outputValue = maxOutputValue;
setIsOn(true);
} else {
outputValue = value;
setIsOn(true);
}
notifyDeviceListener(dsid.getValue());
}
@Override
public boolean isDimmable() {
if (outputMode == null) {
return false;
}
return outputMode.equals(OutputModeEnum.DIMMED) || outputMode.equals(OutputModeEnum.DIMMED_2);
}
@Override
public OutputModeEnum getOutputMode() {
return outputMode;
}
@Override
public synchronized void increase() {
if (isDimmable()) {
if (outputValue == maxOutputValue) {
return;
}
if ((outputValue + getDimmStep()) > maxOutputValue) {
outputValue = maxOutputValue;
} else {
outputValue += getDimmStep();
}
setIsOn(true);
notifyDeviceListener(this.dsid.getValue());
}
}
@Override
public synchronized void decrease() {
if (isDimmable()) {
if (outputValue == minOutputValue) {
if (outputValue == 0) {
setIsOn(false);
}
return;
}
if ((outputValue - getDimmStep()) <= minOutputValue) {
if (isOn) {
System.out.println("Device isOn");
outputValue = minOutputValue;
}
if (minOutputValue == 0) {
setIsOn(false);
} else {
if (outputValue != 0) {
setIsOn(true);
}
}
} else {
outputValue -= getDimmStep();
setIsOn(true);
}
notifyDeviceListener(this.dsid.getValue());
}
}
@Override
public int getOutputValue() {
return outputValue;
}
@Override
public int getMaxOutPutValue() {
return maxOutputValue;
}
@Override
public boolean isRollershutter() {
if (outputMode == null) {
return false;
}
return outputMode.equals(OutputModeEnum.UP_DOWN) || outputMode.equals(OutputModeEnum.SLAT);
}
@Override
public int getSlatPosition() {
return slatPosition;
}
@Override
public synchronized void setSlatPosition(int position) {
if (position < minSlatPosition) {
slatPosition = minSlatPosition;
} else if (position > this.maxSlatPosition) {
slatPosition = this.maxSlatPosition;
} else {
this.slatPosition = position;
}
notifyDeviceListener(this.dsid.getValue());
}
@Override
public int getTemperatureSensorValue() {
return temperatureSensorValue;
}
@Override
public synchronized void setTemperatureSensorValue(int sensorValue) {
if (sensorValue < 0) {
this.temperatureSensorValue = 0;
} else {
this.temperatureSensorValue = sensorValue;
}
notifyDeviceListener(this.dsid.getValue());
}
@Override
public int getHumiditySensorValue() {
return humiditySensorValue;
}
@Override
public synchronized void setHumiditySensorValue(int sensorValue) {
if (sensorValue < 0) {
this.humiditySensorValue = 0;
} else {
this.humiditySensorValue = sensorValue;
}
notifyDeviceListener(this.dsid.getValue());
}
@Override
public int getPowerConsumption() {
return powerConsumption;
}
@Override
public synchronized void setPowerConsumption(int powerConspumtion) {
if (powerConspumtion < 0) {
this.powerConsumption = 0;
} else {
this.powerConsumption = powerConspumtion;
}
notifyDeviceListener(this.dsid.getValue());
}
@Override
public int getEnergyMeterValue() {
return energyMeterValue;
}
@Override
public synchronized void setEnergyMeterValue(int value) {
if (value < 0) {
energyMeterValue = 0;
} else {
energyMeterValue = value;
}
notifyDeviceListener(this.dsid.getValue());
}
@Override
public void addDeviceListener(DeviceListener listener) {
if (listener != null) {
if (!this.deviceListenerList.contains(listener)) {
this.deviceListenerList.add(listener);
}
}
}
@Override
public void removeDeviceListener(DeviceListener listener) {
if (listener != null) {
if (this.deviceListenerList.contains(listener)) {
this.deviceListenerList.remove(listener);
}
}
}
@Override
public void notifyDeviceListener(String dsid) {
for (DeviceListener listener : this.deviceListenerList) {
listener.deviceUpdated(dsid);
}
}
@Override
public int getElectricMeterValue() {
return electricMeterValue;
}
@Override
public synchronized void setElectricMeterValue(int electricMeterValue) {
if (electricMeterValue < 0) {
this.electricMeterValue = 0;
} else {
this.electricMeterValue = electricMeterValue;
}
notifyDeviceListener(this.dsid.getValue());
}
private short getDimmStep() {
if (isDimmable()) {
return DeviceConstants.DIMM_STEP_LIGHT;
} else if (isRollershutter()) {
return DeviceConstants.MOVE_STEP_ROLLERSHUTTER;
} else {
return DeviceConstants.DEFAULT_MOVE_STEP;
}
}
@Override
public int getMaxSlatPosition() {
return maxSlatPosition;
}
@Override
public int getMinSlatPosition() {
return minSlatPosition;
}
@Override
public short getSceneOutputValue(short sceneId) {
synchronized (sceneOutputMap) {
if (sceneOutputMap.containsKey(sceneId)) {
return sceneOutputMap.get(sceneId);
}
}
return -1;
}
@Override
public void setSceneOutputValue(short sceneId, short value) {
synchronized (sceneOutputMap) {
sceneOutputMap.put(sceneId, value);
}
}
@Override
public void addSceneConfig(short sceneId, DeviceSceneSpec sceneSpec) {
if (sceneSpec != null) {
synchronized (sceneConfigMap) {
sceneConfigMap.put(sceneId, sceneSpec);
}
}
}
@Override
public boolean doIgnoreScene(short sceneId) {
synchronized (sceneConfigMap) {
if (this.sceneConfigMap.containsKey(sceneId)) {
return this.sceneConfigMap.get(sceneId).isDontCare();
}
}
return false;
}
@Override
public boolean containsSceneConfig(short sceneId) {
synchronized (sceneConfigMap) {
return sceneConfigMap.containsKey(sceneId);
}
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Device) {
Device device = (Device) obj;
return device.getDSID().equals(this.getDSID());
}
return false;
}
}