org.openhab.binding.irtrans.internal.IRtransBinding.java Source code

Java tutorial

Introduction

Here is the source code for org.openhab.binding.irtrans.internal.IRtransBinding.java

Source

/**
 * Copyright (c) 2010-2015, 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.irtrans.internal;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.openhab.binding.irtrans.IRtransBindingProvider;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.openhab.binding.tcp.AbstractSocketChannelBinding;
import org.openhab.binding.tcp.Direction;

/**
 * 
 * Main binding class for the IRtrans binding, based on the AbstractSocketChannelBinding class which also serves
 * as a basis for the "regular" TCP binding.
 * 
 * @author Karel Goderis
 * @since 1.4.0
 *
 */
public class IRtransBinding extends AbstractSocketChannelBinding<IRtransBindingProvider> implements ManagedService {

    @SuppressWarnings("restriction")
    static private final Logger logger = LoggerFactory.getLogger(IRtransBinding.class);

    // Data structure to store the infrared commands that are 'loaded' from the configuration files
    // command loading from pre-defined configuration files is not supported (anymore), but the code is maintained
    // in case this functionality is re-added in the future
    final static protected HashSet<IrCommand> irCommands = new HashSet<IrCommand>();

    // time to wait for a reply, in milliseconds
    private int timeOut = 1000;

    /**
     * Structure to store IRTrans infrared commands. See IRTrans documentation for a detailed
     * description of the structure of the infrared commands (or wikipedia for infrared in general)
     *
     */
    private class IrCommand {

        /**
         * 
         * Each infrared command is in essence a sequence of characters/pointers that refer
         * to pulse/pause timing pairs. So, in order to build an infrared command one has to 
         * collate the pulse/pause timings as defined by the sequence
         * 
         * PulsePair is a small datastructure to capture each pulse/pair timing pair
         *
         */
        private class PulsePair {
            public int Pulse;
            public int Pause;
        }

        public String remote;
        public String command;
        public String sequence;
        public ArrayList<PulsePair> pulsePairs;
        public int numberOfRepeats;
        public int frequency;
        public int frameLength;
        public int pause;
        public boolean startBit;
        public boolean repeatStartBit;
        public boolean noTog;
        public boolean rc5;
        public boolean rc6;

        /**
         * Matches two IrCommands
         * Commands match if they have the same remote and the same command
         * 
         * @param anotherCommand
         *            the another command
         * @return true, if successful
         */
        public boolean matches(IrCommand anotherCommand) {
            return (matchRemote(anotherCommand) && matchCommand(anotherCommand));
        }

        /**
         * Match remote fields of two IrCommands
         * In everything we do in the IRtrans binding, the "*" stands for a wilcard
         * character and will match anything
         * 
         * @param S
         *            the s
         * @return true, if successful
         */
        private boolean matchRemote(IrCommand S) {
            if (remote.equals("*") || S.remote.equals("*")) {
                return true;
            } else {
                if (S.remote.equals(remote)) {
                    return true;
                } else {
                    return false;
                }
            }
        }

        /**
         * Match command fields of two IrCommands
         * 
         * @param S
         *            the s
         * @return true, if successful
         */
        private boolean matchCommand(IrCommand S) {
            if (command.equals("*") || S.command.equals("*")) {
                return true;
            } else {
                if (S.command.equals(command)) {
                    return true;
                } else {
                    return false;
                }
            }
        }

