001package jmri.jmrix.powerline.cp290; 002 003import jmri.jmrix.powerline.SerialMessage; 004import jmri.jmrix.powerline.X10Sequence; 005 006/** 007 * Contains the data payload of a serial packet. 008 * <p> 009 * The transmission protocol can come in one of several forms: 010 * <ul> 011 * <li>If the interlocked parameter is false (default), the packet is just sent. 012 * If the response length is not zero, a reply of that length is expected. 013 * <li>If the interlocked parameter is true, the transmission will require a CRC 014 * interlock, which will be automatically added. (Design note: this is done to 015 * make sure that the messages remain atomic) 016 * </ul> 017 * 018 * @author Bob Jacobsen Copyright (C) 2001,2003, 2006, 2007, 2008 019 */ 020public class SpecificMessage extends SerialMessage { 021 // is this logically an abstract class? 022 023 public SpecificMessage(int l) { 024 super(l); 025 setResponseLength(0); // only polls require a response 026 setBinary(true); 027 setTimeout(5000); 028 } 029 030 /** 031 * This ctor interprets the String as the exact sequence to send, 032 * byte-for-byte. 033 * 034 * @param m message 035 * @param l response length in bytes 036 */ 037 public SpecificMessage(String m, int l) { 038 super(m, l); 039 } 040 041 /** 042 * This ctor interprets the byte array as a sequence of characters to send. 043 * 044 * @param a Array of bytes to send 045 * @param l length of expected reply 046 */ 047 @Deprecated( since="5.13.5", forRemoval=true) // deprecated super 048 public SpecificMessage(byte[] a, int l) { 049 super(a, l); 050 } 051 052 /** 053 * Find 1st byte that's not 0xFF, or -1 if none 054 * @return -1 or index of first valid byte 055 */ 056 int startIndex() { 057 int len = getNumDataElements(); 058 for (int i = 0; i < len; i++) { 059 if ((getElement(i) & 0xFF) != 0xFF) { 060 return i; 061 } 062 } 063 return -1; 064 } 065 066 /** 067 * Translate packet to text 068 */ 069 @Override 070 public String toMonitorString() { 071 String test = Constants.toMonitorString(this); 072// // check for valid length 073// String val = "???"; 074// int len = getNumDataElements(); 075// boolean goodSync = true; 076// boolean goodCheckSum = true; 077// int sum = 0; 078// String cmd; 079// String stat; 080// String hCode; 081// String bCode; 082// String dev; 083// switch (len) { 084// case 7: 085// for (int i = 0; i < 6; i++) { 086// if ((getElement(i) & 0xFF) != 0xFF) { 087// goodSync = false; 088// } 089// } 090// val = Constants.statusToText(getElement(6)); 091// break; 092// case 12: 093// for (int i = 0; i < 6; i++) { 094// if ((getElement(i) & 0xFF) != 0xFF) { 095// goodSync = false; 096// } 097// } 098// for (int i = 7; i < 12; i++) { 099// sum = (sum + (getElement(i) &0xFF)) & 0xFF; 100// } 101// stat = Constants.statusToText(getElement(6)); 102// cmd = Constants.commandToText(getElement(7) & 0x0F, -1); 103// hCode = Constants.houseCodeToText((getElement(7) >> 4) & 0x0F); 104// dev = Constants.deviceToText(getElement(8), getElement(9)); 105// bCode = Constants.houseCodeToText((getElement(10) >> 4) & 0x0F); 106// if (sum != (getElement(12) & 0xFF)) { 107// goodCheckSum = false; 108// } 109// val = "Cmd Echo: " + cmd + " stat: " + stat + " House: " + hCode + " Device:" + dev + " base: " + bCode; 110// if (!goodSync) { 111// val = val + " BAD SYNC"; 112// } 113// if (!goodCheckSum) { 114// val = val + " BAD CHECKSUM: " + (getElement(11) & 0xFF) + " vs " + sum; 115// } 116// break; 117// case 22: 118// for (int i = 0; i < 16; i++) { 119// if ((getElement(i) & 0xFF) != 0xFF) { 120// goodSync = false; 121// } 122// } 123// for (int i = 17; i < 21; i++) { 124// sum = (sum + (getElement(i) &0xFF)) & 0xFF; 125// } 126// cmd = Constants.commandToText((getElement(17) & 0x0F), ((getElement(17) & 0xF0) >> 4)); 127// hCode = Constants.houseCodeToText((getElement(18) >> 4) & 0x0F); 128// dev = Constants.deviceToText(getElement(19), getElement(20)); 129// if (sum != (getElement(21) & 0xFF)) { 130// goodCheckSum = false; 131// } 132// val = cmd + " House: " + hCode + " Device:" + dev; 133// if (!goodSync) { 134// val = val + " BAD SYNC"; 135// } 136// if (!goodCheckSum) { 137// val = val + " BAD CHECKSUM: " + (getElement(21) & 0xFF) + " vs " + sum; 138// } 139// break; 140// default: 141// val = "UNK " + toString(); 142// break; 143// } 144 return "Send[" + getNumDataElements() + "]: " + test + "\n"; 145 } 146 147 int responseLength = -1; // -1 is an invalid value, indicating it hasn't been set 148 149 @Override 150 public void setResponseLength(int l) { 151 responseLength = l; 152 } 153 154 @Override 155 public int getResponseLength() { 156 return responseLength; 157 } 158 159 // static methods to recognize a message 160 @Override 161 public boolean isPoll() { 162 return getElement(1) == 48; 163 } 164 165 @Override 166 public boolean isXmt() { 167 return getElement(1) == 17; 168 } 169 170 @Override 171 public int getAddr() { 172 return getElement(0); 173 } 174 175 // static methods to return a formatted message 176 static public SerialMessage getPoll(int addr) { 177 // eventually this will have to include logic for reading 178 // various bytes on the card, but our supported 179 // cards don't require that yet 180 // SerialMessage m = new SerialMessage(1); 181 // m.setResponseLength(2); 182 // m.setElement(0, addr); 183 // m.setTimeout(SHORT_TIMEOUT); // minumum reasonable timeout 184 185 // Powerline implementation does not currently poll 186 return null; 187 } 188 189 static public SpecificMessage getAddress(int housecode, int devicecode) { 190 SpecificMessage m = new SpecificMessage(2); 191 m.setElement(0, 0x04); 192 m.setElement(1, (X10Sequence.encode(housecode) << 4) + X10Sequence.encode(devicecode)); 193 return m; 194 } 195 196 static public SpecificMessage getAddressDim(int housecode, int devicecode, int dimcode) { 197 SpecificMessage m = new SpecificMessage(2); 198 if (dimcode > 0) { 199 m.setElement(0, 0x04 | ((dimcode & 0x1f) << 3)); 200 } else { 201 m.setElement(0, 0x04); 202 } 203 m.setElement(1, (X10Sequence.encode(housecode) << 4) + X10Sequence.encode(devicecode)); 204 return m; 205 } 206 207 static public SpecificMessage getFunctionDim(int housecode, int function, int dimcode) { 208 SpecificMessage m = new SpecificMessage(2); 209 if (dimcode > 0) { 210 m.setElement(0, 0x06 | ((dimcode & 0x1f) << 3)); 211 } else { 212 m.setElement(0, 0x06); 213 } 214 m.setElement(1, (X10Sequence.encode(housecode) << 4) + function); 215 return m; 216 } 217 218 static public SpecificMessage getFunction(int housecode, int function) { 219 SpecificMessage m = new SpecificMessage(2); 220 m.setElement(0, 0x06); 221 m.setElement(1, (X10Sequence.encode(housecode) << 4) + function); 222 return m; 223 } 224} 225 226