Commits

Michael Caron  committed eda121f

Reorganized the commands into their own package.
Added an unidentified message exception to be caught when reading garbage messages
Added a configurable timeout to IPConnection
Fixed a bug in IdNamePayload, where upon each successive encoding, we were adding a byte to the message.

  • Participants
  • Parent commits fb74a20

Comments (0)

Files changed (53)

File nbactions.xml

                 <goal>install</goal>
             </goals>
         </action>
+        <action>
+            <actionName>CUSTOM-Fin</actionName>
+            <displayName>Fin</displayName>
+            <goals>
+                <goal>clean</goal>
+                <goal>package</goal>
+                <goal>install</goal>
+            </goals>
+        </action>
     </actions>
     <groupId>com.intelix</groupId>
     <artifactId>NetLib</artifactId>
     <packaging>jar</packaging>
-    <version>0.7.4</version>
+    <version>0.8.0</version>
     <name>NetLib</name>
 
     <description>Networking library for Intelix HW</description>

File src/main/java/com/intelix/net/Command.java

 package com.intelix.net;
 
+import com.intelix.net.exceptions.InsufficientDataException;
+import com.intelix.net.exceptions.UnidentifiedMessageException;
 import com.intelix.net.payload.Payload;
 import java.io.IOException;
 import org.apache.commons.collections.primitives.ArrayByteList;
         return msgBytes.toArray();
     }
 
-    public int decode(byte[] bytes) throws InsufficientDataException, IOException {
+    public int decode(byte[] bytes) throws InsufficientDataException, UnidentifiedMessageException {
         return decode(bytes, 0);
     }
 
         return this.payload;
     }
 
-    int decode(byte[] bytes, int position) throws InsufficientDataException, IOException {
+    int decode(byte[] bytes, int position) throws InsufficientDataException, UnidentifiedMessageException {
         
         int index = 0;
 
             }
         } catch (ArrayIndexOutOfBoundsException ex)
         {
-            throw new IOException("Did not find suitable Intelix message in buffer.");
+            throw new UnidentifiedMessageException("Received unknown message.", ex);
         }
         
         try

File src/main/java/com/intelix/net/Connection.java

 package com.intelix.net;
 
+import com.intelix.net.exceptions.InsufficientDataException;
+import com.intelix.net.exceptions.UnidentifiedMessageException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.SocketTimeoutException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
 
 public abstract class Connection {
 
-    static final int MAX_BUFFER_SIZE = 10000;
+    static final int MAX_BUFFER_SIZE = 70;
     private byte[] bufferIn;
     private byte[] bufferOut;
     private int buffLimit = 0;
 
     public void init()
     {
-        bufferIn = new byte[512];
+        bufferIn = new byte[MAX_BUFFER_SIZE];
         flushBufferIn();
     }
 
         Arrays.fill(this.bufferIn, (byte)0);
     }
 
-    private void flushBufferOut() {
-        this.buffLimit = 0;
-        Arrays.fill(this.bufferOut, (byte)0);
-    }
-
     public void write(Command cmd) throws IOException {
         try {
-            byte[] bytes = cmd.encode();
-            getOutStream().write(bytes);
+            try {
+                bufferOut = cmd.encode();
+            } catch (IndexOutOfBoundsException ex)
+            {
+                Logger.getLogger(getClass().getName()).log(Level.SEVERE,
+                        "INDEX OUT OF BOUNDS WHILE ENCODING MESSAGE!", ex);
+            }
+
+            StringBuffer sBuff = new StringBuffer(bufferOut.length + 3);
+            for(byte b : bufferOut)
+            {
+                sBuff.append(Integer.toHexString(b & 0xff));
+                sBuff.append(',');
+            }
+            Logger.getLogger(getClass().getName()).fine(">>>>WRITE: [" + sBuff + "]");
+
+            getOutStream().write(bufferOut);
             getOutStream().flush();
-        } catch (Exception e) {
-            System.err.println(e.getMessage());
+
+            //Logger.getLogger(getClass().getName()).fine("done.");
+        } catch (Exception ex) {
+            Logger.getLogger(getClass().getName()).log(Level.SEVERE,
+                        "UNEXPECTED EXCEPTION!", ex);
         }
     }
 
     }
 
     public Command readOne()