        /**
         * Convert/Parse the IRCommand into a ByteBuffer that is compatible with the IRTrans devices
         * 
         * @return the byte buffer
         */
        @SuppressWarnings("restriction")
        public ByteBuffer toByteBuffer() {

            ByteBuffer byteBuffer = ByteBuffer.allocate(44 + 210 + 1);

            // skip first byte for length - we will fill it in at the end
            byteBuffer.position(1);

            //Checksum - 1 byte - not used in the ethernet version of the device
            byteBuffer.put((byte) 0);

            //Command - 1 byte - not used
            byteBuffer.put((byte) 0);

            // Address - 1 byte - not used
            byteBuffer.put((byte) 0);

            //Mask - 2 bytes - not used
            byteBuffer.putShort((short) 0);

            //Number of pulse pairs - 1 byte

            try {
                byte[] byteSequence = sequence.getBytes("ASCII");
                byteBuffer.put((byte) (byteSequence.length));
            } catch (UnsupportedEncodingException e) {
                logger.debug("An exception occurred while encoding a bytebuffer");
            }

            //Frequency - 1 byte
            byteBuffer.put((byte) frequency);

            //Mode / Flags - 1 byte
            byte modeFlags = 0;
            if (startBit)
                modeFlags = (byte) (modeFlags | 1);
            if (repeatStartBit)
                modeFlags = (byte) (modeFlags | 2);
            if (rc5)
                modeFlags = (byte) (modeFlags | 4);
            if (rc6)
                modeFlags = (byte) (modeFlags | 8);
            byteBuffer.put(modeFlags);

            //Pause timings - 8 Shorts = 16 bytes
            for (int i = 0; i < pulsePairs.size(); i++) {
                byteBuffer.putShort((short) Math.round(pulsePairs.get(i).Pause / 8));
            }
            for (int i = pulsePairs.size(); i <= 7; i++) {
                byteBuffer.putShort((short) 0);
            }

            //Pulse timings - 8 Shorts = 16 bytes
            for (int i = 0; i < pulsePairs.size(); i++) {
                byteBuffer.putShort((short) Math.round(pulsePairs.get(i).Pulse / 8));
            }
            for (int i = pulsePairs.size(); i <= 7; i++) {
                byteBuffer.putShort((short) 0);
            }

            // Time Counts - 1 Byte
            byteBuffer.put((byte) pulsePairs.size());

            //Repeats - 1 Byte
            byte repeat = (byte) 0;
            repeat = (byte) numberOfRepeats;
            if (frameLength > 0) {
                repeat = (byte) (repeat | 128);
            }
            byteBuffer.put(repeat);

            // Repeat Pause or Frame Length - 1 byte
            if ((repeat & 128) == 128) {
                byteBuffer.put((byte) frameLength);
            } else {
                byteBuffer.put((byte) pause);
            }

            // IR pulse sequence
            try {
                byteBuffer.put(sequence.getBytes("ASCII"));
            } catch (UnsupportedEncodingException e) {
            }

            // Add <CR> (ASCII 13) at the end of the sequence
            byteBuffer.put((byte) ((char) 13));

            // set the length of the byte sequence
            byteBuffer.flip();
            byteBuffer.position(0);
            byteBuffer.put((byte) (byteBuffer.limit() - 1));
            byteBuffer.position(0);

            return byteBuffer;

        }

        /**
         * Convert the the infrared command to a Hexadecimal notation/string that can be 
         * interpreted by the IRTrans device
         * 
         * Convert the first 44 bytes to hex notation, then copy the remainder 
         * (= IR command piece) as ASCII string 
         * 
         * @return the byte buffer in Hex format
         */
        public ByteBuffer toHEXByteBuffer() {

            byte hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

            ByteBuffer byteBuffer = toByteBuffer();
            byte[] toConvert = new byte[byteBuffer.limit()];
            byteBuffer.get(toConvert, 0, byteBuffer.limit());

            byte[] converted = new byte[toConvert.length * 2];

            for (int k = 0; k < toConvert.length - 1; k++) {
                converted[2 * k] = hexDigit[(toConvert[k] >> 4) & 0x0f];
                converted[2 * k + 1] = hexDigit[toConvert[k] & 0x0f];

            }

            ByteBuffer convertedBuffer = ByteBuffer.allocate(converted.length);
            convertedBuffer.put(converted);
            convertedBuffer.flip();

            return convertedBuffer;

        }

        /**
         * Convert 'sequence' bit of the IRTrans compatible byte buffer to a Hexidecimal string
         * 
         * @return the string
         */
        public String sequenceToHEXString() {
            byte[] byteArray = toHEXByteArray();
            return new String(byteArray, 88, byteArray.length - 88 - 2);
        }

        /**
         * Convert the IRTrans compatible byte buffer to a string
         * 
         * @return the string
         */
        public String toHEXString() {
            return new String(toHEXByteArray());
        }

