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 public SpecificMessage(byte[] a, int l) { 048 super(a, l); 049 } 050 051 /** 052 * Find 1st byte that's not 0xFF, or -1 if none 053 * @return -1 or index of first valid byte 054 */ 055 int startIndex() { 056 int len = getNumDataElements(); 057 for (int i = 0; i < len; i++) { 058 if ((getElement(i) & 0xFF) != 0xFF) { 059 return i; 060 } 061 } 062 return -1; 063 } 064 065 /** 066 * Translate packet to text 067 */ 068 @Override 069 public String toMonitorString() { 070 String test = Constants.toMonitorString(this); 071// // check for valid length 072// String val = "???"; 073// int len = getNumDataElements(); 074// boolean goodSync = true; 075// boolean goodCheckSum = true; 076// int sum = 0; 077// String cmd; 078// String stat; 079// String hCode; 080// String bCode; 081// String dev; 082// switch (len) { 083// case 7: 084// for (int i = 0; i < 6; i++) { 085// if ((getElement(i) & 0xFF) != 0xFF) { 086// goodSync = false; 087// } 088// } 089// val = Constants.statusToText(getElement(6)); 090// break; 091// case 12: 092// for (int i = 0; i < 6; i++) { 093// if ((getElement(i) & 0xFF) != 0xFF) { 094// goodSync = false; 095// } 096// } 097// for (int i = 7; i < 12; i++) { 098// sum = (sum + (getElement(i) &0xFF)) & 0xFF; 099// } 100// stat = Constants.statusToText(getElement(6)); 101// cmd = Constants.commandToText(getElement(7) & 0x0F, -1); 102// hCode = Constants.houseCodeToText((getElement(7) >> 4) & 0x0F); 103// dev = Constants.deviceToText(getElement(8), getElement(9)); 104// bCode = Constants.houseCodeToText((getElement(10) >> 4) & 0x0F); 105// if (sum != (getElement(12) & 0xFF)) { 106// goodCheckSum = false; 107// } 108// val = "Cmd Echo: " + cmd + " stat: " + stat + " House: " + hCode + " Device:" + dev + " base: " + bCode; 109// if (!goodSync) { 110// val = val + " BAD SYNC"; 111// } 112// if (!goodCheckSum) { 113// val = val + " BAD CHECKSUM: " + (getElement(11) & 0xFF) + " vs " + sum; 114// } 115// break; 116// case 22: 117// for (int i = 0; i < 16; i++) { 118// if ((getElement(i) & 0xFF) != 0xFF) { 119// goodSync = false; 120// } 121// } 122// for (int i = 17; i < 21; i++) { 123// sum = (sum + (getElement(i) &0xFF)) & 0xFF; 124// } 125// cmd = Constants.commandToText((getElement(17) & 0x0F), ((getElement(17) & 0xF0) >> 4)); 126// hCode = Constants.houseCodeToText((getElement(18) >> 4) & 0x0F); 127// dev = Constants.deviceToText(getElement(19), getElement(20)); 128// if (sum != (getElement(21) & 0xFF)) { 129// goodCheckSum = false; 130// } 131// val = cmd + " House: " + hCode + " Device:" + dev; 132// if (!goodSync) { 133// val = val + " BAD SYNC"; 134// } 135// if (!goodCheckSum) { 136// val = val + " BAD CHECKSUM: " + (getElement(21) & 0xFF) + " vs " + sum; 137// } 138// break; 139// default: 140// val = "UNK " + toString(); 141// break; 142// } 143 return "Send[" + getNumDataElements() + "]: " + test + "\n"; 144 } 145 146 int responseLength = -1; // -1 is an invalid value, indicating it hasn't been set 147 148 @Override 149 public void setResponseLength(int l) { 150 responseLength = l; 151 } 152 153 @Override 154 public int getResponseLength() { 155 return responseLength; 156 } 157 158 // static methods to recognize a message 159 @Override 160 public boolean isPoll() { 161 return getElement(1) == 48; 162 } 163 164 @Override 165 public boolean isXmt() { 166 return getElement(1) == 17; 167 } 168 169 @Override 170 public int getAddr() { 171 return getElement(0); 172 } 173 174 // static methods to return a formatted message 175 static public SerialMessage getPoll(int addr) { 176 // eventually this will have to include logic for reading 177 // various bytes on the card, but our supported 178 // cards don't require that yet 179 // SerialMessage m = new SerialMessage(1); 180 // m.setResponseLength(2); 181 // m.setElement(0, addr); 182 // m.setTimeout(SHORT_TIMEOUT); // minumum reasonable timeout 183 184 // Powerline implementation does not currently poll 185 return null; 186 } 187 188 static public SpecificMessage getAddress(int housecode, int devicecode) { 189 SpecificMessage m = new SpecificMessage(2); 190 m.setElement(0, 0x04); 191 m.setElement(1, (X10Sequence.encode(housecode) << 4) + X10Sequence.encode(devicecode)); 192 return m; 193 } 194 195 static public SpecificMessage getAddressDim(int housecode, int devicecode, int dimcode) { 196 SpecificMessage m = new SpecificMessage(2); 197 if (dimcode > 0) { 198 m.setElement(0, 0x04 | ((dimcode & 0x1f) << 3)); 199 } else { 200 m.setElement(0, 0x04); 201 } 202 m.setElement(1, (X10Sequence.encode(housecode) << 4) + X10Sequence.encode(devicecode)); 203 return m; 204 } 205 206 static public SpecificMessage getFunctionDim(int housecode, int function, int dimcode) { 207 SpecificMessage m = new SpecificMessage(2); 208 if (dimcode > 0) { 209 m.setElement(0, 0x06 | ((dimcode & 0x1f) << 3)); 210 } else { 211 m.setElement(0, 0x06); 212 } 213 m.setElement(1, (X10Sequence.encode(housecode) << 4) + function); 214 return m; 215 } 216 217 static public SpecificMessage getFunction(int housecode, int function) { 218 SpecificMessage m = new SpecificMessage(2); 219 m.setElement(0, 0x06); 220 m.setElement(1, (X10Sequence.encode(housecode) << 4) + function); 221 return m; 222 } 223} 224 225