-            throws IOException {
+            throws IOException, UnidentifiedMessageException {
         Command c = null;
 
-        Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): setting up");
+        Logger.getLogger(getClass().getName()).finer("Setting up reader");
         InputStream in = getInStream();
         int bytesRead = 0;
         flushBufferIn();
-        boolean started = false;
-        byte[] backupBuff = null;
+        //boolean started = false;
+        //byte[] backupBuff = null;
 
-        Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): about to start reading");
-        int MAX_TRIES = 3;
-        int tries = 0;
-        while (((c == null) && (bytesRead > 0)) || ( (!started) && tries < MAX_TRIES) ){
+        Logger.getLogger(getClass().getName()).finer("About to start reading");
+        int MAX_TRIES = 2;
+        int tries = 1;
+        while (/*((*/c == null && tries <= MAX_TRIES /*) && (bytesRead > 0)) || ( (!started) && tries <= MAX_TRIES) */){
             try {
-                Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): Cycling outer loop");
+                //Logger.getLogger(getClass().getName()).fine("<<< READ: Try(" + (tries++) + ")");
 
-                bytesRead = in.read(this.bufferIn);
+                bytesRead = in.read(this.bufferIn);  // blocks until there's something to read
 
-                Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): read " + bytesRead + " bytes.");
-                if (started = (bytesRead > 0))
+                StringBuffer sBuff = new StringBuffer(bytesRead+5);
+                for(byte b : bufferIn)
                 {
-                    Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): started processing bytes");
-                    int position = 0;
-                    while (position < bytesRead) {
-                        Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): Cycling inner loop");
-                        Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): position:" + position);
-                        try {
-                            byte[] temp = null;
-                            if (backupBuff != null) {
-                                Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): copying backup buffer");
-                                temp = Arrays.copyOf(backupBuff, backupBuff.length + this.bufferIn.length);
-                                System.arraycopy(this.bufferIn, 0, temp, backupBuff.length, this.bufferIn.length);
-                            } else {
-                                temp = this.bufferIn;
-                            }
-                            Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): backup buffer size:" + temp.length);
-                            backupBuff = null;
-
-                            c = new Command();
-                            position = c.decode(temp, position);
-                            Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): position after decode:" + position);
-                        } catch (InsufficientDataException ex) {
-                            Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): Have to cycle again, didn't get enough data.");
-                            backupBuff = new byte[bytesRead - position];
-                            System.arraycopy(this.bufferIn, position, backupBuff, 0, backupBuff.length);
-                            c = null;
-                        }
-                    }
+                    sBuff.append(Integer.toHexString(b & 0xff));
+                    sBuff.append(',');
+                }
+                Logger.getLogger(getClass().getName()).fine("<<<<READ(T"+tries+"): [" + sBuff + "]");
+                    //"<<< READ: read " + bytesRead + " bytes, [" + sBuff.toString() + "]");
+                if (bytesRead > 0)
+                {
+                    //Logger.getLogger(getClass().getName()).info("started processing bytes");
+                    //int position = 0;
+                    //while (position < bytesRead) {
+                      //  Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): Cycling inner loop");
+                      //  Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): position:" + position);
+                      //  try {
+                      //      byte[] temp = null;
+                      //      if (backupBuff != null) {
+                      //          Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): copying backup buffer");
+                      //          temp = Arrays.copyOf(backupBuff, backupBuff.length + this.bufferIn.length);
+                      //          System.arraycopy(this.bufferIn, 0, temp, backupBuff.length, this.bufferIn.length);
+                      //      } else {
+                      //          temp = this.bufferIn;
+                      //      }
+                      //      Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): backup buffer size:" + temp.length);
+                      //      backupBuff = null;
+                      try {
+                        //Logger.getLogger(getClass().getName()).info("Decoding");
+                        c = new Command();
+                        c.decode(bufferIn, 0);
+                        //Logger.getLogger(getClass().getName()).info("Decoded, position="+position);
+                            //Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): position after decode:" + position);
+                      } catch (InsufficientDataException ex) {
+                        Logger.getLogger(getClass().getName()).fine(">>> NET(ReadOne): Have to cycle again, didn't get enough data.");
+                        //backupBuff = new byte[bytesRead - position];
+                        //System.arraycopy(this.bufferIn, position, backupBuff, 0, backupBuff.length);
+                        c = null;
+                      }
+                    //}
                 }
             }
             catch (SocketTimeoutException ex)
             {
-                Logger.getLogger(getClass().getName()).info("Didn't read anything, trying again. Tries=" + tries);
+                Logger.getLogger(getClass().getName()).fine("Read timed out. Try to read again.");
                 tries++;
             }
         }
         if (tries >= MAX_TRIES)
         {
-            throw new IOException("Reached max tries... time for the caller to decide what to do.");
+            StringBuffer sBuff = new StringBuffer(bufferOut.length + 3);
+            for(byte b : bufferOut)
+            {
+                sBuff.append(Integer.toHexString(b & 0xff));
+                sBuff.append(',');
+            }
+            throw new IOException("Wrote ("+sBuff+"). But didn't hear back from the device.");
         }
 
         return c;

