001package jmri.jmrix.powerline; 002 003/** 004 * Represent a sequence of one or more Insteon commands (addresses and 005 * functions). 006 * <p> 007 * These are Insteon specific, but not device/interface specific. 008 * <p> 009 * A sequence should consist of addressing (1 or more), and then one or more 010 * commands. It can address multiple devices. 011 * 012 * @author Bob Coleman Copyright (C) 2010 013 * @author Bob Jacobsen Copyright (C) 2008 014 * @author Ken Cameron Copyright (C) 2010 015 */ 016public class InsteonSequence { 017 018 // First implementation of this class uses a fixed length 019 // array to hold the sequence; there's a practical limit to how 020 // many Insteon commands anybody would want to send at once! 021 private static final int MAXINDEX = 32; 022 int index = 0; 023 Command[] cmds = new Command[MAXINDEX]; // doesn't scale, but that's for another day 024 025 /** 026 * Append a new "do function" operation to the sequence 027 * @param idhighbyte 1st id value 028 * @param idmiddlebyte 2nd id value 029 * @param idlowbyte 3rd id value 030 * @param function function 031 * @param flag option flag 032 * @param command1 cmd1 033 * @param command2 cmd2 034 */ 035 public void addFunction(int idhighbyte, int idmiddlebyte, int idlowbyte, int function, int flag, int command1, int command2) { 036 if (index >= MAXINDEX) { 037 throw new IllegalArgumentException("Sequence too long"); 038 } 039 cmds[index] = new Function(idhighbyte, idmiddlebyte, idlowbyte, function, flag, command1, command2); 040 index++; 041 } 042 043 /** 044 * Append a new "set address" operation to the sequence 045 * @param idhighbyte 1st addr 046 * @param idmiddlebyte 2nd addr 047 * @param idlowbyte 3rd addr 048 */ 049 public void addAddress(int idhighbyte, int idmiddlebyte, int idlowbyte) { 050 if (index >= MAXINDEX) { 051 throw new IllegalArgumentException("Sequence too long"); 052 } 053 cmds[index] = new Address(idhighbyte, idmiddlebyte, idlowbyte); 054 index++; 055 } 056 057 /** 058 * Next getCommand will be the first in the sequence 059 */ 060 public void reset() { 061 index = 0; 062 } 063 064 /** 065 * Retrieve the next command in the sequence 066 * @return single Insteon cmd 067 */ 068 public Command getCommand() { 069 return cmds[index++]; 070 } 071 072 /** 073 * Represent a single Insteon command, which is either a "set address" or 074 * "do function" operation 075 */ 076 public interface Command { 077 078 public boolean isAddress(); 079 080 public boolean isFunction(); 081 082 public int getAddressHigh(); 083 084 public int getAddressMiddle(); 085 086 public int getAddressLow(); 087 } 088 089 /** 090 * Represent a single "set address" Insteon command 091 */ 092 public static class Address implements Command { 093 094 public Address(int idhighbyte, int idmiddlebyte, int idlowbyte) { 095 this.idhighbyte = idhighbyte; 096 this.idmiddlebyte = idmiddlebyte; 097 this.idlowbyte = idlowbyte; 098 } 099 int idhighbyte; 100 int idmiddlebyte; 101 int idlowbyte; 102 103 @Override 104 public int getAddressHigh() { 105 return idhighbyte; 106 } 107 108 @Override 109 public int getAddressMiddle() { 110 return idmiddlebyte; 111 } 112 113 @Override 114 public int getAddressLow() { 115 return idlowbyte; 116 } 117 118 @Override 119 public boolean isAddress() { 120 return true; 121 } 122 123 @Override 124 public boolean isFunction() { 125 return false; 126 } 127 } 128 129 /** 130 * Represent a single "do function" Insteon command 131 */ 132 public static class Function implements Command { 133 134 public Function(int idhighbyte, int idmiddlebyte, int idlowbyte, int function, int flag, int command1, int command2) { 135 this.idhighbyte = idhighbyte; 136 this.idmiddlebyte = idmiddlebyte; 137 this.idlowbyte = idlowbyte; 138 this.function = function; 139 this.flag = flag; 140 this.command1 = command1; 141 this.command2 = command2; 142 } 143 int idhighbyte; 144 int idmiddlebyte; 145 int idlowbyte; 146 int function; 147 int flag; 148 int command1; 149 int command2; 150 151 @Override 152 public int getAddressHigh() { 153 return idhighbyte; 154 } 155 156 @Override 157 public int getAddressMiddle() { 158 return idmiddlebyte; 159 } 160 161 @Override 162 public int getAddressLow() { 163 return idlowbyte; 164 } 165 166 public int getFunction() { 167 return function; 168 } 169 170 public int getFlag() { 171 return flag; 172 } 173 174 public int getCommand1() { 175 return command1; 176 } 177 178 public int getCommand2() { 179 return command2; 180 } 181 182 @Override 183 public boolean isAddress() { 184 return false; 185 } 186 187 @Override 188 public boolean isFunction() { 189 return true; 190 } 191 } 192 193 /** 194 * Represent a single "Extended Data" Insteon command 195 */ 196 public static class ExtData implements Command { 197 198 public ExtData(int value) { 199 this.value = value; 200 this.idhighbyte = -1; 201 this.idmiddlebyte = -1; 202 this.idlowbyte = -1; 203 } 204 int idhighbyte; 205 int idmiddlebyte; 206 int idlowbyte; 207 int value; 208 209 @Override 210 public int getAddressHigh() { 211 return idhighbyte; 212 } 213 214 @Override 215 public int getAddressMiddle() { 216 return idmiddlebyte; 217 } 218 219 @Override 220 public int getAddressLow() { 221 return idlowbyte; 222 } 223 224 public int getExtData() { 225 return value; 226 } 227 228 @Override 229 public boolean isAddress() { 230 return false; 231 } 232 233 @Override 234 public boolean isFunction() { 235 return false; 236 } 237 } 238 239 /** 240 * Return a human-readable name for a function code 241 * @param i function value 242 * @return text of the fuction 243 */ 244 public static String functionName(int i) { 245 return X10Sequence.functionName(i); 246 } 247 248 /** 249 * For the house (A-P) and device (1-16) codes, get the line-coded value. 250 * Argument is from 1 to 16 only. 251 * @param i code to convert 252 * @return converted code 253 */ 254 public static int encode(int i) { 255 return X10Sequence.encode(i); 256 } 257 258 /** 259 * Get house (A-P as 1-16) or device (1-16) from line-coded value. 260 * @param i encoded value 261 * @return int value 262 */ 263 public static int decode(int i) { 264 return X10Sequence.decode(i); 265 } 266 267 /** 268 * Pretty-print an address code 269 * @param b address as value 270 * @return text of address explained 271 */ 272 public static String formatAddressByte(int b) { 273 return "House " + X10Sequence.houseValueToText(X10Sequence.decode((b >> 4) & 0x0F)) 274 + " address device " + X10Sequence.decode(b & 0x0f); 275 } 276 277 /** 278 * Pretty-print a function code 279 * @param b function code value 280 * @return text of function code 281 */ 282 public static String formatCommandByte(int b) { 283 return "House " + X10Sequence.houseValueToText(X10Sequence.decode((b >> 4) & 0x0F)) 284 + " function: " + X10Sequence.functionName(b & 0x0f); 285 } 286 287 /** 288 * Translate House Value (1 to 16) to text 289 * @param hV value for housecode 290 * @return text for housecode 291 */ 292 public static String houseValueToText(int hV) { 293 if (hV >= 1 && hV <= 16) { 294 return X10Sequence.houseValueToText(hV); 295 } else { 296 return "??"; 297 } 298 } 299 300 /** 301 * Translate House Code to text 302 * @param hC housecode value 303 * @return text for the housecode 304 */ 305 public static String houseCodeToText(int hC) { 306 return X10Sequence.houseCodeToText(hC); 307 } 308 309}