/**
* Copyright (c) 2010-2016, 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.upb.internal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map.Entry;
import javax.xml.bind.DatatypeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Model for a message sent or received from a UPB modem.
*
* @author cvanorman
* @since 1.9.0
*/
public class UPBMessage {
/**
* An enum of possible commands.
*
* @author cvanorman
*
*/
public enum Command {
ACTIVATE,
DEACTIVATE,
GOTO,
START_FADE,
STOP_FADE,
BLINK,
REPORT_STATE,
STORE_STATE,
DEVICE_STATE,
NONE;
/**
* Gets the protocol byte code for this Command.
*
* @return
*/
public byte toByte() {
for (Entry<Integer, Command> e : commandMap.entrySet()) {
if (e.getValue() == this) {
return e.getKey().byteValue();
}
}
return 0;
}
/**
* Converts a byte value into a Command.
*
* @param value
* the byte value.
* @return the Command that is represented by the given byte value.
*/
public static Command valueOf(byte value) {
return commandMap.get(value);
}
}
/**
* An enum of possible modem response types.
*
* @author cvanorman
*
*/
public enum Type {
ACCEPT,
BUSY,
ERROR,
ACK,
NAK,
MESSAGE_REPORT,
NONE;
}
private static final Logger logger = LoggerFactory.getLogger(UPBMessage.class);
private static HashMap<Integer, Command> commandMap = new HashMap<>();
static {
commandMap.put(0x20, Command.ACTIVATE);
commandMap.put(0x21, Command.DEACTIVATE);
commandMap.put(0x22, Command.GOTO);
commandMap.put(0x23, Command.START_FADE);
commandMap.put(0x24, Command.STOP_FADE);
commandMap.put(0x25, Command.BLINK);
commandMap.put(0x30, Command.REPORT_STATE);
commandMap.put(0x31, Command.STORE_STATE);
commandMap.put(0x86, Command.DEVICE_STATE);
}
private static HashMap<String, Type> typeMap = new HashMap<>();
static {
typeMap.put("PA", Type.ACCEPT);
typeMap.put("PB", Type.BUSY);
typeMap.put("PE", Type.ERROR);
typeMap.put("PK", Type.ACK);
typeMap.put("PN", Type.NAK);
typeMap.put("PU", Type.MESSAGE_REPORT);
}
/**
* Converts a hex string into a {@link UPBMessage}.
*
* @param commandString
* the string as returned by the modem.
* @return a new UPBMessage.
*/
public static UPBMessage fromString(String commandString) {
UPBMessage command = new UPBMessage();
String typeString = commandString.substring(0, 2);
Type type = Type.NONE;
if (typeMap.containsKey(typeString)) {
type = typeMap.get(typeString);
}
command.setType(type);
try {
if (commandString.length() > 2) {
byte[] data = DatatypeConverter.parseHexBinary(commandString.substring(2));
command.getControlWord().setBytes(data[1], data[0]);
int index = 2;
command.setNetwork(data[index++]);
command.setDestination(data[index++]);
command.setSource(data[index++]);
int commandCode = data[index++] & 0xFF;
if (commandMap.containsKey(commandCode)) {
command.setCommand(commandMap.get(commandCode));
} else {
command.setCommand(Command.NONE);
}
if (index < data.length - 1) {
command.setArguments(Arrays.copyOfRange(data, index, data.length - 1));
}
}
} catch (Exception e) {
logger.error("Attempted to parse invalid message: {}", commandString, e);
}
return command;
}
private Type type;
private ControlWord controlWord = new ControlWord();
private byte network;
private byte destination;
private byte source;
private Command command = Command.NONE;
private byte[] arguments;
/**
* @return the type
*/
public Type getType() {
return type;
}
/**
* @param type
* the type to set
*/
public void setType(Type type) {
this.type = type;
}
/**
* @return the controlWord
*/
public ControlWord getControlWord() {
return controlWord;
}
/**
* @param controlWord
* the controlWord to set
*/
public void setControlWord(ControlWord controlWord) {
this.controlWord = controlWord;
}
/**
* @return the network
*/
public byte getNetwork() {
return network;
}
/**
* @param network
* the network to set
*/
public void setNetwork(byte network) {
this.network = network;
}
/**
* @return the destination
*/
public byte getDestination() {
return destination;
}
/**
* @param destination
* the destination to set
*/
public void setDestination(byte destination) {
this.destination = destination;
}
/**
* @return the source
*/
public byte getSource() {
return source;
}
/**
* @param source
* the source to set
*/
public void setSource(byte source) {
this.source = source;
}
/**
* @return the command
*/
public Command getCommand() {
return command;
}
/**
* @param command
* the command to set
*/
public void setCommand(Command command) {
this.command = command;
}
/**
* @return the arguments
*/
public byte[] getArguments() {
return arguments;
}
/**
* @param arguments
* the arguments to set
*/
public void setArguments(byte[] arguments) {
this.arguments = arguments;
}
}