File src/main/java/com/intelix/net/GetAdminLockStatusCommand.java

-package com.intelix.net;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public class GetAdminLockStatusCommand extends Command {
-
-    public GetAdminLockStatusCommand() {
-        super();
-        setClassNo(0);
-        setIdNo(6);
-    }
-
-}

File src/main/java/com/intelix/net/GetAllCrosspointsCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-/**
- *
- * @author mcaron
- */
-public class GetAllCrosspointsCommand extends Command {
-
-    public GetAllCrosspointsCommand()
-    {
-        setClassNo(2);
-        setIdNo(5);
-    }
-
-}

File src/main/java/com/intelix/net/GetCrosspointCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-import com.intelix.net.payload.PairSequencePayload;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public class GetCrosspointCommand extends Command {
-    public GetCrosspointCommand(int id) {
-        setClassNo(2);
-        setIdNo(1);
-        PairSequencePayload p = new PairSequencePayload();
-        p.add(id, 0 /* Don't care with a Get */);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/GetInputIconCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.SequencePayload;
-
-public class GetInputIconCommand extends Command {
-
-    public GetInputIconCommand(int id) {
-        setClassNo(1);
-        setIdNo(4);
-        SequencePayload p = new SequencePayload();
-        p.add(id);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/GetInputNameCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.IdNamePayload;
-
-public class GetInputNameCommand extends Command {
-
-    public GetInputNameCommand(int id) {
-        setClassNo(1);
-        setIdNo(1);
-        IdNamePayload p = new IdNamePayload();
-        p.setItemNo(id);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/GetOutputIconCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.SequencePayload;
-
-public class GetOutputIconCommand extends Command {
-
-    public GetOutputIconCommand(int id) {
-        setClassNo(1);
-        setIdNo(10);
-        SequencePayload p = new SequencePayload();
-        p.add(id);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/GetOutputNameCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.IdNamePayload;
-
-public class GetOutputNameCommand extends Command {
-
-    public GetOutputNameCommand(int id) {
-        setClassNo(1);
-        setIdNo(7);
-        IdNamePayload p = new IdNamePayload();
-        p.setItemNo(id);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/GetPresetCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-import com.intelix.net.payload.SequencePayload;
-
-/**
- *
- * @author developer
- */
-public class GetPresetCommand extends Command {
-
-    public GetPresetCommand(int number) {
-        super();
-        setClassNo(3);
-        setIdNo(1);
-        SequencePayload p = new SequencePayload();
-        p.add(number);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/GetPresetNameCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-import com.intelix.net.payload.IdNamePayload;
-
-/**
- *
- * @author developer
- */
-public class GetPresetNameCommand extends Command {
-    public GetPresetNameCommand(int number)
-    {
-        setClassNo(3);
-        setIdNo(4);
-        IdNamePayload p = new IdNamePayload();
-        p.setItemNo(number);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/IPConnection.java

 
     static final int DEFAULT_PORT = 8001;
     static final String DEFAULT_SVR = "192.168.2.189";
+    static final int DEFAULT_IO_TIMEOUT = 2000;
     
     Socket sock = null;
     private String ipAddr;
     private int port;
     private OutputStream outStream;
     private InputStream inStream;
+    private int ioTimeout = DEFAULT_IO_TIMEOUT;
 
     @Override
     public String toString() {
     }
 
     public IPConnection() {
+        super();
     }
 
     public IPConnection(String ipAddr, int port) throws IOException {
-        this.ipAddr = ipAddr;
-        this.port = port;
+        this(ipAddr,port,false);
     }
 
     public IPConnection(String ipAddr, int port, boolean connect)
     throws IOException
     {
-        this(ipAddr, port);
+        this(ipAddr, port, connect, DEFAULT_IO_TIMEOUT);
+    }
+
+    public IPConnection(String ipAddr, int port, boolean connect, int ioTimeout)
+    throws IOException
+    {
+        super();
+        this.ipAddr = ipAddr;
+        this.port = port;
+        this.ioTimeout = ioTimeout;
         if (connect) { connect(); }
     }
 
 
     @Override
     public InputStream getInStream() {
-        Logger.getLogger(getClass().getName()).fine("NET:   > Returning IO IN Stream for IP Connection.");
+        Logger.getLogger(getClass().getName()).finer("NET:   > Returning IO IN Stream for IP Connection.");
         return this.inStream;
     }
 
     @Override
     public OutputStream getOutStream() {
-        Logger.getLogger(getClass().getName()).fine("NET:   > Returning IO OUT Stream for IP Connection.");
+        Logger.getLogger(getClass().getName()).finer("NET:   > Returning IO OUT Stream for IP Connection.");
         return this.outStream;
     }
 
     @Override
     public void connect() throws IOException {
         this.sock = new Socket();
-        this.sock.setSoTimeout(2000);
+        this.sock.setSoTimeout(ioTimeout);
 
         this.sock.setTcpNoDelay(true);
-        this.sock.connect(new InetSocketAddress(this.ipAddr, this.port), 500);
+        this.sock.connect(new InetSocketAddress(this.ipAddr, this.port), ioTimeout);
 
         this.connected = this.sock.isConnected() && !this.sock.isClosed();
         if (!this.connected) {

File src/main/java/com/intelix/net/InsufficientDataException.java

-package com.intelix.net;
-
-public class InsufficientDataException extends Exception {
-}

File src/main/java/com/intelix/net/IntelixInputStream.java

-package com.intelix.net;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class IntelixInputStream extends FilterInputStream {
-
-    protected IntelixInputStream(InputStream in) {
-        super(in);
-    }
-
-    public int read() throws IOException {
-        int n = super.read();
-        n = (n >= 240) ? n + super.read() : n;
-        return n;
-    }
-
-    public int read(byte[] b) throws IOException {
-        int bytesRead = super.read(b);
-
-        return bytesRead;
-    }
-
-    public int read(byte[] b, int off, int len) throws IOException {
-        return super.read(b, off, len);
-    }
-}

File src/main/java/com/intelix/net/IntelixOutputStream.java

-package com.intelix.net;
-
-public class IntelixOutputStream {
-}
-

File src/main/java/com/intelix/net/SetAdminPasswordCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-/**
- *
- * @author mcaron
- */
-public class SetAdminPasswordCommand extends SetPasswordCommand {
-
-    public SetAdminPasswordCommand(String password) {
-        super(password, 10, "MAX_PASS_LENGTH");
-    }
-
-}

File src/main/java/com/intelix/net/SetConnectorIconCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.SequencePayload;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public class SetConnectorIconCommand extends Command
-{
-    public SetConnectorIconCommand(int number, int iconNumber, boolean isInput) {
-        setClassNo(1);
-        setIdNo( isInput ? 3 : 9);
-        SequencePayload p = new SequencePayload(2);
-        p.add(number);
-        p.add(iconNumber);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/SetConnectorNameCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-import com.intelix.net.payload.IdNamePayload;
-import java.util.ResourceBundle;
-public class SetConnectorNameCommand extends Command {
-    
-    private static int MAX_IO_NAME_LENGTH = -1;
-
-    private static int MAX_IO_NAME_LENGTH()
-    {
-        if (MAX_IO_NAME_LENGTH < 0)
-        {
-            ResourceBundle config = ResourceBundle.getBundle("Device");
-            MAX_IO_NAME_LENGTH = Integer.parseInt(
-                config.getString("MAX_IO_NAME_LENGTH"));
-        }
-
-        return MAX_IO_NAME_LENGTH;
-    }
-
-    public SetConnectorNameCommand(String name, int number, boolean isInput) {
-        setClassNo(1);
-        setIdNo(isInput ? 0 : 6);
-        IdNamePayload p = new IdNamePayload(MAX_IO_NAME_LENGTH(), name, number);
-        setPayload(p);
-    }
-
-}

File src/main/java/com/intelix/net/SetCrosspointCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.PairSequencePayload;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public class SetCrosspointCommand extends Command {
-    public SetCrosspointCommand(int input, int output) {
-        setClassNo(2);
-        setIdNo(0);
-        PairSequencePayload p = new PairSequencePayload();
-        p.add(input, output);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/SetNameCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public abstract class SetNameCommand {
-    
-}

File src/main/java/com/intelix/net/SetPasswordCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-import com.intelix.net.payload.SequencePayload;
-import java.util.ResourceBundle;
-
-/**
- *
- * @author mcaron
- */
-public abstract class SetPasswordCommand extends Command {
-
-    protected int MAX_LENGTH = -1;
-
-    public SetPasswordCommand(String password) {}
-
-    protected SetPasswordCommand(String password, int id, String propName) {
-        ResourceBundle config = ResourceBundle.getBundle("Device");
-        if (MAX_LENGTH < 0)
-            MAX_LENGTH = Integer.parseInt(
-                config.getString(propName));
-
-        setClassNo(0);
-        setIdNo(id);
-        SequencePayload p = new SequencePayload(MAX_LENGTH);
-        for(int i=0; i<MAX_LENGTH || i<password.length(); i++)
-        {
-            p.add(password.charAt(i));
-        }
-
-        setPayload(p);
-    }
-
-}

File src/main/java/com/intelix/net/SetPresetCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-import com.intelix.net.payload.SequencePayload;
-
-/**
- *
- * @author mcaron
- */
-public class SetPresetCommand extends Command {
-
-    public SetPresetCommand(int number) {
-        super();
-        setClassNo(3);
-        setIdNo(0);
-        SequencePayload p = new SequencePayload();
-        p.add(number);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/SetPresetNameCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-import com.intelix.net.payload.IdNamePayload;
-import java.util.ResourceBundle;
-
-/**
- *
- * @author mcaron
- */
-public class SetPresetNameCommand extends Command {
-    
-    private static int MAX_PRESET_NAME_LENGTH = -1;
-
-    private static int MAX_PRESET_NAME_LENGTH() {
-        ResourceBundle config = ResourceBundle.getBundle("Device");
-        if (MAX_PRESET_NAME_LENGTH < 0)
-            MAX_PRESET_NAME_LENGTH = Integer.parseInt(
-                config.getString("MAX_PRESET_NAME_LENGTH"));
-
-        return MAX_PRESET_NAME_LENGTH;
-    }
-
-    public SetPresetNameCommand(int number, String name) {
-
-        setClassNo(3);
-        setIdNo(3);
-
-        IdNamePayload p = new IdNamePayload(1 + MAX_PRESET_NAME_LENGTH(), name, number);
-        setPayload(p);
-    }
-
-}

File src/main/java/com/intelix/net/SetUnlockPasswordCommand.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.intelix.net;
-
-/**
- *
- * @author mcaron
- */
-public class SetUnlockPasswordCommand extends SetPasswordCommand {
-
-    public SetUnlockPasswordCommand(String password) {
-        super(password, 8, "MAX_PASS_LENGTH");
-    }
-}

File src/main/java/com/intelix/net/ToggleLockCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.StringPayload;
-import java.util.ResourceBundle;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public class ToggleLockCommand extends Command {
-
-    private static int MAX_PASS_LENGTH = -1;
-
-    public ToggleLockCommand() {
-        super();
-        setClassNo(0);
-        setIdNo(12);
-    }
-
-    public ToggleLockCommand(String password)
-    {
-        this();
-        setIdNo(2);
-
-        ResourceBundle config = ResourceBundle.getBundle("Device");
-        if (MAX_PASS_LENGTH < 0)
-            MAX_PASS_LENGTH = Integer.parseInt(
-                config.getString("MAX_PASS_LENGTH"));
-        StringPayload p = new StringPayload(MAX_PASS_LENGTH, password);
-        setPayload(p);
-    }
-}

File src/main/java/com/intelix/net/ToggleUtilityLockCommand.java

-package com.intelix.net;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public class ToggleUtilityLockCommand extends ToggleLockCommand {
-    public ToggleUtilityLockCommand(String password) {
-        super(password);
-        setIdNo(5);
-    }
-
-    public ToggleUtilityLockCommand() {
-        super();
-        setIdNo(13);
-    }
-}

File src/main/java/com/intelix/net/TriggerPresetCommand.java

-package com.intelix.net;
-
-import com.intelix.net.payload.SequencePayload;
-
-/**
- *
- * @author Michael Caron <michael.r.caron@gmail.com>
- */
-public class TriggerPresetCommand extends Command {
-
-    public TriggerPresetCommand(int presetNum) {
-        setClassNo(3);
-        setIdNo(6);
-        SequencePayload p = new SequencePayload(1);
-        p.add(presetNum);
-        setPayload(p);
-    }
-    
-}

File src/main/java/com/intelix/net/commands/GetAdminLockStatusCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class GetAdminLockStatusCommand extends Command {
+
+    public GetAdminLockStatusCommand() {
+        super();
+        setClassNo(0);
+        setIdNo(6);
+    }
+
+}

File src/main/java/com/intelix/net/commands/GetAllCrosspointsCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+
+/**
+ *
+ * @author mcaron
+ */
+public class GetAllCrosspointsCommand extends Command {
+
+    public GetAllCrosspointsCommand()
+    {
+        setClassNo(2);
+        setIdNo(5);
+    }
+
+}

File src/main/java/com/intelix/net/commands/GetCrosspointCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.PairSequencePayload;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class GetCrosspointCommand extends Command {
+    public GetCrosspointCommand(int id) {
+        setClassNo(2);
+        setIdNo(1);
+        PairSequencePayload p = new PairSequencePayload();
+        p.add(id, 0 /* Don't care with a Get */);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/GetInputIconCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.SequencePayload;
+
+public class GetInputIconCommand extends Command {
+
+    public GetInputIconCommand(int id) {
+        setClassNo(1);
+        setIdNo(4);
+        SequencePayload p = new SequencePayload();
+        p.add(id);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/GetInputNameCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.IdNamePayload;
+
+public class GetInputNameCommand extends Command {
+
+    public GetInputNameCommand(int id) {
+        setClassNo(1);
+        setIdNo(1);
+        IdNamePayload p = new IdNamePayload();
+        p.setItemNo(id);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/GetOutputIconCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.SequencePayload;
+
+public class GetOutputIconCommand extends Command {
+
+    public GetOutputIconCommand(int id) {
+        setClassNo(1);
+        setIdNo(10);
+        SequencePayload p = new SequencePayload();
+        p.add(id);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/GetOutputNameCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.IdNamePayload;
+
+public class GetOutputNameCommand extends Command {
+
+    public GetOutputNameCommand(int id) {
+        setClassNo(1);
+        setIdNo(7);
+        IdNamePayload p = new IdNamePayload();
+        p.setItemNo(id);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/GetPresetCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.SequencePayload;
+
+/**
+ *
+ * @author developer
+ */
+public class GetPresetCommand extends Command {
+
+    public GetPresetCommand(int number) {
+        super();
+        setClassNo(3);
+        setIdNo(1);
+        SequencePayload p = new SequencePayload();
+        p.add(number);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/GetPresetNameCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.IdNamePayload;
+
+/**
+ *
+ * @author developer
+ */
+public class GetPresetNameCommand extends Command {
+    public GetPresetNameCommand(int number)
+    {
+        setClassNo(3);
+        setIdNo(4);
+        IdNamePayload p = new IdNamePayload();
+        p.setItemNo(number);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/SetAdminPasswordCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+/**
+ *
+ * @author mcaron
+ */
+public class SetAdminPasswordCommand extends SetPasswordCommand {
+
+    public SetAdminPasswordCommand(String password) {
+        super(password, 10, "MAX_PASS_LENGTH");
+    }
+
+}

File src/main/java/com/intelix/net/commands/SetConnectorIconCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.SequencePayload;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class SetConnectorIconCommand extends Command
+{
+    public SetConnectorIconCommand(int number, int iconNumber, boolean isInput) {
+        setClassNo(1);
+        setIdNo( isInput ? 3 : 9);
+        SequencePayload p = new SequencePayload(2);
+        p.add(number);
+        p.add(iconNumber);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/SetConnectorNameCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+import com.intelix.net.Command;
+import com.intelix.net.payload.IdNamePayload;
+import java.util.ResourceBundle;
+public class SetConnectorNameCommand extends Command {
+    
+    private static int MAX_IO_NAME_LENGTH = -1;
+
+    private static int MAX_IO_NAME_LENGTH()
+    {
+        if (MAX_IO_NAME_LENGTH < 0)
+        {
+            ResourceBundle config = ResourceBundle.getBundle("Device");
+            MAX_IO_NAME_LENGTH = Integer.parseInt(
+                config.getString("MAX_IO_NAME_LENGTH"));
+        }
+
+        return MAX_IO_NAME_LENGTH;
+    }
+
+    public SetConnectorNameCommand(String name, int number, boolean isInput) {
+        setClassNo(1);
+        setIdNo(isInput ? 0 : 6);
+        IdNamePayload p = new IdNamePayload(MAX_IO_NAME_LENGTH(), name, number);
+        setPayload(p);
+    }
+
+}

File src/main/java/com/intelix/net/commands/SetCrosspointCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.PairSequencePayload;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class SetCrosspointCommand extends Command {
+    public SetCrosspointCommand(int input, int output) {
+        setClassNo(2);
+        setIdNo(0);
+        PairSequencePayload p = new PairSequencePayload();
+        p.add(input, output);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/SetNameCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public abstract class SetNameCommand {
+    
+}

File src/main/java/com/intelix/net/commands/SetPasswordCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.SequencePayload;
+import java.util.ResourceBundle;
+
+/**
+ *
+ * @author mcaron
+ */
+public abstract class SetPasswordCommand extends Command {
+
+    protected int MAX_LENGTH = -1;
+
+    public SetPasswordCommand(String password) {}
+
+    protected SetPasswordCommand(String password, int id, String propName) {
+        ResourceBundle config = ResourceBundle.getBundle("Device");
+        if (MAX_LENGTH < 0)
+            MAX_LENGTH = Integer.parseInt(
+                config.getString(propName));
+
+        setClassNo(0);
+        setIdNo(id);
+        SequencePayload p = new SequencePayload(MAX_LENGTH);
+        for(int i=0; i<MAX_LENGTH || i<password.length(); i++)
+        {
+            p.add(password.charAt(i));
+        }
+
+        setPayload(p);
+    }
+
+}

File src/main/java/com/intelix/net/commands/SetPresetCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.SequencePayload;
+
+/**
+ *
+ * @author mcaron
+ */
+public class SetPresetCommand extends Command {
+
+    public SetPresetCommand(int number) {
+        super();
+        setClassNo(3);
+        setIdNo(0);
+        SequencePayload p = new SequencePayload();
+        p.add(number);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/SetPresetNameCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.IdNamePayload;
+import java.util.ResourceBundle;
+
+/**
+ *
+ * @author mcaron
+ */
+public class SetPresetNameCommand extends Command {
+    
+    private static int MAX_PRESET_NAME_LENGTH = -1;
+
+    private static int MAX_PRESET_NAME_LENGTH() {
+        ResourceBundle config = ResourceBundle.getBundle("Device");
+        if (MAX_PRESET_NAME_LENGTH < 0)
+            MAX_PRESET_NAME_LENGTH = Integer.parseInt(
+                config.getString("MAX_PRESET_NAME_LENGTH"));
+
+        return MAX_PRESET_NAME_LENGTH;
+    }
+
+    public SetPresetNameCommand(int number, String name) {
+
+        setClassNo(3);
+        setIdNo(3);
+
+        IdNamePayload p = new IdNamePayload(1 + MAX_PRESET_NAME_LENGTH(), name, number);
+        setPayload(p);
+    }
+
+}

File src/main/java/com/intelix/net/commands/SetUnlockPasswordCommand.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.commands;
+
+/**
+ *
+ * @author mcaron
+ */
+public class SetUnlockPasswordCommand extends SetPasswordCommand {
+
+    public SetUnlockPasswordCommand(String password) {
+        super(password, 8, "MAX_PASS_LENGTH");
+    }
+}

File src/main/java/com/intelix/net/commands/ToggleLockCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.StringPayload;
+import java.util.ResourceBundle;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class ToggleLockCommand extends Command {
+
+    private static int MAX_PASS_LENGTH = -1;
+
+    public ToggleLockCommand() {
+        super();
+        setClassNo(0);
+        setIdNo(12);
+    }
+
+    public ToggleLockCommand(String password)
+    {
+        this();
+        setIdNo(2);
+
+        ResourceBundle config = ResourceBundle.getBundle("Device");
+        if (MAX_PASS_LENGTH < 0)
+            MAX_PASS_LENGTH = Integer.parseInt(
+                config.getString("MAX_PASS_LENGTH"));
+        StringPayload p = new StringPayload(MAX_PASS_LENGTH, password);
+        setPayload(p);
+    }
+}

File src/main/java/com/intelix/net/commands/ToggleUtilityLockCommand.java

+package com.intelix.net.commands;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class ToggleUtilityLockCommand extends ToggleLockCommand {
+    public ToggleUtilityLockCommand(String password) {
+        super(password);
+        setIdNo(5);
+    }
+
+    public ToggleUtilityLockCommand() {
+        super();
+        setIdNo(13);
+    }
+}

File src/main/java/com/intelix/net/commands/TriggerPresetCommand.java

+package com.intelix.net.commands;
+
+import com.intelix.net.Command;
+import com.intelix.net.payload.SequencePayload;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class TriggerPresetCommand extends Command {
+
+    public TriggerPresetCommand(int presetNum) {
+        setClassNo(3);
+        setIdNo(6);
+        SequencePayload p = new SequencePayload(1);
+        p.add(presetNum);
+        setPayload(p);
+    }
+    
+}

File src/main/java/com/intelix/net/exceptions/InsufficientDataException.java

+package com.intelix.net.exceptions;
+
+public class InsufficientDataException extends Exception {
+}

File src/main/java/com/intelix/net/exceptions/UnidentifiedMessageException.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.intelix.net.exceptions;
+
+/**
+ *
+ * @author Michael Caron <michael.r.caron@gmail.com>
+ */
+public class UnidentifiedMessageException extends Exception {
+    public UnidentifiedMessageException() { super(); }
+    public UnidentifiedMessageException(String msg) { super(msg); }
+    public UnidentifiedMessageException(Throwable t) { super(t); }
+    public UnidentifiedMessageException(String msg, Throwable t) { super(msg, t); }
+}

File src/main/java/com/intelix/net/payload/IdNamePayload.java

     @Override
     public IntList encode() {
         IntList encoded = super.encode();
-        encoded.add(0, this.itemNo);
+        try {
+            encoded.set(0, this.itemNo);
+        } catch (IndexOutOfBoundsException ex) {
+            encoded.add(itemNo);
+        }
         return encoded;
     }