Java eISCP - Integra Serial Control Protocol

Post date: Nov 2, 2011 4:45:41 AM

  • I wanted to control my Onkyo AV receiver using a computer. Lucky for me, my Onkyo has a published serial control protocol that also works over Ethernet - eISCP. So off to the races!! I wrote a Java Implementation of the eISCP.UPDATE: I have added more to this Java App in a 2nd post - Part 2, where I have added full response processing.
  • read this post 1st then go on to Part 2

Onkyo's protocol doc is attached to this post below in the attachments section. This doc is version 1.21 dated 2011, I just got it from my dealer (Crutchfield.ca), great support! It appears to be newer than any other floating around the net and specifically references the 3008 and 5008 models.

Onkyo NR5008
eISCP message

There are a few implementations that are floating around the internet - the one I found most useful was a python implementation at https://github.com/compbrain/Onkyo-TX-NR708-Control. It worked but was minimal, plus I wanted to wrap eISCP in a Java class that was robust and extendable.

I wrote a simple java class that I plan to continue to expand its functionality:

My Eiscp.java file is attached to this post below in the attachments section

    • It has a full set of methods that can be used from other Java classes,
    • It can also be run from the command line to send commands and requests to a receiver.
    • > java ca.bc.webarts.tools.eiscp.Eiscp MUTE

Things I still want to update:

    • It does not (yet) validate if the receiver can accept the specific commands,
    • It has the IP and port hardcoded,
    • all the command strings are hard-coded (I want to put them in some config/properties file).
    • more stuff

While I was implementing the eISCP message packet I found some things that were unclear in the Onkyo protocol document. Specifically the data size part of the message - is actually the size of the entire message, not just the data part. See my comments in the code for details.

Here is my code for the method that forms the data message. (full class is attached below)

getEiscpMessage Method

  /**
    * Wraps a command in a eiscp data message (data characters).
    *
    * @param command must be one of the Strings from the eiscp.Eiscp.Command class.
    **/
  public StringBuilder getEiscpMessage(String command)
  {
    StringBuilder sb = new StringBuilder();
    int eiscpDataSize = command.length() + 2 ; // this is the eISCP data size
    int eiscpMsgSize = eiscpDataSize + 1 + 16 ; // this is the size of the entire eISCP msg
    /* This is where I construct the entire message
        character by character. Each char is represented by a 2 disgit hex value */
    sb.append("ISCP");
    // the following are all in HEX representing one char
    // 4 char Big Endian Header
    sb.append((char)Integer.parseInt("00", 16));
    sb.append((char)Integer.parseInt("00", 16));
    sb.append((char)Integer.parseInt("00", 16));
    sb.append((char)Integer.parseInt("10", 16));
    // 4 char  Big Endian data size
    sb.append((char)Integer.parseInt("00", 16));
    sb.append((char)Integer.parseInt("00", 16));
    sb.append((char)Integer.parseInt("00", 16));
    // the official ISCP docs say this is supposed to be just the data size  (eiscpDataSize)
    // ** BUT **
    // It only works if you send the size of the entire Message size (eiscpMsgSize)
    sb.append((char)Integer.parseInt(Integer.toHexString(eiscpMsgSize), 16));
    // eiscp_version = "01";
    sb.append((char)Integer.parseInt("01", 16));
    // 3 chars reserved = "00"+"00"+"00";
    sb.append((char)Integer.parseInt("00", 16));
    sb.append((char)Integer.parseInt("00", 16));
    sb.append((char)Integer.parseInt("00", 16));
    //  eISCP data
    // Start Character
    sb.append("!");
    // eISCP data - unittype char '1' is receiver
    sb.append("1");
    // eISCP data - 3 char command and param    ie PWR01
    sb.append( command);
    // msg end - this can be a few different cahrs depending on you receiver
    // my NR5008 works when I use  'EOF'
    sb.append((char)Integer.parseInt("0D", 16));
    System.out.println("eISCP data size: "+eiscpDataSize +"(0x"+Integer.toHexString(eiscpDataSize) +") chars");
    System.out.println("eISCP msg size: "+sb.length() +"(0x"+Integer.toHexString(sb.length()) +") chars");
    return sb;
  }

You can take and use the code as per the GNU license.

Have fun! and check back, I will continue to extend this until I have a full remote app.

Stay tuned, I also want to test this through the Networking module of the Universal Devices ISY-99i home controller.