001package jmri.jmrix.ieee802154.xbee; 002 003import com.digi.xbee.api.models.XBee16BitAddress; 004import com.digi.xbee.api.models.XBee64BitAddress; 005import com.digi.xbee.api.models.XBeeTransmitOptions; 006import com.digi.xbee.api.packet.XBeeAPIPacket; 007import com.digi.xbee.api.packet.common.ATCommandPacket; 008import com.digi.xbee.api.packet.common.RemoteATCommandPacket; 009import com.digi.xbee.api.packet.common.TransmitPacket; 010import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 011 012import java.util.Arrays; 013 014/** 015 * This is a wrapper class for a Digi XBeeAPIPacket. 016 * 017 * @author Paul Bender Copyright (C) 2013 018 */ 019public class XBeeMessage extends jmri.jmrix.ieee802154.IEEE802154Message { 020 021 private XBeeAPIPacket xbm = null; 022 023 /** 024 * Suppress the default ctor, as the length must always be specified 025 */ 026 protected XBeeMessage() { 027 } 028 029 public XBeeMessage(int l) { 030 super(l); 031 } 032 033 /** 034 * This ctor interprets the String as the exact sequence to send, 035 * byte-for-byte. 036 * @param m message 037 * @param l length 038 * 039 */ 040 public XBeeMessage(String m, int l) { 041 super(m, l); 042 } 043 044 /** 045 * This ctor interprets the byte array as a sequence of characters to send. 046 * 047 * @param a Array of bytes to send 048 * @param l length 049 */ 050 public XBeeMessage(byte[] a, int l) { 051 super(Arrays.toString(a), l); 052 } 053 054 /** 055 * This ctor interprets the parameter as an XBeeAPIPacket message. This is the 056 * message form that will generally be used by the implementation. 057 * 058 * @param request an XBeeAPIPacket of bytes to send 059 */ 060 public XBeeMessage(XBeeAPIPacket request) { 061 _nDataChars = request.getPacketData().length; 062 byte[] data = request.getPacketData(); 063 _dataChars = new int[_nDataChars]; 064 for(int i=0;i<_nDataChars;i++) { 065 _dataChars[i] = data[i]; 066 } 067 xbm = request; 068 } 069 070 @Override 071 public boolean replyExpected() { 072 return false; 073 } 074 075 public XBeeAPIPacket getXBeeRequest() { 076 return xbm; 077 } 078 079 public void setXBeeRequest(XBeeAPIPacket request) { 080 xbm = request; 081 } 082 083 @Override 084 public String toMonitorString() { 085 if (xbm != null) { 086 return xbm.toPrettyString(); 087 } else { 088 return toString(); 089 } 090 } 091 092 @Override 093 public String toString() { 094 String s = ""; 095 if (xbm != null) { 096 byte[] packet = xbm.getPacketData(); 097 for (byte b : packet) { 098 s = jmri.util.StringUtil.appendTwoHexFromInt(b, s); 099 } 100 } 101 return s; 102 } 103 104 /** 105 * check whether the message has a valid parity 106 */ 107 @Override 108 public boolean checkParity() { 109 int len = getNumDataElements(); 110 int chksum = 0x00; /* the seed */ 111 112 int loop; 113 114 for (loop = 0; loop < len - 1; loop++) { // calculate contents for data part 115 chksum ^= getElement(loop); 116 } 117 return ((chksum & 0xFF) == getElement(len - 1)); 118 } 119 120 @Override 121 public void setParity() { 122 int len = getNumDataElements(); 123 int chksum = 0x00; /* the seed */ 124 125 int loop; 126 127 for (loop = 0; loop < len - 1; loop++) { // calculate contents for data part 128 chksum ^= getElement(loop); 129 } 130 setElement(len - 1, chksum & 0xFF); 131 } 132 133 // a few canned messages 134 public static XBeeMessage getHardwareVersionRequest() { 135 return new XBeeMessage(new ATCommandPacket(0, "HV", "")); 136 } 137 138 public static XBeeMessage getFirmwareVersionRequest() { 139 return new XBeeMessage(new ATCommandPacket(0, "VR", "")); 140 } 141 142 /** 143 * Get an XBee Message requesting a digital output pin be turned on or off. 144 * @param address XBee Address of the node. This can be either 145 16 bit or 64 bit. 146 * @param pin the DIO Pin on the XBee to use. 147 * @param on boolean value stating whether the pin should be turned 148 * on (true) or off (false) 149 * @return XBeeMessage with a message requesting a digital IO pin be turned on or off. 150 */ 151 @SuppressFBWarnings( value = {"BC_UNCONFIRMED_CAST"}, justification="The passed address must be either a 16 bit address or a 64 bit address, and we check to see if the address is a 16 bit address, so it is redundant to also check for a 64 bit address") 152 public static XBeeMessage getRemoteDoutMessage(Object address, int pin, boolean on) { 153 byte[] onValue = {0x5}; 154 byte[] offValue = {0x4}; 155 if (address instanceof XBee16BitAddress) { 156 return new XBeeMessage(new RemoteATCommandPacket(XBeeAPIPacket.NO_FRAME_ID,XBee64BitAddress.COORDINATOR_ADDRESS,(XBee16BitAddress) address, XBeeTransmitOptions.NONE,"D" + pin, on ? onValue : offValue)); 157 } else { 158 return new XBeeMessage(new RemoteATCommandPacket(XBeeAPIPacket.NO_FRAME_ID,(XBee64BitAddress) address,XBee16BitAddress.UNKNOWN_ADDRESS,XBeeTransmitOptions.NONE, "D" + pin, on ? onValue : offValue)); 159 } 160 } 161 162 /** 163 * Get an XBee Message requesting the status of a digital IO pin. 164 * @param address XBee Address of the node. This can be either 165 16 bit or 64 bit. 166 * @param pin the DIO Pin on the XBee to use. 167 * @return XBeeMessage with a digital IO pin status request. 168 */ 169 @SuppressFBWarnings( value = {"BC_UNCONFIRMED_CAST"}, justification="The passed address must be either a 16 bit address or a 64 bit address, and we check to see if the address is a 16 bit address, so it is redundant to also check for a 64 bit address") 170 public static XBeeMessage getRemoteDoutMessage(Object address, int pin) { 171 if (address instanceof com.digi.xbee.api.models.XBee16BitAddress) { 172 return new XBeeMessage(new RemoteATCommandPacket(XBeeAPIPacket.NO_FRAME_ID,XBee64BitAddress.COORDINATOR_ADDRESS,(XBee16BitAddress) address,XBeeTransmitOptions.NONE,"D" + pin, "")); 173 } else { 174 return new XBeeMessage(new RemoteATCommandPacket(XBeeAPIPacket.NO_FRAME_ID,(XBee64BitAddress) address,XBee16BitAddress.UNKNOWN_ADDRESS,XBeeTransmitOptions.NONE,"D" + pin, "")); 175 } 176 } 177 178 /** 179 * Get an XBee Message requesting an IO sample from the node. 180 * @param address XBee Address of the node. This can be either 181 * @return XBeeMessage with a force IO sample request. 182 16 bit or 64 bit. 183 */ 184 @SuppressFBWarnings( value = {"BC_UNCONFIRMED_CAST"}, justification="The passed address must be either a 16 bit address or a 64 bit address, and we check to see if the address is a 16 bit address, so it is redundant to also check for a 64 bit address") 185 public static XBeeMessage getForceSampleMessage(Object address) { 186 if (address instanceof com.digi.xbee.api.models.XBee16BitAddress) { 187 return new XBeeMessage(new RemoteATCommandPacket(XBeeAPIPacket.NO_FRAME_ID, XBee64BitAddress.COORDINATOR_ADDRESS, (XBee16BitAddress) address, XBeeTransmitOptions.NONE, "IS", "")); 188 } else { 189 return new XBeeMessage(new RemoteATCommandPacket(XBeeAPIPacket.NO_FRAME_ID, (XBee64BitAddress) address, XBee16BitAddress.UNKNOWN_ADDRESS, XBeeTransmitOptions.NONE, "IS", "")); 190 } 191 } 192 193 /** 194 * Get an XBee Message requesting data be sent to the serial port 195 * on a remote node. 196 * @param address XBee Address of the node. This can be either 197 16 bit or 64 bit. 198 * @param payload An byte array containing the bytes to be transfered, as the low order word of the integer. 199 * @return XBeeMessage with remote transmission request for the provided address containing the provided payload. 200 */ 201 @SuppressFBWarnings( value = {"BC_UNCONFIRMED_CAST"}, justification="The passed address must be either a 16 bit address or a 64 bit address, and we check to see if the address is a 16 bit address, so it is redundant to also check for a 64 bit address") 202 public static XBeeMessage getRemoteTransmissionRequest(Object address, byte[] payload) { 203 if (address instanceof com.digi.xbee.api.models.XBee16BitAddress) { 204 return getRemoteTransmissionRequest((com.digi.xbee.api.models.XBee16BitAddress) address, payload); 205 } else { 206 return getRemoteTransmissionRequest((com.digi.xbee.api.models.XBee64BitAddress) address, payload); 207 } 208 } 209 210 /** 211 * Get an XBee Message requesting data be sent to the serial port 212 * on a remote node. 213 * @param address XBee16BitAddress of the node. 214 * @param payload A byte array containing the bytes to be transfered, as the low order word of the integer. 215 * @return XBeeMessage with remote transmission request for the provided address containing the provided payload. 216 */ 217 public static XBeeMessage getRemoteTransmissionRequest(XBee16BitAddress address, byte[] payload) { 218 return new XBeeMessage(new TransmitPacket(XBeeAPIPacket.NO_FRAME_ID,XBee64BitAddress.COORDINATOR_ADDRESS,address,255,XBeeTransmitOptions.NONE,payload)); 219 } 220 221 /** 222 * Get an XBee Message requesting data be sent to the serial port 223 * on a remote node. 224 * @param address XBee64BitAddress of the node. 225 * @param payload A byte array containing the bytes to be transfered, as the low order word of the integer. 226 * @return XBeeMessage with remote transmission request for the provided address containing the provided payload. 227 */ 228 public static XBeeMessage getRemoteTransmissionRequest(XBee64BitAddress address, byte[] payload) { 229 return new XBeeMessage(new TransmitPacket(XBeeAPIPacket.NO_FRAME_ID,address,XBee16BitAddress.UNKNOWN_ADDRESS,255,0,payload)); 230 } 231 232} 233