/**
* 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.comfoair.handling;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openhab.binding.comfoair.datatypes.ComfoAirDataType;
import org.openhab.binding.comfoair.datatypes.DataTypeBoolean;
import org.openhab.binding.comfoair.datatypes.DataTypeMessage;
import org.openhab.binding.comfoair.datatypes.DataTypeNumber;
import org.openhab.binding.comfoair.datatypes.DataTypeTemperature;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Represents all valid commands which could be processed by this binding
*
* @author Holger Hees
* @since 1.3.0
*/
public enum ComfoAirCommandType {
ACTIVATE {
{
key = "activate";
data_type = DataTypeBoolean.class;
possible_values = new int[] { 0x03 };
change_command = 0x9b;
change_data_size = 1;
change_data_pos = 0;
read_command = 0x9c;
read_reply_command = 0x9c;
read_reply_data_pos = new int[] { 0 };
read_reply_data_bits = 0x03;
}
},
FAN_LEVEL {
{
key = "fan_level";
data_type = DataTypeNumber.class;
possible_values = new int[] { 0x01, 0x02, 0x03, 0x04 };
change_command = 0x99;
change_data_size = 1;
change_data_pos = 0;
change_affected = new String[] { "auto_mode", "incomming_fan", "outgoing_fan" };
read_command = 0xcd;
read_reply_command = 0xce;
read_reply_data_pos = new int[] { 8 };
}
},
INCOMMING_FAN {
{
key = "incomming_fan";
data_type = DataTypeNumber.class;
read_command = 0x0b;
read_reply_command = 0x0c;
read_reply_data_pos = new int[] { 0 };
}
},
OUTGOING_FAN {
{
key = "outgoing_fan";
data_type = DataTypeNumber.class;
read_command = 0x0b;
read_reply_command = 0x0c;
read_reply_data_pos = new int[] { 1 };
}
},
TARGET_TEMPERATUR {
{
key = "target_temperatur";
data_type = DataTypeTemperature.class;
change_command = 0xd3;
change_data_size = 1;
change_data_pos = 0;
read_command = 0xd1;
read_reply_command = 0xd2;
read_reply_data_pos = new int[] { 0 };
}
},
OUTDOOR_INCOMMING_TEMPERATUR {
{
key = "outdoor_incomming_temperatur";
data_type = DataTypeTemperature.class;
read_command = 0xd1;
read_reply_command = 0xd2;
read_reply_data_pos = new int[] { 1 };
}
},
OUTDOOR_OUTGOING_TEMPERATUR {
{
key = "outdoor_outgoing_temperatur";
data_type = DataTypeTemperature.class;
read_command = 0xd1;
read_reply_command = 0xd2;
read_reply_data_pos = new int[] { 4 };
}
},
INDOOR_INCOMMING_TEMPERATUR {
{
key = "indoor_incomming_temperatur";
data_type = DataTypeTemperature.class;
read_command = 0xd1;
read_reply_command = 0xd2;
read_reply_data_pos = new int[] { 2 };
}
},
INDOOR_OUTGOING_TEMPERATUR {
{
key = "indoor_outgoing_temperatur";
data_type = DataTypeTemperature.class;
read_command = 0xd1;
read_reply_command = 0xd2;
read_reply_data_pos = new int[] { 3 };
}
},
EWT_TEMPERATUR {
{
key = "ewt_temperatur";
data_type = DataTypeTemperature.class;
read_command = 0xd1;
read_reply_command = 0xd2;
read_reply_data_pos = new int[] { 6 };
}
},
EWT_TEMPERATUR_LOW {
{
key = "ewt_temperatur_low";
data_type = DataTypeNumber.class;
read_command = 0xeb;
read_reply_command = 0xec;
read_reply_data_pos = new int[] { 0 };
}
},
EWT_TEMPERATUR_HIGH {
{
key = "ewt_temperatur_high";
data_type = DataTypeNumber.class;
read_command = 0xeb;
read_reply_command = 0xec;
read_reply_data_pos = new int[] { 1 };
}
},
EWT_SPEED {
{
key = "ewt_speed";
data_type = DataTypeNumber.class;
read_command = 0xeb;
read_reply_command = 0xec;
read_reply_data_pos = new int[] { 2 };
}
},
EWT_MODE {
{
key = "ewt_mode";
data_type = DataTypeBoolean.class;
read_command = 0x37;
read_reply_command = 0x3c;
read_reply_data_pos = new int[] { 6 };
read_reply_data_bits = 0x80;
}
},
BYPASS_MODE {
{
key = "bypass_mode";
data_type = DataTypeBoolean.class;
read_command = 0x37;
read_reply_command = 0x3c;
read_reply_data_pos = new int[] { 9 };
read_reply_data_bits = 0x02;
}
},
FILTER_RUNNING {
{
key = "filter_running";
data_type = DataTypeNumber.class;
read_command = 0xdd;
read_reply_command = 0xde;
read_reply_data_pos = new int[] { 15, 16 };
}
},
FILTER_RESET {
{
key = "filter_reset";
data_type = DataTypeBoolean.class;
possible_values = new int[] { 0x01 };
change_command = 0xdb;
change_data_size = 4;
change_data_pos = 3;
change_affected = new String[] { "filter_error", "filter_error_intern", "filter_error_extern" };
}
},
FILTER_ERROR {
{
key = "filter_error";
data_type = DataTypeBoolean.class;
read_command = 0xd9;
read_reply_command = 0xda;
read_reply_data_pos = new int[] { 8 };
read_reply_data_bits = 0x01;
}
},
FILTER_ERROR_INTERN {
{
key = "filter_error_intern";
data_type = DataTypeBoolean.class;
read_command = 0x37;
read_reply_command = 0x3c;
read_reply_data_pos = new int[] { 1 };
read_reply_data_bits = 0x40;
}
},
FILTER_ERROR_EXTERN {
{
key = "filter_error_extern";
data_type = DataTypeBoolean.class;
read_command = 0x37;
read_reply_command = 0x3c;
read_reply_data_pos = new int[] { 1 };
read_reply_data_bits = 0x80;
}
},
ERROR_RESET {
{
key = "error_reset";
data_type = DataTypeBoolean.class;
possible_values = new int[] { 0x01 };
change_command = 0xdb;
change_data_size = 4;
change_data_pos = 0;
change_affected = new String[] { "error_message" };
}
},
ERROR_MESSAGE {
{
key = "error_message";
data_type = DataTypeMessage.class;
read_command = 0xd9;
read_reply_command = 0xda;
read_reply_data_pos = new int[] { 0, 1, 9, 13 };
}
};
Logger logger = LoggerFactory.getLogger(ComfoAirCommandType.class);
String key;
Class<? extends ComfoAirDataType> data_type;
/*
* Possible values
*/
int[] possible_values;
/*
* Cmd code to change properties on the comfoair.
*/
int change_command;
/*
* The size of the data block.
*/
int change_data_size;
/*
* The byte inside the data block which holds the crucial value.
*/
int change_data_pos;
/*
* Affected commands which should be refreshed after a successful change
* command call.
*/
String[] change_affected;
/*
* Command for reading properties.
*/
int read_command;
/*
* ACK Command which identifies the matching response.
*/
int read_reply_command;
/*
* The byte position inside the response data.
*/
int[] read_reply_data_pos;
/*
* Bit mask for boolean response properties to identify a true value.
*/
int read_reply_data_bits;
/**
* @return command key
*/
public String getKey() {
return key;
}
/**
* @return data type for this command key
*/
public ComfoAirDataType getDataType() {
try {
return data_type.newInstance();
} catch (Exception e) {
logger.error("Creating new DataType went wrong", e);
}
return null;
}
/**
* @return possible byte values
*/
public int[] getPossibleValues() {
return possible_values;
}
/**
* @return relevant byte position inside the response byte value array
*/
public int getChangeDataPos() {
return change_data_pos;
}
/**
* @return generate a byte value sequence for the response stream
*/
public int[] getChangeDataTemplate() {
int[] template = new int[change_data_size];
for (int i = 0; i < template.length; i++) {
template[i] = 0x00;
}
return template;
}
/**
* @return byte position inside the request byte value array
*/
public int[] getGetReplyDataPos() {
return read_reply_data_pos;
}
/**
* @return bit mask for the response byte value
*/
public int getGetReplyDataBits() {
return read_reply_data_bits;
}
/**
* Get a command to change properties on the comfoair.
*
* @param key
* command key
* @param value
* new state
* @return initialized ComfoAirCommand
*/
public static ComfoAirCommand getChangeCommand(String key, State value) {
ComfoAirCommandType commandType = ComfoAirCommandType.getCommandTypeByKey(key);
ComfoAirDataType dataType = commandType.getDataType();
int[] data = dataType.convertFromState(value, commandType);
return new ComfoAirCommand(key, commandType.change_command, null, data);
}
/**
* Get all commands which should be refreshed after a successful change
* command.
*
* @param key
* command key
* @param usedKeys
* @return ComfoAirCommand's which should be updated after a modifying
* ComfoAirCommand named by key
*/
public static Collection<ComfoAirCommand> getAffectedReadCommands(String key, Set<String> usedKeys) {
Map<Integer, ComfoAirCommand> commands = new HashMap<Integer, ComfoAirCommand>();
ComfoAirCommandType commandType = ComfoAirCommandType.getCommandTypeByKey(key);
if (commandType.read_reply_command != 0) {
Integer getCmd = commandType.read_command == 0 ? null : new Integer(commandType.read_command);
Integer replyCmd = new Integer(commandType.read_reply_command);
ComfoAirCommand command = new ComfoAirCommand(key, getCmd, replyCmd, null);
commands.put(command.getReplyCmd(), command);
}
for (String affectedKey : commandType.change_affected) {
// refresh affected event keys only when they are used
if (!usedKeys.contains(affectedKey)) {
continue;
}
ComfoAirCommandType affectedCommandType = ComfoAirCommandType.getCommandTypeByKey(affectedKey);
Integer getCmd = affectedCommandType.read_command == 0 ? null
: new Integer(affectedCommandType.read_command);
Integer replyCmd = new Integer(affectedCommandType.read_reply_command);
ComfoAirCommand command = commands.get(replyCmd);
if (command == null) {
command = new ComfoAirCommand(affectedKey, getCmd, replyCmd, null);
commands.put(command.getReplyCmd(), command);
} else {
command.addKey(affectedKey);
}
}
return commands.values();
}
/**
* Get all commands which receive informations to update items.
*
* @return all ComfoAirCommand's identified by keys
*/
public static Collection<ComfoAirCommand> getReadCommandsByEventTypes(List<String> keys) {
Map<Integer, ComfoAirCommand> commands = new HashMap<Integer, ComfoAirCommand>();
for (ComfoAirCommandType entry : values()) {
if (!keys.contains(entry.key)) {
continue;
}
if (entry.read_reply_command == 0) {
continue;
}
Integer getCmd = entry.read_command == 0 ? null : new Integer(entry.read_command);
Integer replyCmd = new Integer(entry.read_reply_command);
ComfoAirCommand command = commands.get(replyCmd);
if (command == null) {
command = new ComfoAirCommand(entry.key, getCmd, replyCmd, null);
commands.put(command.getReplyCmd(), command);
} else {
command.addKey(entry.key);
}
}
return commands.values();
}
/**
* Get commandtypes which matches the replyCmd.
*
* @param replyCmd
* reply command byte value
* @return ComfoAirCommandType identified by replyCmd
*/
public static List<ComfoAirCommandType> getCommandTypesByReplyCmd(int replyCmd) {
List<ComfoAirCommandType> commands = new ArrayList<ComfoAirCommandType>();
for (ComfoAirCommandType entry : values()) {
if (entry.read_reply_command != replyCmd) {
continue;
}
commands.add(entry);
}
return commands;
}
/**
* Get a specific command.
*
* @param key
* command key
* @return ComfoAirCommandType identified by key
*/
private static ComfoAirCommandType getCommandTypeByKey(String key) {
for (ComfoAirCommandType entry : values()) {
if (entry.key.equals(key)) {
return entry;
}
}
return null;
}
}