Class LocoNetMessage

  • All Implemented Interfaces:
    java.io.Serializable, Message

    public class LocoNetMessage
    extends AbstractMessage
    implements java.io.Serializable
    Represents a single command or response on the LocoNet.

    Content is represented with ints to avoid the problems with sign-extension that bytes have, and because a Java char is actually a variable number of bytes in Unicode.

    Note that this class does not manage the upper bit of the message. By convention, most LocoNet messages have the upper bit set on the first byte, and on no other byte; but not all of them do, and that must be managed elsewhere.

    Note that many specific message types are created elsewhere. In general, if more than one tool will need to use a particular format, it's useful to refactor it to here.


    This file is part of JMRI.

    JMRI is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. See the "COPYING" file for a copy of this license.

    JMRI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

    Some of the message formats used in this class are Copyright Digitrax, Inc. and used with permission as part of the JMRI project. That permission does not extend to uses in other software products. If you wish to use this code, algorithm or these message formats outside of JMRI, please contact Digitrax Inc for separate permission.

    See Also:
    NceMessage, AbstractMessage, Serialized Form
    • Constructor Summary

      Constructors 
      Constructor Description
      LocoNetMessage()
      Create a LocoNetMessage object without providing any indication of its size or contents.
      LocoNetMessage​(byte[] contents)
      Create a message with specified contents.
      LocoNetMessage​(int len)
      Create a new object, representing a specific-length message.
      LocoNetMessage​(int[] contents)
      Create a message with specified contents.
      LocoNetMessage​(java.lang.String s)
      Create a LocoNetMessage from a String
      LocoNetMessage​(LocoNetMessage original)  
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      boolean checkParity()
      Check whether the message has a valid checksum.
      boolean equals​(java.lang.Object o)
      Two messages are the same if their entire data content is the same.
      boolean equals​(LocoNetMessage o, int[] masks)
      Two messages are the same if their masked data content is the same.
      int getElement​(int n)
      Get a specific byte from the message
      int getOpCode()  
      java.lang.String getOpCodeHex()
      Get a String representation of the op code in hex.
      int[] getPeerXfrData()
      Get the 8 data bytes from an OPC_PEER_XFR message.
      int hashCode()
      Hash code from base data.
      protected static boolean highBit​(int val)
      Check if a high bit is set, usually used to store it in some other location (LocoNet does not allow the high bit to be set in data bytes).
      protected static int highByte​(int val)  
      int inputRepAddr()
      If this is an OPC_INPUT_REP, get the 0-n address, else -1
      protected static int lowByte​(int val)  
      static LocoNetMessage makePeerXfr​(int src, int dst, int[] d, int code)
      Return a newly created OPC_PEER_XFR message.
      int sensorAddr()
      Extract sensor address from a sensor message.
      void setElement​(int n, int v)
      set a specific byte at a specific index in the message
      void setOpCode​(int i)  
      void setParity()
      Set the checksum byte(s) of this message.
      java.lang.String toMonitorString()
      Interprets a LocoNet message into a string describing the message.
      java.lang.String toMonitorString​(java.lang.String prefix)
      Interprets a LocoNet message into a string describing the message when a specific connection prefix is known.
      java.lang.String toString()
      Get a String representation of the entire message in hex.
      int turnoutAddr()
      Get turnout address.
      • Methods inherited from class java.lang.Object

        clone, finalize, getClass, notify, notifyAll, wait, wait, wait
    • Constructor Detail

      • LocoNetMessage

        public LocoNetMessage()
        Create a LocoNetMessage object without providing any indication of its size or contents.

        Because a LocoNet message requires at least a size, if not actual contents, this constructor always logs an error.

      • LocoNetMessage

        public LocoNetMessage​(int len)
        Create a new object, representing a specific-length message.

        Logs an error if len is less than 2

        Parameters:
        len - Total bytes in message, including opcode and error-detection byte.
      • LocoNetMessage

        public LocoNetMessage​(java.lang.String s)
        Create a LocoNetMessage from a String

        Because it is difficult to create a complete LocoNet object using a string, this method of AbstractMessage is not supported.

        This constructor always logs an error

        Parameters:
        s - an unused parameter
      • LocoNetMessage

        public LocoNetMessage​(int[] contents)
        Create a message with specified contents.

        This method logs an error and returns if the contents are too short to represent a valid LocoNet message.

        Parameters:
        contents - The array of contents for the message. The error check word must be present, e.g. a 4-byte message must have four values in the array
      • LocoNetMessage

        public LocoNetMessage​(byte[] contents)
        Create a message with specified contents. Each element is forced into an 8-bit value.

        This method logs an error and returns if the message length is too short to represent a valid LocoNet message.

        Parameters:
        contents - The array of contents for the message. The error check word must be present, e.g. a 4-byte message must have four values in the array
    • Method Detail

      • setOpCode

        public void setOpCode​(int i)
      • getOpCodeHex

        public java.lang.String getOpCodeHex()
        Get a String representation of the op code in hex.
        Returns:
        string containing a hexadecimal representation of the message OpCode
      • getElement

        public int getElement​(int n)
        Get a specific byte from the message

        Logs an error and aborts if the index is beyond the length of the message.

        Specified by:
        getElement in interface Message
        Overrides:
        getElement in class AbstractMessage
        Parameters:
        n - the byte index within the message
        Returns:
        integer value of the byte at the index within the message
      • setElement

        public void setElement​(int n,
                               int v)
        set a specific byte at a specific index in the message

        Logs an error and aborts if the index is beyond the length of the message.

        Specified by:
        setElement in interface Message
        Overrides:
        setElement in class AbstractMessage
        Parameters:
        n - the byte index within the message
        v - the value to be set
      • toString

        public java.lang.String toString()
        Get a String representation of the entire message in hex.
        Specified by:
        toString in interface Message
        Overrides:
        toString in class java.lang.Object
        Returns:
        a string representation containing a space-delimited set of hexadecimal values.
      • setParity

        public void setParity()
        Set the checksum byte(s) of this message.
      • checkParity

        public boolean checkParity()
        Check whether the message has a valid checksum.
        Returns:
        true if checksum is correct, else false
      • getPeerXfrData

        public int[] getPeerXfrData()
        Get the 8 data bytes from an OPC_PEER_XFR message.
        Returns:
        int[8] data bytes
      • equals

        public boolean equals​(java.lang.Object o)
        Two messages are the same if their entire data content is the same. We ignore the error-check byte to ease comparisons before a message is transmitted.
        Overrides:
        equals in class AbstractMessage
        Returns:
        true if objects contain the same message contents
      • toMonitorString

        public java.lang.String toMonitorString()
        Interprets a LocoNet message into a string describing the message.

        Where appropriate, this method presents both the JMRI "System Name" and the JMRI "User Name" (where available) for messages which contain control or status information for a Turnout, Sensor or Reporter.

        Display of "User Name" information is acquired from the appropriate "manager", via a reference to an object with an assembled "System Name". This method assumes a system connection "prefix" of "L" when assembling that system name. The remainder of the assembled system name depends on the message contents - message type determines which JMRI object type letter to add - "T" for turnouts, "S" for sensors, and "R" for transponding reporters.

        If the appropriate manager already has an object for the system name being referenced, the method requests the associated user name. If a user name is returned, then the method uses that user name as part of the message. If there is no associated JMRI object configured, or if the associated JMRI object does not have a user name assigned, then the method does not display a user name.

        The method is not appropriate when the user has multiple LocoNet connections or when the user has a single LocoNet connection but has changed the connection prefix to something other than the default of "L".

        Specified by:
        toMonitorString in interface Message
        Returns:
        a human readable representation of the message.
      • toMonitorString

        public java.lang.String toMonitorString​(@Nonnull
                                                java.lang.String prefix)
        Interprets a LocoNet message into a string describing the message when a specific connection prefix is known.

        Where appropriate, this method presents both the JMRI "System Name" and the JMRI "User Name" (where available) for messages which contain control or status information for a Turnout, Sensor or Reporter.

        Display of "User Name" information is acquired from the appropriate "manager", via a reference to an object with an assembled "System Name". This method uses system connection "prefix" as specified in the "prefix" argument when assembling that system name. The remainder of the assembled system name depends on the message contents. Message type determines which JMRI object type letter is added after the "prefix" - "T" for turnouts, * "S" for sensors, and "R" for transponding reporters. The item number specified in the LocoNet message is appended to finish the system name.

        If the appropriate manager already has an object for the system name being referenced, the method requests the associated user name. If a user name is returned, then the method uses that user name as part of the message. If there is no associated JMRI object configured, or if the associated JMRI object does not have a user name assigned, then the method does not display a user name.

        Parameters:
        prefix - the "System Name" prefix denoting the connection
        Returns:
        a human readable representation of the message.
      • makePeerXfr

        public static LocoNetMessage makePeerXfr​(int src,
                                                 int dst,
                                                 int[] d,
                                                 int code)
        Return a newly created OPC_PEER_XFR message.
        Parameters:
        src - Source address
        dst - Destination address
        d - int[8] for the data contents or null
        code - The instruction code placed in the pcxt1 pcxt2 bytes
        Returns:
        The formatted message
      • highBit

        protected static boolean highBit​(int val)
        Check if a high bit is set, usually used to store it in some other location (LocoNet does not allow the high bit to be set in data bytes).
        Parameters:
        val - value to be checked
        Returns:
        True if the argument has the high bit set
      • lowByte

        protected static int lowByte​(int val)
      • highByte

        protected static int highByte​(int val)
      • sensorAddr

        public int sensorAddr()
        Extract sensor address from a sensor message. Does not verify that the message is a sensor message.
        Returns:
        address (in range 0 to n-1)
      • inputRepAddr

        public int inputRepAddr()
        If this is an OPC_INPUT_REP, get the 0-n address, else -1
        Returns:
        address (in range 0 to n-1)
      • turnoutAddr

        public int turnoutAddr()
        Get turnout address. Does not check to see that the message is a turnout message.
        Returns:
        address (in range 1 to n )
      • equals

        public boolean equals​(LocoNetMessage o,
                              int[] masks)
        Two messages are the same if their masked data content is the same.
        We ignore the error-check byte to ease comparisons before a message is transmitted.
        Parameters:
        o - the LocoNet message to be compared against this object's message
        masks - an array of bytes to use to mask the corresponding bytes of the messages.
        Returns:
        true if objects contain the same message contents