        /**
         * Convert the IRTrans compatible byte buffer to a byte array.
         * 
         * @return the byte[]
         */
        public byte[] toHEXByteArray() {
            return toHEXByteBuffer().array();
        }

    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings({ "rawtypes", "restriction" })
    public void updated(Dictionary config) throws ConfigurationException {

        super.updated(config);

        if (config != null) {

            String timeOutString = (String) config.get("timeout");
            if (StringUtils.isNotBlank(timeOutString)) {
                timeOut = Integer.parseInt((timeOutString));
            } else {
                logger.info(
                        "The maximum time out for blocking write operations will be set to the default vaulue of {}",
                        timeOut);
            }

        }

        // Prevent users from doing funny stuff with this binding
        useAddressMask = false;
        itemShareChannels = true;
        bindingShareChannels = true;
        directionsShareChannels = false;
        maximumBufferSize = 1024;

        setProperlyConfigured(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean internalReceiveChanneledCommand(String itemName, Command command, Channel sChannel,
            String commandAsString) {

        IRtransBindingProvider provider = findFirstMatchingBindingProvider(itemName);

        String remoteName = null;
        String irCommandName = null;

        if (command != null && provider != null) {

            if (command instanceof DecimalType) {
                remoteName = StringUtils.substringBefore(commandAsString, ",");
                irCommandName = StringUtils.substringAfter(commandAsString, ",");

                IrCommand firstCommand = new IrCommand();
                firstCommand.remote = remoteName;
                firstCommand.command = irCommandName;
                IrCommand secondCommand = new IrCommand();
                secondCommand.remote = provider.getRemote(itemName, command);
                secondCommand.command = provider.getIrCommand(itemName, command);

                if (!firstCommand.matches(secondCommand)) {
                    remoteName = null;
                    irCommandName = null;
                }
            } else {
                remoteName = provider.getRemote(itemName, command);
                irCommandName = provider.getIrCommand(itemName, command);
            }
        }

        if (remoteName != null && irCommandName != null) {

            Leds led = provider.getLed(itemName, command);

            IrCommand theCommand = new IrCommand();
            theCommand.remote = remoteName;
            theCommand.command = irCommandName;

            // construct the string we need to send to the IRtrans device
            String output = packIRDBCommand(led, theCommand);

            ByteBuffer outputBuffer = ByteBuffer.allocate(output.getBytes().length);
            ByteBuffer response = null;
            try {
                outputBuffer.put(output.getBytes("ASCII"));
                response = writeBuffer(outputBuffer, sChannel, true, timeOut);
            } catch (UnsupportedEncodingException e) {
                logger.error("An exception occurred while encoding an infrared command: {}", e.getMessage());
            }

            if (response != null) {
                String message = stripByteCount(response);
                if (message != null) {
                    if (message.contains("RESULT OK")) {

                        List<Class<? extends State>> stateTypeList = provider.getAcceptedDataTypes(itemName,
                                command);
                        State newState = createStateFromString(stateTypeList, commandAsString);

                        if (newState != null) {
                            eventPublisher.postUpdate(itemName, newState);
                        } else {
                            logger.warn("Can not parse " + commandAsString + " to match command {} on item {}  ",
                                    command, itemName);
                        }

                    } else {
                        logger.warn("Received an unexecpted response {}",
                                StringUtils.substringAfter(message, "RESULT "));
                    }
                }
            } else {
                logger.warn("Did not receive an answer from the IRtrans device - Parsing is skipped");
            }
        } else {
            logger.warn("Invalid command {} for Item {} - Transmission is skipped", commandAsString, itemName);
        }

        // we will always return false, because the irBinding itself will postUpdate new values, the underlying tcp binding should
        // not deal with that anymore.
        return false;

    }

    /**
     * Main method to parse ASCII string received from the IR Transceiver.
     * 
     * @param qualifiedItems
     *            the qualified items, e.g. only those items that have the host:port combination
     *            in its binding configuration string will "receive" the ASCII string from the 
     *            IRTrans device with host:port 
     * @param byteBuffer
     *            the byte buffer
     */
    @Override
    protected void parseBuffer(String itemName, Command aCommand, Direction theDirection, ByteBuffer byteBuffer) {

        String message = stripByteCount(byteBuffer);

        if (message != null) {

            // IRTrans devices return "RESULT OK" when it succeeds to emit an infrared sequence
            if (message.contains("RESULT OK")) {
                parseOKMessage(itemName, message);
            }

            // IRTrans devices return a string starting with RCV_HEX each time it captures an
            // infrared sequence from a remote control
            if (message.contains("RCV_HEX")) {
                parseHexMessage(itemName, message, aCommand);
            }

            // IRTrans devices return a string starting with RCV_COM each time it captures an
            // infrared sequence from a remote control that is stored in the device's internal dB
            if (message.contains("RCV_COM")) {
                parseIRDBMessage(itemName, message, aCommand);
            }
        } else {
            logger.warn("Received some non-compliant garbage ({})- Parsing is skipped", byteBuffer.toString());
        }

    }

    /**
     * Parses the rcv hex.
     * 
     * @param itemName
     *            the qualified items
     * @param message
     *            the message
     * @param ohCommand
     *            the openHAB command
     */
    protected void parseHexMessage(String itemName, String message, Command ohCommand) {

        Pattern HEX_PATTERN = Pattern.compile("RCV_HEX (.*)");
        Matcher matcher = HEX_PATTERN.matcher(message);

        if (matcher.matches()) {
            String command = matcher.group(1);
            IrCommand theCommand = getIrCommand(command);

            if (theCommand != null) {
                parseDecodedCommand(itemName, theCommand, ohCommand);
            } else {
                logger.error("{} does not match any know IRtrans command", command);
            }

        } else {
            logger.error("{} does not match the IRtrans message formet ({})", message, matcher.pattern());
        }
    }

    protected void parseIRDBMessage(String itemName, String message, Command ohCommand) {

        Pattern IRDB_PATTERN = Pattern.compile("RCV_COM (.*),(.*),(.*),(.*)");
        Matcher matcher = IRDB_PATTERN.matcher(message);

        if (matcher.matches()) {

            IrCommand theCommand = new IrCommand();
            theCommand.remote = matcher.group(1);
            theCommand.command = matcher.group(2);

            parseDecodedCommand(itemName, theCommand, ohCommand);

        } else {
            logger.error("{} does not match the IRDB IRtrans message format ({})", message, matcher.pattern());
        }
    }

    protected void parseDecodedCommand(String itemName, IrCommand theCommand, Command ohCommand) {

        if (theCommand != null) {
            //traverse the providers, for each provider, check each binding if it matches theCommand
            for (IRtransBindingProvider provider : providers) {
                if (provider.providesBindingFor(itemName)) {
                    List<org.openhab.core.types.Command> commands = provider.getAllCommands(itemName);

                    // first check if commands are defined, and that they have the correct DirectionType
                    Iterator<org.openhab.core.types.Command> listIterator = commands.listIterator();
                    while (listIterator.hasNext()) {
                        org.openhab.core.types.Command aCommand = listIterator.next();
                        IrCommand providerCommand = new IrCommand();
                        providerCommand.remote = provider.getRemote(itemName, aCommand);
                        providerCommand.command = provider.getIrCommand(itemName, aCommand);

                        if (aCommand == ohCommand) {
                            if (providerCommand.matches(theCommand)) {

                                List<Class<? extends State>> stateTypeList = provider.getAcceptedDataTypes(itemName,
                                        aCommand);
                                State newState = null;

                                if (aCommand instanceof DecimalType) {
                                    newState = createStateFromString(stateTypeList,
                                            theCommand.remote + "," + theCommand.command);
                                } else {
                                    newState = createStateFromString(stateTypeList, aCommand.toString());
                                }

                                if (newState != null) {
                                    eventPublisher.postUpdate(itemName, newState);
                                } else {
                                    logger.warn("Can not create an Item State to match command {} on item {}  ",
                                            aCommand, itemName);
                                }
                            } else {
                                logger.info(
                                        "The IRtrans command '{},{}' does not match the command '{}' of the binding configuration for item '{}'",
                                        new Object[] { theCommand.remote, theCommand.command, ohCommand,
                                                itemName });
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Parses the result send.
     * 
     * @param itemName
     *            the qualified items
     * @param message
     *            the message
     */
    protected void parseOKMessage(String itemName, String message) {
        // nothing interesting to do here
    }

    /**
     * "Pack" the infrared command so that it can be sent to the IRTrans device
     * 
     * @param led
     *            the led
     * @param theCommand
     *            the the command
     * @return a string which is the full command to be sent to the device
     */
    protected String packHexCommand(Leds led, IrCommand theCommand) {
        String output = new String();

        output = "Asndhex ";
        output += "L";
        switch (led) {
        case ALL:
            output += "B";
            break;
        case ONE:
            output += "1";
            break;
        case TWO:
            output += "2";
            break;
        case THREE:
            output += "3";
            break;
        case FOUR:
            output += "4";
            break;
        case FIVE:
            output += "5";
            break;
        case SIX:
            output += "6";
            break;
        case SEVEN:
            output += "7";
            break;
        case EIGHT:
            output += "8";
            break;
        case INTERNAL:
            output += "I";
            break;
        case EXTERNAL:
            output += "E";
            break;
        case DEFAULT:
            output += "D";
            break;
        }

        output += ",";
        output += "H" + theCommand.toHEXString();

        output += (char) 13;

        return output;

    }

    /**
     * "Pack" the infrared command so that it can be sent to the IRTrans device
     * 
     * @param led
     *            the led
     * @param theCommand
     *            the the command
     * @return a string which is the full command to be sent to the device
     */
    protected String packIRDBCommand(Leds led, IrCommand theCommand) {
        String output = new String();

        output = "Asnd ";
        output += theCommand.remote;
        output += ",";
        output += theCommand.command;
        output += ",l";
        switch (led) {
        case ALL:
            output += "B";
            break;
        case ONE:
            output += "1";
            break;
        case TWO:
            output += "2";
            break;
        case THREE:
            output += "3";
            break;
        case FOUR:
            output += "4";
            break;
        case FIVE:
            output += "5";
            break;
        case SIX:
            output += "6";
            break;
        case SEVEN:
            output += "7";
            break;
        case EIGHT:
            output += "8";
            break;
        case INTERNAL:
            output += "I";
            break;
        case EXTERNAL:
            output += "E";
            break;
        case DEFAULT:
            output += "D";
            break;
        }

        output += "\r\n";

        return output;

    }

    /**
     * Strip byte count from the bytebuffer. IRTrans devices include the number of bytes sent
     * in each response it sends back to the connected host. This is a simple error checking 
     * mechanism - we do need that information, and so, we strip it
     * 
     * @param byteBuffer
     *            the byte buffer
     * @return the string
     */
    protected String stripByteCount(ByteBuffer byteBuffer) {
        /** {@link Pattern} which matches a binding configuration part */
        Pattern RESPONSE_PATTERN = Pattern.compile("..(\\d{5}) (.*)");
        String message = null;

        String response = new String(byteBuffer.array(), 0, byteBuffer.limit());
        response = StringUtils.chomp(response);

        Matcher matcher = RESPONSE_PATTERN.matcher(response);
        if (matcher.matches()) {
            String byteCountAsString = matcher.group(1);
            int byteCount = Integer.parseInt(byteCountAsString);
            message = matcher.group(2);
        }

        return message;
    }

    /**
     * Fetch the IrCommand that corresponds with the given (hex)String.
     * 
     * @param someString
     *            the some string
     * @return the ir command
     */
    protected IrCommand getIrCommand(String someString) {

        IrCommand theCommand = null;

        if (someString != null) {
            // Run through the dB if IrCommands to see which one is matching, if any, the payload we just received
            Iterator<IrCommand> commandIterator = irCommands.iterator();
            while (commandIterator.hasNext()) {
                IrCommand aCommand = commandIterator.next();
                if (aCommand.sequenceToHEXString().equals(someString)) {
                    theCommand = aCommand;
                    break;
                }
            }
        }

        return theCommand;
    }

    /**
     * Fetch the IrCommand for a given remote:command combination
     * 
     * @param remote
     *            the remote
     * @param command
     *            the command
     * @return the ir command
     */
    protected IrCommand getIrCommand(String remote, String command) {
        IrCommand theCommand = null;

        if (remote != null && command != null) {
            // Run through the dB if IrCommands to see which one is matching, if any, the payload we just received
            Iterator<IrCommand> commandIterator = irCommands.iterator();
            while (commandIterator.hasNext()) {
                IrCommand aCommand = commandIterator.next();
                if (aCommand.remote.equals(remote) && aCommand.command.equals(command)) {
                    theCommand = aCommand;
                    break;
                }
            }
        }

        return theCommand;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void configureChannel(Channel channel) {

        String putInASCIImode = "ASCI";

        ByteBuffer byteBuffer = ByteBuffer.allocate(4);
        try {
            byteBuffer.put(putInASCIImode.getBytes("ASCII"));
            writeBuffer(byteBuffer, channel, false, timeOut);
        } catch (UnsupportedEncodingException e) {
            logger.error("An exception occurred while configurting the IRtrans device: {}", e.getMessage());
        }

        String getFirmwareVersion = "Aver" + (char) 13;
        ByteBuffer response = null;

        byteBuffer = ByteBuffer.allocate(5);
        try {
            byteBuffer.put(getFirmwareVersion.getBytes("ASCII"));
            response = writeBuffer(byteBuffer, channel, true, timeOut);
        } catch (UnsupportedEncodingException e) {
            logger.error("An exception occurred while configurting the IRtrans device: {}", e.getMessage());
        }

        if (response != null) {
            String message = stripByteCount(response);
            if (message != null) {
                if (message.contains("VERSION")) {
                    logger.info("Found an IRtrans device with firmware {}", message);
                } else {
                    logger.warn("Received some non-compliant garbage ({})", message);
                }
            }
        } else {
            logger.warn("Did not receive an answer from the IRtrans device - Parsing is skipped");
        }

    }

    /**
     * @{inheritDoc}
     */
    @Override
    protected String getName() {
        return "IRtrans Refresh Service";
    }

    // FOR FUTURE USAGE - ORG.OPENHAB.MODEL.* RELATED - Parsing of IRtrans .rem files
    // KEPT IN PLACE IN CASE A NEW MODEL RELATED PARSING APPROACH IS CHOSEN IN THE FUTURE

    //   /**
    //    * Populates our infrared command database with the contents of the IRTrans .rem config files
    //    * 
    //    * @param aModel
    //    *            
    //    */
    //   private void addIRtransModel(IRtransModel aModel){
    //      String remoteName = aModel.getRemote().getName();
    //
    //      for (org.openhab.model.irtrans.IRtrans.Command aCommand : aModel.getCommands()) {
    //
    //         int timingId = Integer.parseInt(aCommand.getTiming());
    //
    //         Timing theTiming = null;
    //         for (Timing atiming: aModel.getTimings()) {
    //            if(Integer.parseInt(atiming.getId()) == timingId)
    //            {
    //               theTiming = atiming;
    //               break;
    //            }
    //         }
    //
    //         if(theTiming != null && Integer.parseInt(theTiming.getCount()) == theTiming.getPairs().size()) {
    //            IrCommand newCommand = new IrCommand();
    //            newCommand.remote = remoteName;
    //            newCommand.command = aCommand.getName();
    //            newCommand.sequence = aCommand.getCommand();
    //
    //            newCommand.pulsePairs = new ArrayList<PulsePair>();
    //
    //            for(int i=1;i<=Integer.parseInt(theTiming.getCount());i++ ) {
    //               PulsePair newPair = new PulsePair();
    //
    //               TimingPair thePair = null;
    //
    //               for (TimingPair aPair: theTiming.getPairs()) {
    //                  if(Integer.parseInt(aPair.getId()) == i){
    //                     thePair = aPair;
    //                     break;
    //                  }
    //               }
    //
    //               newPair.Pause = Integer.parseInt(thePair.getPause());
    //               newPair.Pulse = Integer.parseInt(thePair.getPulse());
    //
    //               newCommand.pulsePairs.add(newPair);
    //            }       
    //
    //            TimingOptions theOptions = theTiming.getOptions();
    //            if(theOptions.getFrequency()!=null)newCommand.frequency = Integer.parseInt(theOptions.getFrequency());
    //            if(theOptions.getLength()!=null)newCommand.frameLength = Integer.parseInt(theOptions.getLength());
    //            if(theOptions.getPause()!=null) newCommand.pause = Integer.parseInt(theOptions.getPause());
    //            if(theOptions.getRepeats()!=null)newCommand.numberOfRepeats = Integer.parseInt(theOptions.getRepeats());
    //            newCommand.startBit = theOptions.isStartbit();
    //            newCommand.noTog = theOptions.isNotog();
    //            newCommand.rc5 = theOptions.isRc5();
    //            newCommand.rc6 = theOptions.isRc6();
    //            newCommand.repeatStartBit = theOptions.isRepeatstartbit();
    //
    //            irCommands.add(newCommand);
    //
    //         }
    //      }
    //   }
    //
    //   /**
    //    * Removes the ir trans model.
    //    * 
    //    * @param aModel
    //    *            the a model
    //    */
    //   private void removeIRtransModel(IRtransModel aModel){      
    //      String remoteName = aModel.getRemote().getName();
    //      
    //      Iterator<IrCommand> commandIterator = irCommands.iterator();
    //      while(commandIterator.hasNext()){
    //         IrCommand aCommand = commandIterator.next();
    //         if(aCommand.remote.equals(remoteName)) {
    //            irCommands.remove(aCommand);
    //         }
    //      }
    //      
    //
    //   }

}