001package jmri.jmrix.lenz; 002 003import java.io.Serializable; 004 005import org.slf4j.Logger; 006import org.slf4j.LoggerFactory; 007import jmri.SpeedStepMode; 008 009/** 010 * Represents a single command or response on the XpressNet. 011 * <p> 012 * Content is represented with ints to avoid the problems with sign-extension 013 * that bytes have, and because a Java char is actually a variable number of 014 * bytes in Unicode. 015 * 016 * @author Bob Jacobsen Copyright (C) 2002 017 * @author Paul Bender Copyright (C) 2003-2010 018 * 019 */ 020public class XNetMessage extends jmri.jmrix.AbstractMRMessage implements Serializable { 021 022 private static final String X_NET_MESSAGE_REQUEST_LI_BAUD = "XNetMessageRequestLIBaud"; 023 private static final String X_NET_MESSAGE_REQUEST_SERVICE_MODE_READ_DIRECT_V_36 = "XNetMessageRequestServiceModeReadDirectV36"; 024 private static final String X_NET_MESSAGE_REQUEST_SERVICE_MODE_WRITE_DIRECT_V_36 = "XNetMessageRequestServiceModeWriteDirectV36"; 025 private static final String FORWARD = "Forward"; 026 private static final String REVERSE = "Reverse"; 027 private static final String X_NET_MESSAGE_SET_SPEED = "XNetMessageSetSpeed"; 028 private static final String X_NET_MESSAGE_SET_DIRECTION = "XNetMessageSetDirection"; 029 private static final String X_NET_MESSAGE_SET_FUNCTION_GROUP_X = "XNetMessageSetFunctionGroupX"; 030 private static final String POWER_STATE_ON = "PowerStateOn"; 031 private static final String POWER_STATE_OFF = "PowerStateOff"; 032 private static final String SPEED_STEP_MODE_X = "SpeedStepModeX"; 033 private static final String X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY = "XNetMessageSetFunctionGroupXMomentary"; 034 private static final String FUNCTION_CONTINUOUS = "FunctionContinuous"; 035 private static final String FUNCTION_MOMENTARY = "FunctionMomentary"; 036 private static int _nRetries = 5; 037 038 /* According to the specification, XpressNet has a maximum timing 039 interval of 500 milliseconds during normal communications */ 040 protected static final int XNetProgrammingTimeout = 10000; 041 private static int XNetMessageTimeout = 5000; 042 043 /** 044 * Create a new object, representing a specific-length message. 045 * 046 * @param len Total bytes in message, including opcode and error-detection 047 * byte. Valid values are 0 to 15 (0x0 to 0xF). 048 */ 049 public XNetMessage(int len) { 050 super(len); 051 if (len > 15 ) { // only check upper bound. Lower bound checked in 052 // super call. 053 log.error("Invalid length in ctor: {}", len); 054 throw new IllegalArgumentException("Invalid length in ctor: " + len); 055 } 056 setBinary(true); 057 setRetries(_nRetries); 058 setTimeout(XNetMessageTimeout); 059 _nDataChars = len; 060 } 061 062 /** 063 * Create a new object, that is a copy of an existing message. 064 * 065 * @param message an existing XpressNet message 066 */ 067 public XNetMessage(XNetMessage message) { 068 super(message); 069 setBinary(true); 070 setRetries(_nRetries); 071 setTimeout(XNetMessageTimeout); 072 } 073 074 /** 075 * Create an XNetMessage from an XNetReply. 076 * @param message existing XNetReply. 077 */ 078 public XNetMessage(XNetReply message) { 079 super(message.getNumDataElements()); 080 setBinary(true); 081 setRetries(_nRetries); 082 setTimeout(XNetMessageTimeout); 083 for (int i = 0; i < message.getNumDataElements(); i++) { 084 setElement(i, message.getElement(i)); 085 } 086 } 087 088 /** 089 * Create an XNetMessage from a String containing bytes. 090 * @param s string containing data bytes. 091 */ 092 public XNetMessage(String s) { 093 setBinary(true); 094 setRetries(_nRetries); 095 setTimeout(XNetMessageTimeout); 096 // gather bytes in result 097 byte[] b = jmri.util.StringUtil.bytesFromHexString(s); 098 if (b.length == 0) { 099 // no such thing as a zero-length message 100 _nDataChars = 0; 101 _dataChars = null; 102 return; 103 } 104 _nDataChars = b.length; 105 _dataChars = new int[_nDataChars]; 106 for (int i = 0; i < b.length; i++) { 107 setElement(i, b[i]); 108 } 109 } 110 111 // note that the opcode is part of the message, so we treat it 112 // directly 113 // WARNING: use this only with opcodes that have a variable number 114 // of arguments following included. Otherwise, just use setElement 115 @Override 116 public void setOpCode(int i) { 117 if (i > 0xF || i < 0) { 118 log.error("Opcode invalid: {}", i); 119 } 120 setElement(0, ((i * 16) & 0xF0) | ((getNumDataElements() - 2) & 0xF)); 121 } 122 123 @Override 124 public int getOpCode() { 125 return (getElement(0) / 16) & 0xF; 126 } 127 128 /** 129 * Get a String representation of the op code in hex. 130 * {@inheritDoc} 131 */ 132 @Override 133 public String getOpCodeHex() { 134 return "0x" + Integer.toHexString(getOpCode()); 135 } 136 137 /** 138 * Check whether the message has a valid parity. 139 * @return true if parity valid, else false. 140 */ 141 public boolean checkParity() { 142 int len = getNumDataElements(); 143 int chksum = 0x00; /* the seed */ 144 145 int loop; 146 147 for (loop = 0; loop < len - 1; loop++) { // calculate contents for data part 148 chksum ^= getElement(loop); 149 } 150 return ((chksum & 0xFF) == getElement(len - 1)); 151 } 152 153 public void setParity() { 154 int len = getNumDataElements(); 155 int chksum = 0x00; /* the seed */ 156 157 int loop; 158 159 for (loop = 0; loop < len - 1; loop++) { // calculate contents for data part 160 chksum ^= getElement(loop); 161 } 162 setElement(len - 1, chksum & 0xFF); 163 } 164 165 /** 166 * Get an integer representation of a BCD value. 167 * @param n message element index. 168 * @return integer of BCD. 169 */ 170 public Integer getElementBCD(int n) { 171 return Integer.decode(Integer.toHexString(getElement(n))); 172 } 173 174 /** 175 * Get the message length. 176 * @return message length. 177 */ 178 public int length() { 179 return _nDataChars; 180 } 181 182 /** 183 * Set the default number of retries for an XpressNet message. 184 * 185 * @param t number of retries to attempt 186 */ 187 public static void setXNetMessageRetries(int t) { 188 _nRetries = t; 189 } 190 191 /** 192 * Set the default timeout for an XpressNet message. 193 * 194 * @param t Timeout in milliseconds 195 */ 196 public static void setXNetMessageTimeout(int t) { 197 XNetMessageTimeout = t; 198 } 199 200 /** 201 * Most messages are sent with a reply expected, but 202 * we have a few that we treat as though the reply is always 203 * a broadcast message, because the reply usually comes to us 204 * that way. 205 * {@inheritDoc} 206 */ 207 @Override 208 public boolean replyExpected() { 209 return !broadcastReply; 210 } 211 212 private boolean broadcastReply = false; 213 214 /** 215 * Tell the traffic controller we expect this 216 * message to have a broadcast reply. 217 */ 218 public void setBroadcastReply() { 219 broadcastReply = true; 220 } 221 222 // decode messages of a particular form 223 // create messages of a particular form 224 225 /** 226 * Encapsulate an NMRA DCC packet in an XpressNet message. 227 * <p> 228 * On Current (v3.5) Lenz command stations, the Operations Mode 229 * Programming Request is implemented by sending a packet directly 230 * to the rails. This packet is not checked by the XpressNet 231 * protocol, and is just the track packet with an added header 232 * byte. 233 * <p> 234 * NOTE: Lenz does not say this will work for anything but 5 235 * byte packets. 236 * @param packet byte array containing packet data elements. 237 * @return message to send DCC packet. 238 */ 239 public static XNetMessage getNMRAXNetMsg(byte[] packet) { 240 XNetMessage msg = new XNetMessage(packet.length + 2); 241 msg.setOpCode((XNetConstants.OPS_MODE_PROG_REQ & 0xF0) >> 4); 242 msg.setElement(1, 0x30); 243 for (int i = 0; i < packet.length; i++) { 244 msg.setElement((i + 2), packet[i] & 0xff); 245 } 246 msg.setParity(); 247 return (msg); 248 } 249 250 /* 251 * The next group of routines are used by Feedback and/or turnout 252 * control code. These are used in multiple places within the code, 253 * so they appear here. 254 */ 255 256 /** 257 * Generate a message to change turnout state. 258 * @param pNumber address number. 259 * @param pClose true if set turnout closed. 260 * @param pThrow true if set turnout thrown. 261 * @param pOn accessory line true for on, false off. 262 * @return message containing turnout command. 263 */ 264 public static XNetMessage getTurnoutCommandMsg(int pNumber, boolean pClose, 265 boolean pThrow, boolean pOn) { 266 XNetMessage l = new XNetMessage(4); 267 l.setElement(0, XNetConstants.ACC_OPER_REQ); 268 269 // compute address byte fields 270 int hiadr = (pNumber - 1) / 4; 271 int loadr = ((pNumber - 1) - hiadr * 4) * 2; 272 // The MSB of the upper nibble is required to be set on 273 // The rest of the upper nibble should be zeros. 274 // The MSB of the lower nibble says weather or not the 275 // accessory line should be "on" or "off" 276 if (!pOn) { 277 loadr |= 0x80; 278 } else { 279 loadr |= 0x88; 280 } 281 // If we are sending a "throw" command, we set the LSB of the 282 // lower nibble on, otherwise, we leave it "off". 283 if (pThrow) { 284 loadr |= 0x01; 285 } 286 287 // we don't know how to command both states right now! 288 if (pClose && pThrow) { 289 log.error("XpressNet turnout logic can't handle both THROWN and CLOSED yet"); 290 } 291 // store and send 292 l.setElement(1, hiadr); 293 l.setElement(2, loadr); 294 l.setParity(); // Set the parity bit 295 296 return l; 297 } 298 299 /** 300 * Generate a message to receive the feedback information for an upper or 301 * lower nibble of the feedback address in question. 302 * @param pNumber feedback address. 303 * @param pLowerNibble true for upper nibble, else false for lower. 304 * @return feedback request message. 305 */ 306 public static XNetMessage getFeedbackRequestMsg(int pNumber, 307 boolean pLowerNibble) { 308 XNetMessage l = new XNetMessage(4); 309 l.setBroadcastReply(); // we the message reply as a broadcast message. 310 l.setElement(0, XNetConstants.ACC_INFO_REQ); 311 312 // compute address byte field 313 l.setElement(1, (pNumber - 1) / 4); 314 // The MSB of the upper nibble is required to be set on 315 // The rest of the upper nibble should be zeros. 316 // The LSB of the lower nibble says weather or not the 317 // information request is for the upper or lower nibble. 318 if (pLowerNibble) { 319 l.setElement(2, 0x80); 320 } else { 321 l.setElement(2, 0x81); 322 } 323 l.setParity(); // Set the parity bit 324 return l; 325 } 326 327 /* 328 * Next, we have some messages related to sending programming commands. 329 */ 330 331 public static XNetMessage getServiceModeResultsMsg() { 332 XNetMessage m = new XNetMessage(3); 333 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 334 m.setTimeout(XNetProgrammingTimeout); 335 m.setElement(0, XNetConstants.CS_REQUEST); 336 m.setElement(1, XNetConstants.SERVICE_MODE_CSRESULT); 337 m.setParity(); // Set the parity bit 338 return m; 339 } 340 341 public static XNetMessage getExitProgModeMsg() { 342 XNetMessage m = new XNetMessage(3); 343 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 344 m.setElement(0, XNetConstants.CS_REQUEST); 345 m.setElement(1, XNetConstants.RESUME_OPS); 346 m.setParity(); 347 return m; 348 } 349 350 public static XNetMessage getReadPagedCVMsg(int cv) { 351 XNetMessage m = new XNetMessage(4); 352 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 353 m.setTimeout(XNetProgrammingTimeout); 354 m.setElement(0, XNetConstants.PROG_READ_REQUEST); 355 m.setElement(1, XNetConstants.PROG_READ_MODE_PAGED); 356 m.setElement(2, (0xff & cv)); 357 m.setParity(); // Set the parity bit 358 return m; 359 } 360 361 public static XNetMessage getReadDirectCVMsg(int cv) { 362 XNetMessage m = new XNetMessage(4); 363 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 364 m.setTimeout(XNetProgrammingTimeout); 365 m.setElement(0, XNetConstants.PROG_READ_REQUEST); 366 if (cv < 0x0100) /* Use the version 3.5 command for CVs <= 256 */ { 367 m.setElement(1, XNetConstants.PROG_READ_MODE_CV); 368 } else if (cv == 0x0400) /* For CV1024, we need to send the version 3.6 369 command for CVs 1 to 256, sending a 0 for the 370 CV */ { 371 m.setElement(1, XNetConstants.PROG_READ_MODE_CV_V36); 372 } else /* and the version 3.6 command for CVs > 256 */ { 373 m.setElement(1, XNetConstants.PROG_READ_MODE_CV_V36 | ((cv & 0x0300) >> 8)); 374 } 375 m.setElement(2, (0xff & cv)); 376 m.setParity(); // Set the parity bit 377 return m; 378 } 379 380 public static XNetMessage getWritePagedCVMsg(int cv, int val) { 381 XNetMessage m = new XNetMessage(5); 382 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 383 m.setTimeout(XNetProgrammingTimeout); 384 m.setElement(0, XNetConstants.PROG_WRITE_REQUEST); 385 m.setElement(1, XNetConstants.PROG_WRITE_MODE_PAGED); 386 m.setElement(2, (0xff & cv)); 387 m.setElement(3, val); 388 m.setParity(); // Set the parity bit 389 return m; 390 } 391 392 public static XNetMessage getWriteDirectCVMsg(int cv, int val) { 393 XNetMessage m = new XNetMessage(5); 394 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 395 m.setTimeout(XNetProgrammingTimeout); 396 m.setElement(0, XNetConstants.PROG_WRITE_REQUEST); 397 if (cv < 0x0100) /* Use the version 3.5 command for CVs <= 256 */ { 398 m.setElement(1, XNetConstants.PROG_WRITE_MODE_CV); 399 } else if (cv == 0x0400) /* For CV1024, we need to send the version 3.6 400 command for CVs 1 to 256, sending a 0 for the 401 CV */ { 402 m.setElement(1, XNetConstants.PROG_WRITE_MODE_CV_V36); 403 } else /* and the version 3.6 command for CVs > 256 */ { 404 m.setElement(1, XNetConstants.PROG_WRITE_MODE_CV_V36 | ((cv & 0x0300) >> 8)); 405 } 406 m.setElement(2, (0xff & cv)); 407 m.setElement(3, val); 408 m.setParity(); // Set the parity bit 409 return m; 410 } 411 412 public static XNetMessage getReadRegisterMsg(int reg) { 413 if (reg > 8) { 414 log.error("register number too large: {}",reg); 415 } 416 XNetMessage m = new XNetMessage(4); 417 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 418 m.setTimeout(XNetProgrammingTimeout); 419 m.setElement(0, XNetConstants.PROG_READ_REQUEST); 420 m.setElement(1, XNetConstants.PROG_READ_MODE_REGISTER); 421 m.setElement(2, (0x0f & reg)); 422 m.setParity(); // Set the parity bit 423 return m; 424 } 425 426 public static XNetMessage getWriteRegisterMsg(int reg, int val) { 427 if (reg > 8) { 428 log.error("register number too large: {}",reg); 429 } 430 XNetMessage m = new XNetMessage(5); 431 m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE); 432 m.setTimeout(XNetProgrammingTimeout); 433 m.setElement(0, XNetConstants.PROG_WRITE_REQUEST); 434 m.setElement(1, XNetConstants.PROG_WRITE_MODE_REGISTER); 435 m.setElement(2, (0x0f & reg)); 436 m.setElement(3, val); 437 m.setParity(); // Set the parity bit 438 return m; 439 } 440 441 public static XNetMessage getWriteOpsModeCVMsg(int AH, int AL, int cv, int val) { 442 XNetMessage m = new XNetMessage(8); 443 m.setElement(0, XNetConstants.OPS_MODE_PROG_REQ); 444 m.setElement(1, XNetConstants.OPS_MODE_PROG_WRITE_REQ); 445 m.setElement(2, AH); 446 m.setElement(3, AL); 447 /* Element 4 is 0xEC + the upper two bits of the 10 bit CV address. 448 NOTE: This is the track packet CV, not the human readable CV, so 449 its value actually is one less than what we normally think of it as.*/ 450 int temp = (cv - 1) & 0x0300; 451 temp = temp / 0x00FF; 452 m.setElement(4, 0xEC + temp); 453 /* Element 5 is the lower 8 bits of the cv */ 454 m.setElement(5, ((0x00ff & cv) - 1)); 455 m.setElement(6, val); 456 m.setParity(); // Set the parity bit 457 return m; 458 } 459 460 public static XNetMessage getVerifyOpsModeCVMsg(int AH, int AL, int cv, int val) { 461 XNetMessage m = new XNetMessage(8); 462 m.setElement(0, XNetConstants.OPS_MODE_PROG_REQ); 463 m.setElement(1, XNetConstants.OPS_MODE_PROG_WRITE_REQ); 464 m.setElement(2, AH); 465 m.setElement(3, AL); 466 /* Element 4 is 0xE4 + the upper two bits of the 10 bit CV address. 467 NOTE: This is the track packet CV, not the human readable CV, so 468 its value actually is one less than what we normally think of it as.*/ 469 int temp = (cv - 1) & 0x0300; 470 temp = temp / 0x00FF; 471 m.setElement(4, 0xE4 + temp); 472 /* Element 5 is the lower 8 bits of the cv */ 473 m.setElement(5, ((0x00ff & cv) - 1)); 474 m.setElement(6, val); 475 m.setParity(); // Set the parity bit 476 return m; 477 } 478 479 public static XNetMessage getBitWriteOpsModeCVMsg(int AH, int AL, int cv, int bit, boolean value) { 480 XNetMessage m = new XNetMessage(8); 481 m.setElement(0, XNetConstants.OPS_MODE_PROG_REQ); 482 m.setElement(1, XNetConstants.OPS_MODE_PROG_WRITE_REQ); 483 m.setElement(2, AH); 484 m.setElement(3, AL); 485 /* Element 4 is 0xE8 + the upper two bits of the 10 bit CV address. 486 NOTE: This is the track packet CV, not the human readable CV, so 487 its value actually is one less than what we normally think of it as.*/ 488 int temp = (cv - 1) & 0x0300; 489 temp = temp / 0x00FF; 490 m.setElement(4, 0xE8 + temp); 491 /* Element 5 is the lower 8 bits of the cv */ 492 m.setElement(5, ((0x00ff & cv) - 1)); 493 /* Since this is a bit write, Element 6 is: 494 0xE0 + 495 bit 3 is the value to write 496 bit's 0-2 are the location of the bit we are changing */ 497 if (value) { 498 m.setElement(6, ((0xe8) | (bit & 0xff))); 499 } else // value == false 500 { 501 m.setElement(6, ((0xe0) | (bit & 0xff))); 502 } 503 m.setParity(); // Set the parity bit 504 return m; 505 } 506 507 public static XNetMessage getBitVerifyOpsModeCVMsg(int AH, int AL, int cv, int bit, boolean value) { 508 XNetMessage m = new XNetMessage(8); 509 m.setElement(0, XNetConstants.OPS_MODE_PROG_REQ); 510 m.setElement(1, XNetConstants.OPS_MODE_PROG_WRITE_REQ); 511 m.setElement(2, AH); 512 m.setElement(3, AL); 513 /* Element 4 is 0xE8 + the upper two bits of the 10 bit CV address. 514 NOTE: This is the track packet CV, not the human readable CV, so 515 its value actually is one less than what we normally think of it as.*/ 516 int temp = (cv - 1) & 0x0300; 517 temp = temp / 0x00FF; 518 m.setElement(4, 0xE8 + temp); 519 /* Element 5 is the lower 8 bits of the cv */ 520 m.setElement(5, ((0x00ff & cv) - 1)); 521 /* Since this is a bit verify, Element 6 is: 522 0xF0 + 523 bit 3 is the value to write 524 bit's 0-2 are the location of the bit we are changing */ 525 if (value) { 526 m.setElement(6, ((0xf8) | (bit & 0xff))); 527 } else // value == false 528 { 529 m.setElement(6, ((0xf0) | (bit & 0xff))); 530 } 531 m.setParity(); // Set the parity bit 532 return m; 533 } 534 535 /* 536 * Next, we have routines to generate XpressNet Messages for building 537 * and tearing down a consist or a double header. 538 */ 539 540 /** 541 * Build a Double Header. 542 * 543 * @param address1 the first address in the consist 544 * @param address2 the second address in the consist. 545 * @return message to build double header. 546 */ 547 public static XNetMessage getBuildDoubleHeaderMsg(int address1, int address2) { 548 XNetMessage msg = new XNetMessage(7); 549 msg.setElement(0, XNetConstants.LOCO_DOUBLEHEAD); 550 msg.setElement(1, XNetConstants.LOCO_DOUBLEHEAD_BYTE2); 551 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address1)); 552 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address1)); 553 msg.setElement(4, LenzCommandStation.getDCCAddressHigh(address2)); 554 msg.setElement(5, LenzCommandStation.getDCCAddressLow(address2)); 555 msg.setParity(); 556 return (msg); 557 } 558 559 /** 560 * Dissolve a Double Header. 561 * 562 * @param address one of the two addresses in the Double Header 563 * @return message to dissolve a double header. 564 */ 565 public static XNetMessage getDisolveDoubleHeaderMsg(int address) { 566 // All we have to do is call getBuildDoubleHeaderMsg with the 567 // second address as a zero 568 return (getBuildDoubleHeaderMsg(address, 0)); 569 } 570 571 /** 572 * Add a Single address to a specified Advanced consist. 573 * 574 * @param consist the consist address (1-99) 575 * @param address the locomotive address to add. 576 * @param isNormalDir tells us if the locomotive is going forward when 577 * the consist is going forward. 578 * @return message to add address to consist. 579 */ 580 public static XNetMessage getAddLocoToConsistMsg(int consist, int address, 581 boolean isNormalDir) { 582 XNetMessage msg = new XNetMessage(6); 583 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 584 if (isNormalDir) { 585 msg.setElement(1, XNetConstants.LOCO_ADD_MULTI_UNIT_REQ); 586 } else { 587 msg.setElement(1, XNetConstants.LOCO_ADD_MULTI_UNIT_REQ | 0x01); 588 } 589 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 590 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 591 msg.setElement(4, consist); 592 msg.setParity(); 593 return (msg); 594 } 595 596 /** 597 * Remove a Single address to a specified Advanced consist. 598 * 599 * @param consist the consist address (1-99) 600 * @param address the locomotive address to remove 601 * @return message to remove single address from consist. 602 */ 603 public static XNetMessage getRemoveLocoFromConsistMsg(int consist, int address) { 604 XNetMessage msg = new XNetMessage(6); 605 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 606 msg.setElement(1, XNetConstants.LOCO_REM_MULTI_UNIT_REQ); 607 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 608 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 609 msg.setElement(4, consist); 610 msg.setParity(); 611 return (msg); 612 } 613 614 615 /* 616 * Next, we have routines to generate XpressNet Messages for search 617 * and manipulation of the Command Station Database 618 */ 619 620 /** 621 * Given a locomotive address, search the database for the next 622 * member. 623 * (if the Address is zero start at the beginning of the database). 624 * 625 * @param address is the locomotive address 626 * @param searchForward indicates to search the database Forward if 627 * true, or backwards if False 628 * @return message to request next address. 629 */ 630 public static XNetMessage getNextAddressOnStackMsg(int address, boolean searchForward) { 631 XNetMessage msg = new XNetMessage(5); 632 msg.setElement(0, XNetConstants.LOCO_STATUS_REQ); 633 if (searchForward) { 634 msg.setElement(1, XNetConstants.LOCO_STACK_SEARCH_FWD); 635 } else { 636 msg.setElement(1, XNetConstants.LOCO_STACK_SEARCH_BKWD); 637 } 638 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 639 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 640 msg.setParity(); 641 return (msg); 642 } 643 644 /** 645 * Given a consist address, search the database for the next Consist 646 * address. 647 * 648 * @param address is the consist address (in the range 1-99). 649 * If the Address is zero start at the beginning of the database. 650 * @param searchForward indicates to search the database Forward if 651 * true, or backwards if false 652 * @return message to get next consist address. 653 */ 654 public static XNetMessage getDBSearchMsgConsistAddress(int address, boolean searchForward) { 655 XNetMessage msg = new XNetMessage(4); 656 msg.setElement(0, XNetConstants.CS_MULTI_UNIT_REQ); 657 if (searchForward) { 658 msg.setElement(1, XNetConstants.CS_MULTI_UNIT_REQ_FWD); 659 } else { 660 msg.setElement(1, XNetConstants.CS_MULTI_UNIT_REQ_BKWD); 661 } 662 msg.setElement(2, address); 663 msg.setParity(); 664 return (msg); 665 } 666 667 /** 668 * Given a consist and a locomotive address, search the database for 669 * the next Locomotive in the consist. 670 * 671 * @param consist the consist address (1-99). 672 * If the Consist Address is zero start at the begining of the database 673 * @param address the locomotive address. 674 * If the Address is zero start at the begining of the consist 675 * @param searchForward indicates to search the database Forward if 676 * true, or backwards if False 677 * @return message to request next loco in consist. 678 */ 679 public static XNetMessage getDBSearchMsgNextMULoco(int consist, int address, boolean searchForward) { 680 XNetMessage msg = new XNetMessage(6); 681 msg.setElement(0, XNetConstants.LOCO_IN_MULTI_UNIT_SEARCH_REQ); 682 if (searchForward) { 683 msg.setElement(1, XNetConstants.LOCO_IN_MULTI_UNIT_REQ_FORWARD); 684 } else { 685 msg.setElement(1, XNetConstants.LOCO_IN_MULTI_UNIT_REQ_BACKWARD); 686 } 687 msg.setElement(2, consist); 688 msg.setElement(3, LenzCommandStation.getDCCAddressHigh(address)); 689 msg.setElement(4, LenzCommandStation.getDCCAddressLow(address)); 690 msg.setParity(); 691 return (msg); 692 } 693 694 /** 695 * Given a locomotive address, delete it from the database . 696 * 697 * @param address the locomotive address 698 * @return message to delete loco address from stack. 699 */ 700 public static XNetMessage getDeleteAddressOnStackMsg(int address) { 701 XNetMessage msg = new XNetMessage(5); 702 msg.setElement(0, XNetConstants.LOCO_STATUS_REQ); 703 msg.setElement(1, XNetConstants.LOCO_STACK_DELETE); 704 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 705 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 706 msg.setParity(); 707 return (msg); 708 } 709 710 /** 711 * Given a locomotive address, request its status . 712 * 713 * @param address the locomotive address 714 * @return message to request loco status. 715 */ 716 public static XNetMessage getLocomotiveInfoRequestMsg(int address) { 717 XNetMessage msg = new XNetMessage(5); 718 msg.setElement(0, XNetConstants.LOCO_STATUS_REQ); 719 msg.setElement(1, XNetConstants.LOCO_INFO_REQ_V3); 720 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 721 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 722 msg.setParity(); 723 return (msg); 724 } 725 726 /** 727 * Given a locomotive address, request the function state (momentary status). 728 * 729 * @param address the locomotive address 730 * @return momentary function state request request. 731 */ 732 public static XNetMessage getLocomotiveFunctionStatusMsg(int address) { 733 XNetMessage msg = new XNetMessage(5); 734 msg.setElement(0, XNetConstants.LOCO_STATUS_REQ); 735 msg.setElement(1, XNetConstants.LOCO_INFO_REQ_FUNC); 736 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 737 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 738 msg.setParity(); 739 return (msg); 740 } 741 742 /** 743 * Given a locomotive address, request the function on/off state 744 * for functions 13-28 745 * 746 * @param address the locomotive address 747 * @return function state request request f13-f28. 748 */ 749 public static XNetMessage getLocomotiveFunctionHighOnStatusMsg(int address) { 750 XNetMessage msg = new XNetMessage(5); 751 msg.setElement(0, XNetConstants.LOCO_STATUS_REQ); 752 msg.setElement(1, XNetConstants.LOCO_INFO_REQ_FUNC_HI_ON); 753 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 754 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 755 msg.setParity(); 756 return (msg); 757 } 758 759 /** 760 * Given a locomotive address, request the function state (momentary status) 761 * for high functions (functions 13-28). 762 * 763 * @param address the locomotive address 764 * @return momentary function state request request f13-f28. 765 */ 766 public static XNetMessage getLocomotiveFunctionHighMomStatusMsg(int address) { 767 XNetMessage msg = new XNetMessage(5); 768 msg.setElement(0, XNetConstants.LOCO_STATUS_REQ); 769 msg.setElement(1, XNetConstants.LOCO_INFO_REQ_FUNC_HI_MOM); 770 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 771 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 772 msg.setParity(); 773 return (msg); 774 } 775 776 /* 777 * Generate an emergency stop for the specified address. 778 * 779 * @param address the locomotive address 780 */ 781 public static XNetMessage getAddressedEmergencyStop(int address) { 782 XNetMessage msg = new XNetMessage(4); 783 msg.setElement(0, XNetConstants.EMERGENCY_STOP); 784 msg.setElement(1, LenzCommandStation.getDCCAddressHigh(address)); 785 // set to the upper 786 // byte of the DCC address 787 msg.setElement(2, LenzCommandStation.getDCCAddressLow(address)); 788 // set to the lower byte 789 //of the DCC address 790 msg.setParity(); // Set the parity bit 791 return msg; 792 } 793 794 /** 795 * Generate a Speed and Direction Request message. 796 * 797 * @param address the locomotive address 798 * @param speedStepMode the speedstep mode see @jmri.DccThrottle 799 * for possible values. 800 * @param speed a normalized speed value (a floating point number between 0 801 * and 1). A negative value indicates emergency stop. 802 * @param isForward true for forward, false for reverse. 803 * @return set speed and direction message. 804 */ 805 public static XNetMessage getSpeedAndDirectionMsg(int address, 806 SpeedStepMode speedStepMode, 807 float speed, 808 boolean isForward) { 809 XNetMessage msg = new XNetMessage(6); 810 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 811 int element4value = 0; /* this is for holding the speed and 812 direction setting */ 813 814 if (speedStepMode == SpeedStepMode.NMRA_DCC_128) { 815 // We're in 128 speed step mode 816 msg.setElement(1, XNetConstants.LOCO_SPEED_128); 817 // Now, we need to figure out what to send in element 4 818 // Remember, the speed steps are identified as 0-127 (in 819 // 128 step mode), not 1-128. 820 int speedVal = java.lang.Math.round(speed * 126); 821 // speed step 1 is reserved to indicate emergency stop, 822 // so we need to step over speed step 1 823 if (speedVal >= 1) { 824 element4value = speedVal + 1; 825 } 826 } else if (speedStepMode == SpeedStepMode.NMRA_DCC_28) { 827 // We're in 28 speed step mode 828 msg.setElement(1, XNetConstants.LOCO_SPEED_28); 829 // Now, we need to figure out what to send in element 4 830 int speedVal = java.lang.Math.round(speed * 28); 831 // The first speed step used is actually at 4 for 28 832 // speed step mode. 833 if (speedVal >= 1) { 834 speedVal += 3; 835 } 836 // We have to re-arange the bits, since bit 4 is the LSB, 837 // but other bits are in order from 0-3 838 element4value = ((speedVal & 0x1e) >> 1) 839 + ((speedVal & 0x01) << 4); 840 } else if (speedStepMode == SpeedStepMode.NMRA_DCC_27) { 841 // We're in 27 speed step mode 842 msg.setElement(1, XNetConstants.LOCO_SPEED_27); 843 // Now, we need to figure out what to send in element 4 844 int speedVal = java.lang.Math.round(speed * 27); 845 // The first speed step used is actually at 4 for 27 846 // speed step mode. 847 if (speedVal >= 1) { 848 speedVal += 3; 849 } 850 // We have to re-arange the bits, since bit 4 is the LSB, 851 // but other bits are in order from 0-3 852 element4value = ((speedVal & 0x1e) >> 1) 853 + ((speedVal & 0x01) << 4); 854 } else { 855 // We're in 14 speed step mode 856 msg.setElement(1, XNetConstants.LOCO_SPEED_14); 857 // Now, we need to figure out what to send in element 4 858 element4value = (int) (speed * 14); 859 int speedVal = java.lang.Math.round(speed * 14); 860 // The first speed step used is actually at 2 for 14 861 // speed step mode. 862 if (speedVal >= 1) { 863 element4value += 1; 864 } 865 } 866 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 867 // set to the upper byte of the DCC address 868 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 869 // set to the lower byte 870 //of the DCC address 871 if (isForward) { 872 /* the direction bit is always the most significant bit */ 873 element4value += 128; 874 } 875 msg.setElement(4, element4value); 876 msg.setParity(); // Set the parity bit 877 return msg; 878 } 879 880 /** 881 * Generate a Function Group One Operation Request message. 882 * 883 * @param address the locomotive address 884 * @param f0 is true if f0 is on, false if f0 is off 885 * @param f1 is true if f1 is on, false if f1 is off 886 * @param f2 is true if f2 is on, false if f2 is off 887 * @param f3 is true if f3 is on, false if f3 is off 888 * @param f4 is true if f4 is on, false if f4 is off 889 * @return set function group 1 message. 890 */ 891 public static XNetMessage getFunctionGroup1OpsMsg(int address, 892 boolean f0, 893 boolean f1, 894 boolean f2, 895 boolean f3, 896 boolean f4) { 897 XNetMessage msg = new XNetMessage(6); 898 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 899 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP1); 900 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 901 // set to the upper byte of the DCC address 902 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 903 // set to the lower byte of the DCC address 904 // Now, we need to figure out what to send in element 3 905 int element4value = 0; 906 if (f0) { 907 element4value += 16; 908 } 909 if (f1) { 910 element4value += 1; 911 } 912 if (f2) { 913 element4value += 2; 914 } 915 if (f3) { 916 element4value += 4; 917 } 918 if (f4) { 919 element4value += 8; 920 } 921 msg.setElement(4, element4value); 922 msg.setParity(); // Set the parity bit 923 return msg; 924 } 925 926 /** 927 * Generate a Function Group One Set Momentary Functions message. 928 * 929 * @param address the locomotive address 930 * @param f0 is true if f0 is momentary 931 * @param f1 is true if f1 is momentary 932 * @param f2 is true if f2 is momentary 933 * @param f3 is true if f3 is momentary 934 * @param f4 is true if f4 is momentary 935 * @return set momentary function group 1 message. 936 */ 937 public static XNetMessage getFunctionGroup1SetMomMsg(int address, 938 boolean f0, 939 boolean f1, 940 boolean f2, 941 boolean f3, 942 boolean f4) { 943 XNetMessage msg = new XNetMessage(6); 944 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 945 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP1_MOMENTARY); 946 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 947 // set to the upper byte of the DCC address 948 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 949 // set to the lower byte of the DCC address 950 // Now, we need to figure out what to send in element 3 951 int element4value = 0; 952 if (f0) { 953 element4value += 16; 954 } 955 if (f1) { 956 element4value += 1; 957 } 958 if (f2) { 959 element4value += 2; 960 } 961 if (f3) { 962 element4value += 4; 963 } 964 if (f4) { 965 element4value += 8; 966 } 967 msg.setElement(4, element4value); 968 msg.setParity(); // Set the parity bit 969 return msg; 970 } 971 972 /** 973 * Generate a Function Group Two Operation Request message. 974 * 975 * @param address the locomotive address 976 * @param f5 is true if f5 is on, false if f5 is off 977 * @param f6 is true if f6 is on, false if f6 is off 978 * @param f7 is true if f7 is on, false if f7 is off 979 * @param f8 is true if f8 is on, false if f8 is off 980 * @return set function group 2 message. 981 */ 982 public static XNetMessage getFunctionGroup2OpsMsg(int address, 983 boolean f5, 984 boolean f6, 985 boolean f7, 986 boolean f8) { 987 XNetMessage msg = new XNetMessage(6); 988 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 989 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP2); 990 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 991 // set to the upper byte of the DCC address 992 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 993 // set to the lower byte of the DCC address 994 // Now, we need to figure out what to send in element 3 995 int element4value = 0; 996 if (f5) { 997 element4value += 1; 998 } 999 if (f6) { 1000 element4value += 2; 1001 } 1002 if (f7) { 1003 element4value += 4; 1004 } 1005 if (f8) { 1006 element4value += 8; 1007 } 1008 msg.setElement(4, element4value); 1009 msg.setParity(); // Set the parity bit 1010 return msg; 1011 } 1012 1013 /** 1014 * Generate a Function Group Two Set Momentary Functions message. 1015 * 1016 * @param address the locomotive address 1017 * @param f5 is true if f5 is momentary 1018 * @param f6 is true if f6 is momentary 1019 * @param f7 is true if f7 is momentary 1020 * @param f8 is true if f8 is momentary 1021 * @return set momentary function group 2 message. 1022 */ 1023 public static XNetMessage getFunctionGroup2SetMomMsg(int address, 1024 boolean f5, 1025 boolean f6, 1026 boolean f7, 1027 boolean f8) { 1028 XNetMessage msg = new XNetMessage(6); 1029 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1030 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP2_MOMENTARY); 1031 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1032 // set to the upper byte of the DCC address 1033 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1034 // set to the lower byte of the DCC address 1035 // Now, we need to figure out what to send in element 3 1036 int element4value = 0; 1037 if (f5) { 1038 element4value += 1; 1039 } 1040 if (f6) { 1041 element4value += 2; 1042 } 1043 if (f7) { 1044 element4value += 4; 1045 } 1046 if (f8) { 1047 element4value += 8; 1048 } 1049 msg.setElement(4, element4value); 1050 msg.setParity(); // Set the parity bit 1051 return msg; 1052 } 1053 1054 /** 1055 * Generate a Function Group Three Operation Request message. 1056 * 1057 * @param address the locomotive address 1058 * @param f9 is true if f9 is on, false if f9 is off 1059 * @param f10 is true if f10 is on, false if f10 is off 1060 * @param f11 is true if f11 is on, false if f11 is off 1061 * @param f12 is true if f12 is on, false if f12 is off 1062 * @return set function group 3 message. 1063 */ 1064 public static XNetMessage getFunctionGroup3OpsMsg(int address, 1065 boolean f9, 1066 boolean f10, 1067 boolean f11, 1068 boolean f12) { 1069 XNetMessage msg = new XNetMessage(6); 1070 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1071 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP3); 1072 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1073 // set to the upper byte of the DCC address 1074 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1075 // set to the lower byte of the DCC address 1076 // Now, we need to figure out what to send in element 3 1077 int element4value = 0; 1078 if (f9) { 1079 element4value += 1; 1080 } 1081 if (f10) { 1082 element4value += 2; 1083 } 1084 if (f11) { 1085 element4value += 4; 1086 } 1087 if (f12) { 1088 element4value += 8; 1089 } 1090 msg.setElement(4, element4value); 1091 msg.setParity(); // Set the parity bit 1092 return msg; 1093 } 1094 1095 /** 1096 * Generate a Function Group Three Set Momentary Functions message. 1097 * 1098 * @param address the locomotive address 1099 * @param f9 is true if f9 is momentary 1100 * @param f10 is true if f10 is momentary 1101 * @param f11 is true if f11 is momentary 1102 * @param f12 is true if f12 is momentary 1103 * @return set momentary function group 3 message. 1104 */ 1105 public static XNetMessage getFunctionGroup3SetMomMsg(int address, 1106 boolean f9, 1107 boolean f10, 1108 boolean f11, 1109 boolean f12) { 1110 XNetMessage msg = new XNetMessage(6); 1111 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1112 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP3_MOMENTARY); 1113 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1114 // set to the upper byte of the DCC address 1115 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1116 // set to the lower byte of the DCC address 1117 // Now, we need to figure out what to send in element 3 1118 int element4value = 0; 1119 if (f9) { 1120 element4value += 1; 1121 } 1122 if (f10) { 1123 element4value += 2; 1124 } 1125 if (f11) { 1126 element4value += 4; 1127 } 1128 if (f12) { 1129 element4value += 8; 1130 } 1131 msg.setElement(4, element4value); 1132 msg.setParity(); // Set the parity bit 1133 return msg; 1134 } 1135 1136 /** 1137 * Generate a Function Group Four Operation Request message. 1138 * 1139 * @param address the locomotive address 1140 * @param f13 is true if f13 is on, false if f13 is off 1141 * @param f14 is true if f14 is on, false if f14 is off 1142 * @param f15 is true if f15 is on, false if f15 is off 1143 * @param f16 is true if f18 is on, false if f16 is off 1144 * @param f17 is true if f17 is on, false if f17 is off 1145 * @param f18 is true if f18 is on, false if f18 is off 1146 * @param f19 is true if f19 is on, false if f19 is off 1147 * @param f20 is true if f20 is on, false if f20 is off 1148 * @return set function group 4 message. 1149 */ 1150 public static XNetMessage getFunctionGroup4OpsMsg(int address, 1151 boolean f13, 1152 boolean f14, 1153 boolean f15, 1154 boolean f16, 1155 boolean f17, 1156 boolean f18, 1157 boolean f19, 1158 boolean f20) { 1159 XNetMessage msg = new XNetMessage(6); 1160 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1161 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP4); 1162 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1163 // set to the upper byte of the DCC address 1164 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1165 // set to the lower byte of the DCC address 1166 // Now, we need to figure out what to send in element 3 1167 int element4value = 0; 1168 if (f13) { 1169 element4value += 1; 1170 } 1171 if (f14) { 1172 element4value += 2; 1173 } 1174 if (f15) { 1175 element4value += 4; 1176 } 1177 if (f16) { 1178 element4value += 8; 1179 } 1180 if (f17) { 1181 element4value += 16; 1182 } 1183 if (f18) { 1184 element4value += 32; 1185 } 1186 if (f19) { 1187 element4value += 64; 1188 } 1189 if (f20) { 1190 element4value += 128; 1191 } 1192 msg.setElement(4, element4value); 1193 msg.setParity(); // Set the parity bit 1194 return msg; 1195 } 1196 1197 /** 1198 * Generate a Function Group Four Set Momentary Function message. 1199 * 1200 * @param address the locomotive address 1201 * @param f13 is true if f13 is Momentary 1202 * @param f14 is true if f14 is Momentary 1203 * @param f15 is true if f15 is Momentary 1204 * @param f16 is true if f18 is Momentary 1205 * @param f17 is true if f17 is Momentary 1206 * @param f18 is true if f18 is Momentary 1207 * @param f19 is true if f19 is Momentary 1208 * @param f20 is true if f20 is Momentary 1209 * @return set momentary function group 4 message. 1210 */ 1211 public static XNetMessage getFunctionGroup4SetMomMsg(int address, 1212 boolean f13, 1213 boolean f14, 1214 boolean f15, 1215 boolean f16, 1216 boolean f17, 1217 boolean f18, 1218 boolean f19, 1219 boolean f20) { 1220 XNetMessage msg = new XNetMessage(6); 1221 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1222 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP4_MOMENTARY); 1223 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1224 // set to the upper byte of the DCC address 1225 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1226 // set to the lower byte of the DCC address 1227 // Now, we need to figure out what to send in element 3 1228 int element4value = 0; 1229 if (f13) { 1230 element4value += 1; 1231 } 1232 if (f14) { 1233 element4value += 2; 1234 } 1235 if (f15) { 1236 element4value += 4; 1237 } 1238 if (f16) { 1239 element4value += 8; 1240 } 1241 if (f17) { 1242 element4value += 16; 1243 } 1244 if (f18) { 1245 element4value += 32; 1246 } 1247 if (f19) { 1248 element4value += 64; 1249 } 1250 if (f20) { 1251 element4value += 128; 1252 } 1253 msg.setElement(4, element4value); 1254 msg.setParity(); // Set the parity bit 1255 return msg; 1256 } 1257 1258 /** 1259 * Generate a Function Group Five Operation Request message. 1260 * 1261 * @param address the locomotive address 1262 * @param f21 is true if f21 is on, false if f21 is off 1263 * @param f22 is true if f22 is on, false if f22 is off 1264 * @param f23 is true if f23 is on, false if f23 is off 1265 * @param f24 is true if f24 is on, false if f24 is off 1266 * @param f25 is true if f25 is on, false if f25 is off 1267 * @param f26 is true if f26 is on, false if f26 is off 1268 * @param f27 is true if f27 is on, false if f27 is off 1269 * @param f28 is true if f28 is on, false if f28 is off 1270 * @return set function group 5 message. 1271 */ 1272 public static XNetMessage getFunctionGroup5OpsMsg(int address, 1273 boolean f21, 1274 boolean f22, 1275 boolean f23, 1276 boolean f24, 1277 boolean f25, 1278 boolean f26, 1279 boolean f27, 1280 boolean f28) { 1281 XNetMessage msg = new XNetMessage(6); 1282 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1283 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP5); 1284 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1285 // set to the upper byte of the DCC address 1286 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1287 // set to the lower byte of the DCC address 1288 // Now, we need to figure out what to send in element 3 1289 int element4value = 0; 1290 if (f21) { 1291 element4value += 1; 1292 } 1293 if (f22) { 1294 element4value += 2; 1295 } 1296 if (f23) { 1297 element4value += 4; 1298 } 1299 if (f24) { 1300 element4value += 8; 1301 } 1302 if (f25) { 1303 element4value += 16; 1304 } 1305 if (f26) { 1306 element4value += 32; 1307 } 1308 if (f27) { 1309 element4value += 64; 1310 } 1311 if (f28) { 1312 element4value += 128; 1313 } 1314 msg.setElement(4, element4value); 1315 msg.setParity(); // Set the parity bit 1316 return msg; 1317 } 1318 1319 /** 1320 * Generate a Function Group Five Set Momentary Function message. 1321 * 1322 * @param address the locomotive address 1323 * @param f21 is true if f21 is momentary 1324 * @param f22 is true if f22 is momentary 1325 * @param f23 is true if f23 is momentary 1326 * @param f24 is true if f24 is momentary 1327 * @param f25 is true if f25 is momentary 1328 * @param f26 is true if f26 is momentary 1329 * @param f27 is true if f27 is momentary 1330 * @param f28 is true if f28 is momentary 1331 * @return set momentary function group 5 message. 1332 */ 1333 public static XNetMessage getFunctionGroup5SetMomMsg(int address, 1334 boolean f21, 1335 boolean f22, 1336 boolean f23, 1337 boolean f24, 1338 boolean f25, 1339 boolean f26, 1340 boolean f27, 1341 boolean f28) { 1342 XNetMessage msg = new XNetMessage(6); 1343 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1344 msg.setElement(1, XNetConstants.LOCO_SET_FUNC_GROUP5_MOMENTARY); 1345 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1346 // set to the upper byte of the DCC address 1347 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1348 // set to the lower byte of the DCC address 1349 // Now, we need to figure out what to send in element 3 1350 int element4value = 0; 1351 if (f21) { 1352 element4value += 1; 1353 } 1354 if (f22) { 1355 element4value += 2; 1356 } 1357 if (f23) { 1358 element4value += 4; 1359 } 1360 if (f24) { 1361 element4value += 8; 1362 } 1363 if (f25) { 1364 element4value += 16; 1365 } 1366 if (f26) { 1367 element4value += 32; 1368 } 1369 if (f27) { 1370 element4value += 64; 1371 } 1372 if (f28) { 1373 element4value += 128; 1374 } 1375 msg.setElement(4, element4value); 1376 msg.setParity(); // Set the parity bit 1377 return msg; 1378 } 1379 1380 // Generate a Function Group Operation Request message for some specific case. 1381 private static XNetMessage getFunctionGroupNOpsMsg(int address, int byte1, 1382 boolean fA, 1383 boolean fB, 1384 boolean fC, 1385 boolean fD, 1386 boolean fE, 1387 boolean fF, 1388 boolean fG, 1389 boolean fH) { 1390 XNetMessage msg = new XNetMessage(6); 1391 msg.setElement(0, XNetConstants.LOCO_OPER_REQ); 1392 msg.setElement(1, byte1); 1393 msg.setElement(2, LenzCommandStation.getDCCAddressHigh(address)); 1394 // set to the upper byte of the DCC address 1395 msg.setElement(3, LenzCommandStation.getDCCAddressLow(address)); 1396 // set to the lower byte of the DCC address 1397 // Now, we need to figure out what to send in element 3 1398 int element4value = 0; 1399 if (fA) { 1400 element4value += 1; 1401 } 1402 if (fB) { 1403 element4value += 2; 1404 } 1405 if (fC) { 1406 element4value += 4; 1407 } 1408 if (fD) { 1409 element4value += 8; 1410 } 1411 if (fE) { 1412 element4value += 16; 1413 } 1414 if (fF) { 1415 element4value += 32; 1416 } 1417 if (fG) { 1418 element4value += 64; 1419 } 1420 if (fH) { 1421 element4value += 128; 1422 } 1423 msg.setElement(4, element4value); 1424 msg.setParity(); // Set the parity bit 1425 return msg; 1426 } 1427 1428 public static XNetMessage getFunctionGroup6OpsMsg(int address, 1429 boolean fA, boolean fB, boolean fC, boolean fD, 1430 boolean fE, boolean fF, boolean fG, boolean fH) { 1431 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP6, 1432 fA, fB, fC, fD, fE, fF, fG, fH); 1433 } 1434 1435 public static XNetMessage getFunctionGroup7OpsMsg(int address, 1436 boolean fA, boolean fB, boolean fC, boolean fD, 1437 boolean fE, boolean fF, boolean fG, boolean fH) { 1438 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP7, 1439 fA, fB, fC, fD, fE, fF, fG, fH); 1440 } 1441 1442 public static XNetMessage getFunctionGroup8OpsMsg(int address, 1443 boolean fA, boolean fB, boolean fC, boolean fD, 1444 boolean fE, boolean fF, boolean fG, boolean fH) { 1445 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP8, 1446 fA, fB, fC, fD, fE, fF, fG, fH); 1447 } 1448 1449 public static XNetMessage getFunctionGroup9OpsMsg(int address, 1450 boolean fA, boolean fB, boolean fC, boolean fD, 1451 boolean fE, boolean fF, boolean fG, boolean fH) { 1452 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP9, 1453 fA, fB, fC, fD, fE, fF, fG, fH); 1454 } 1455 1456 public static XNetMessage getFunctionGroup10OpsMsg(int address, 1457 boolean fA, boolean fB, boolean fC, boolean fD, 1458 boolean fE, boolean fF, boolean fG, boolean fH) { 1459 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP10, 1460 fA, fB, fC, fD, fE, fF, fG, fH); 1461 } 1462 1463 public static XNetMessage getFunctionGroup6SetMomMsg(int address, 1464 boolean fA, boolean fB, boolean fC, boolean fD, 1465 boolean fE, boolean fF, boolean fG, boolean fH) { 1466 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP6_MOMENTARY, 1467 fA, fB, fC, fD, fE, fF, fG, fH); 1468 } 1469 1470 public static XNetMessage getFunctionGroup7SetMomMsg(int address, 1471 boolean fA, boolean fB, boolean fC, boolean fD, 1472 boolean fE, boolean fF, boolean fG, boolean fH) { 1473 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP7_MOMENTARY, 1474 fA, fB, fC, fD, fE, fF, fG, fH); 1475 } 1476 1477 public static XNetMessage getFunctionGroup8SetMomMsg(int address, 1478 boolean fA, boolean fB, boolean fC, boolean fD, 1479 boolean fE, boolean fF, boolean fG, boolean fH) { 1480 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP8_MOMENTARY, 1481 fA, fB, fC, fD, fE, fF, fG, fH); 1482 } 1483 1484 public static XNetMessage getFunctionGroup9SetMomMsg(int address, 1485 boolean fA, boolean fB, boolean fC, boolean fD, 1486 boolean fE, boolean fF, boolean fG, boolean fH) { 1487 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP9_MOMENTARY, 1488 fA, fB, fC, fD, fE, fF, fG, fH); 1489 } 1490 1491 public static XNetMessage getFunctionGroup10SetMomMsg(int address, 1492 boolean fA, boolean fB, boolean fC, boolean fD, 1493 boolean fE, boolean fF, boolean fG, boolean fH) { 1494 return getFunctionGroupNOpsMsg(address, XNetConstants.LOCO_SET_FUNC_GROUP10_MOMENTARY, 1495 fA, fB, fC, fD, fE, fF, fG, fH); 1496 } 1497 1498 /** 1499 * Build a Resume operations Message. 1500 * @return resume message. 1501 */ 1502 public static XNetMessage getResumeOperationsMsg() { 1503 XNetMessage msg = new XNetMessage(3); 1504 msg.setElement(0, XNetConstants.CS_REQUEST); 1505 msg.setElement(1, XNetConstants.RESUME_OPS); 1506 msg.setParity(); 1507 return (msg); 1508 } 1509 1510 /** 1511 * Build an EmergencyOff Message. 1512 * @return emergency off message. 1513 */ 1514 public static XNetMessage getEmergencyOffMsg() { 1515 XNetMessage msg = new XNetMessage(3); 1516 msg.setElement(0, XNetConstants.CS_REQUEST); 1517 msg.setElement(1, XNetConstants.EMERGENCY_OFF); 1518 msg.setParity(); 1519 return (msg); 1520 } 1521 1522 /** 1523 * Build an EmergencyStop Message. 1524 * @return emergency stop message. 1525 */ 1526 public static XNetMessage getEmergencyStopMsg() { 1527 XNetMessage msg = new XNetMessage(2); 1528 msg.setElement(0, XNetConstants.ALL_ESTOP); 1529 msg.setParity(); 1530 return (msg); 1531 } 1532 1533 /** 1534 * Generate the message to request the Command Station Hardware/Software 1535 * Version. 1536 * @return message to request CS hardware and software version. 1537 */ 1538 public static XNetMessage getCSVersionRequestMessage() { 1539 XNetMessage msg = new XNetMessage(3); 1540 msg.setElement(0, XNetConstants.CS_REQUEST); 1541 msg.setElement(1, XNetConstants.CS_VERSION); 1542 msg.setParity(); // Set the parity bit 1543 return msg; 1544 } 1545 1546 /** 1547 * Generate the message to request the Command Station Status. 1548 * @return message to request CS status. 1549 */ 1550 public static XNetMessage getCSStatusRequestMessage() { 1551 XNetMessage msg = new XNetMessage(3); 1552 msg.setElement(0, XNetConstants.CS_REQUEST); 1553 msg.setElement(1, XNetConstants.CS_STATUS); 1554 msg.setParity(); // Set the parity bit 1555 return msg; 1556 } 1557 1558 /** 1559 * Generate the message to set the Command Station to Auto or Manual restart 1560 * mode. 1561 * @param autoMode true if auto, false for manual. 1562 * @return message to set CS restart mode. 1563 */ 1564 public static XNetMessage getCSAutoStartMessage(boolean autoMode) { 1565 XNetMessage msg = new XNetMessage(4); 1566 msg.setElement(0, XNetConstants.CS_SET_POWERMODE); 1567 msg.setElement(1, XNetConstants.CS_SET_POWERMODE); 1568 if (autoMode) { 1569 msg.setElement(2, XNetConstants.CS_POWERMODE_AUTO); 1570 } else { 1571 msg.setElement(2, XNetConstants.CS_POWERMODE_MANUAL); 1572 } 1573 msg.setParity(); // Set the parity bit 1574 return msg; 1575 } 1576 1577 /** 1578 * Generate the message to request the Computer Interface Hardware/Software 1579 * Version. 1580 * @return message to request interface hardware and software version. 1581 */ 1582 public static XNetMessage getLIVersionRequestMessage() { 1583 XNetMessage msg = new XNetMessage(2); 1584 msg.setElement(0, XNetConstants.LI_VERSION_REQUEST); 1585 msg.setParity(); // Set the parity bit 1586 return msg; 1587 } 1588 1589 /** 1590 * Generate the message to set or request the Computer Interface Address. 1591 * 1592 * @param address Interface address (0-31). Send invalid address to request 1593 * the address (32-255). 1594 * @return message to set or request interface address. 1595 */ 1596 public static XNetMessage getLIAddressRequestMsg(int address) { 1597 XNetMessage msg = new XNetMessage(4); 1598 msg.setElement(0, XNetConstants.LI101_REQUEST); 1599 msg.setElement(1, XNetConstants.LI101_REQUEST_ADDRESS); 1600 msg.setElement(2, address); 1601 msg.setParity(); // Set the parity bit 1602 return msg; 1603 } 1604 1605 /** 1606 * Generate the message to set or request the Computer Interface speed. 1607 * 1608 * @param speed 1 is 19,200bps, 2 is 38,400bps, 3 is 57,600bps, 4 is 1609 * 115,200bps. Send invalid speed to request the current 1610 * setting. 1611 * @return message for set / request interface speed. 1612 */ 1613 public static XNetMessage getLISpeedRequestMsg(int speed) { 1614 XNetMessage msg = new XNetMessage(4); 1615 msg.setElement(0, XNetConstants.LI101_REQUEST); 1616 msg.setElement(1, XNetConstants.LI101_REQUEST_BAUD); 1617 msg.setElement(2, speed); 1618 msg.setParity(); // Set the parity bit 1619 return msg; 1620 } 1621 1622 /** 1623 * Generate text translations of messages for use in the XpressNet monitor. 1624 * 1625 * @return representation of the XNetMessage as a string. 1626 */ 1627 @Override 1628 public String toMonitorString(){ 1629 String text; 1630 /* Start decoding messages sent by the computer */ 1631 /* Start with LI101F requests */ 1632 if (getElement(0) == XNetConstants.LI_VERSION_REQUEST) { 1633 text = Bundle.getMessage("XNetMessageRequestLIVersion"); 1634 } else if (getElement(0) == XNetConstants.LI101_REQUEST) { 1635 switch (getElement(1)) { 1636 case XNetConstants.LI101_REQUEST_ADDRESS: 1637 text = Bundle.getMessage("XNetMessageRequestLIAddress", getElement(2)); 1638 break; 1639 case XNetConstants.LI101_REQUEST_BAUD: 1640 switch (getElement(2)) { 1641 case 1: 1642 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_LI_BAUD, 1643 Bundle.getMessage("LIBaud19200")); 1644 break; 1645 case 2: 1646 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_LI_BAUD, 1647 Bundle.getMessage("Baud38400")); 1648 break; 1649 case 3: 1650 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_LI_BAUD, 1651 Bundle.getMessage("Baud57600")); 1652 break; 1653 case 4: 1654 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_LI_BAUD, 1655 Bundle.getMessage("Baud115200")); 1656 break; 1657 default: 1658 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_LI_BAUD, 1659 Bundle.getMessage("BaudOther")); 1660 } 1661 break; 1662 default: 1663 text = toString(); 1664 } 1665 /* Next, we have generic requests */ 1666 } else if (getElement(0) == XNetConstants.CS_REQUEST) { 1667 switch (getElement(1)) { 1668 case XNetConstants.EMERGENCY_OFF: 1669 text = Bundle.getMessage("XNetMessageRequestEmergencyOff"); 1670 break; 1671 case XNetConstants.RESUME_OPS: 1672 text = Bundle.getMessage("XNetMessageRequestNormalOps"); 1673 break; 1674 case XNetConstants.SERVICE_MODE_CSRESULT: 1675 text = Bundle.getMessage("XNetMessageRequestServiceModeResult"); 1676 break; 1677 case XNetConstants.CS_VERSION: 1678 text = Bundle.getMessage("XNetMessageRequestCSVersion"); 1679 break; 1680 case XNetConstants.CS_STATUS: 1681 text = Bundle.getMessage("XNetMessageRequestCSStatus"); 1682 break; 1683 default: 1684 text = toString(); 1685 } 1686 } else if (getElement(0) == XNetConstants.CS_SET_POWERMODE 1687 && getElement(1) == XNetConstants.CS_SET_POWERMODE 1688 && getElement(2) == XNetConstants.CS_POWERMODE_AUTO) { 1689 text = Bundle.getMessage("XNetMessageRequestCSPowerModeAuto"); 1690 } else if (getElement(0) == XNetConstants.CS_SET_POWERMODE 1691 && getElement(1) == XNetConstants.CS_SET_POWERMODE 1692 && getElement(2) == XNetConstants.CS_POWERMODE_MANUAL) { 1693 text = Bundle.getMessage("XNetMessageRequestCSPowerModeManual"); 1694 /* Next, we have Programming Requests */ 1695 } else if (getElement(0) == XNetConstants.PROG_READ_REQUEST) { 1696 switch (getElement(1)) { 1697 case XNetConstants.PROG_READ_MODE_REGISTER: 1698 text = Bundle.getMessage("XNetMessageRequestServiceModeReadRegister",getElement(2)); 1699 break; 1700 case XNetConstants.PROG_READ_MODE_CV: 1701 text = Bundle.getMessage("XNetMessageRequestServiceModeReadDirect",getElement(2)); 1702 break; 1703 case XNetConstants.PROG_READ_MODE_PAGED: 1704 text = Bundle.getMessage("XNetMessageRequestServiceModeReadPaged",getElement(2)); 1705 break; 1706 case XNetConstants.PROG_READ_MODE_CV_V36: 1707 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_READ_DIRECT_V_36,(getElement(2)== 0 ? 1024 : getElement(2))); 1708 break; 1709 case XNetConstants.PROG_READ_MODE_CV_V36 + 1: 1710 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_READ_DIRECT_V_36,(256 + getElement(2))); 1711 break; 1712 case XNetConstants.PROG_READ_MODE_CV_V36 + 2: 1713 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_READ_DIRECT_V_36,(512 + getElement(2))); 1714 break; 1715 case XNetConstants.PROG_READ_MODE_CV_V36 + 3: 1716 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_READ_DIRECT_V_36,(768 + getElement(2))); 1717 break; 1718 default: 1719 text = toString(); 1720 } 1721 } else if (getElement(0) == XNetConstants.PROG_WRITE_REQUEST) { 1722 switch (getElement(1)) { 1723 case XNetConstants.PROG_WRITE_MODE_REGISTER: 1724 text = Bundle.getMessage("XNetMessageRequestServiceModeWriteRegister",getElement(2),getElement(3)); 1725 break; 1726 case XNetConstants.PROG_WRITE_MODE_CV: 1727 text = Bundle.getMessage("XNetMessageRequestServiceModeWriteDirect",getElement(2),getElement(3)); 1728 break; 1729 case XNetConstants.PROG_WRITE_MODE_PAGED: 1730 text = Bundle.getMessage("XNetMessageRequestServiceModeWritePaged",getElement(2),getElement(3)); 1731 break; 1732 case XNetConstants.PROG_WRITE_MODE_CV_V36: 1733 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_WRITE_DIRECT_V_36,(getElement(2)== 0 ? 1024 : getElement(2)),getElement(3)); 1734 break; 1735 case (XNetConstants.PROG_WRITE_MODE_CV_V36 + 1): 1736 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_WRITE_DIRECT_V_36,(256 + getElement(2)),getElement(3)); 1737 break; 1738 case (XNetConstants.PROG_WRITE_MODE_CV_V36 + 2): 1739 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_WRITE_DIRECT_V_36,(512 + getElement(2)),getElement(3)); 1740 break; 1741 case (XNetConstants.PROG_WRITE_MODE_CV_V36 + 3): 1742 text = Bundle.getMessage(X_NET_MESSAGE_REQUEST_SERVICE_MODE_WRITE_DIRECT_V_36,(768 + getElement(2)),getElement(3)); 1743 break; 1744 default: 1745 text = toString(); 1746 } 1747 } else if (getElement(0) == XNetConstants.OPS_MODE_PROG_REQ) { 1748 switch (getElement(1)) { 1749 case XNetConstants.OPS_MODE_PROG_WRITE_REQ: 1750 if ((getElement(4) & 0xEC) == 0xEC 1751 || (getElement(4) & 0xE4) == 0xE4) { 1752 String message = ""; 1753 if ((getElement(4) & 0xEC) == 0xEC) { 1754 message ="XNetMessageOpsModeByteWrite"; 1755 } else if ((getElement(4) & 0xE4) == 0xE4) { 1756 message ="XNetMessageOpsModeByteVerify"; 1757 } 1758 text = Bundle.getMessage(message, 1759 getElement(6), 1760 (1 + getElement(5) + ((getElement(4) & 0x03) << 8)), 1761 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1762 break; 1763 } else if ((getElement(4) & 0xE8) == 0xE8) { 1764 String message; 1765 if ((getElement(6) & 0x10) == 0x10) { 1766 message ="XNetMessageOpsModeBitVerify"; 1767 } else { 1768 message ="XNetMessageOpsModeBitWrite"; 1769 } 1770 text = Bundle.getMessage(message, 1771 ((getElement(6) & 0x08) >> 3), 1772 (1 + getElement(5) + ((getElement(4) & 0x03) << 8)), 1773 (getElement(6) & 0x07), 1774 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1775 break; 1776 } 1777 //$FALL-THROUGH$ 1778 default: 1779 text = toString(); 1780 } 1781 // Next, decode the locomotive operation requests 1782 } else if (getElement(0) == XNetConstants.LOCO_OPER_REQ) { 1783 text = "Mobile Decoder Operations Request: "; 1784 int speed; 1785 String direction; 1786 switch (getElement(1)) { 1787 case XNetConstants.LOCO_SPEED_14: 1788 if ((getElement(4) & 0x80) != 0) { 1789 direction = Bundle.getMessage(FORWARD); 1790 } else { 1791 direction = Bundle.getMessage(REVERSE); 1792 } 1793 text = text 1794 + Bundle.getMessage(X_NET_MESSAGE_SET_SPEED, 1795 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))) 1796 + " " + (getElement(4) & 0x0f) 1797 + " " + Bundle.getMessage(X_NET_MESSAGE_SET_DIRECTION, direction); 1798 text += " " + Bundle.getMessage(SPEED_STEP_MODE_X, 14) + "."; 1799 break; 1800 case XNetConstants.LOCO_SPEED_27: 1801 text = text 1802 + Bundle.getMessage(X_NET_MESSAGE_SET_SPEED, 1803 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))) 1804 + " "; 1805 if(log.isDebugEnabled()) { 1806 log.debug("LOCO_SPEED_27 {} {}", LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)), text); 1807 // address printed as: "1234" = OK 1808 // address printed as: "1,234" = WRONG 1809 } 1810 speed 1811 = (((getElement(4) & 0x10) >> 4) 1812 + ((getElement(4) & 0x0F) << 1)); 1813 if (speed >= 3) { 1814 speed -= 3; 1815 } 1816 text += speed; 1817 if ((getElement(4) & 0x80) != 0) { 1818 text += " " + Bundle.getMessage(X_NET_MESSAGE_SET_DIRECTION, Bundle.getMessage(FORWARD)); 1819 } else { 1820 text += " " + Bundle.getMessage(X_NET_MESSAGE_SET_DIRECTION, Bundle.getMessage(REVERSE)); 1821 } 1822 text += " " + Bundle.getMessage(SPEED_STEP_MODE_X, 27) + "."; 1823 break; 1824 case XNetConstants.LOCO_SPEED_28: 1825 text = text 1826 + Bundle.getMessage(X_NET_MESSAGE_SET_SPEED, 1827 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))) 1828 + " "; 1829 speed 1830 = (((getElement(4) & 0x10) >> 4) 1831 + ((getElement(4) & 0x0F) << 1)); 1832 if (speed >= 3) { 1833 speed -= 3; 1834 } 1835 text += speed; 1836 if ((getElement(4) & 0x80) != 0) { 1837 text += " " + Bundle.getMessage(X_NET_MESSAGE_SET_DIRECTION, Bundle.getMessage(FORWARD)); 1838 } else { 1839 text += " " + Bundle.getMessage(X_NET_MESSAGE_SET_DIRECTION, Bundle.getMessage(REVERSE)); 1840 } 1841 text += " " + Bundle.getMessage(SPEED_STEP_MODE_X, 28) + "."; 1842 break; 1843 case XNetConstants.LOCO_SPEED_128: 1844 if ((getElement(4) & 0x80) != 0) { 1845 direction = Bundle.getMessage(FORWARD); 1846 } else { 1847 direction = Bundle.getMessage(REVERSE); 1848 } 1849 text = text 1850 + Bundle.getMessage(X_NET_MESSAGE_SET_SPEED, 1851 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))) 1852 + " " 1853 + (getElement(4) & 0x7F) + " " + Bundle.getMessage(X_NET_MESSAGE_SET_DIRECTION, direction); 1854 text += " " + Bundle.getMessage(SPEED_STEP_MODE_X, 128) + "."; 1855 break; 1856 case XNetConstants.LOCO_SET_FUNC_GROUP1: 1857 text = text + buildSetFunctionGroup1MonitorString(); 1858 break; 1859 case XNetConstants.LOCO_SET_FUNC_GROUP2: 1860 text = text + buildSetFunctionGroup2MonitorString(); 1861 break; 1862 case XNetConstants.LOCO_SET_FUNC_GROUP3: 1863 text = text + buildSetFunctionGroup3MonitorString(); 1864 break; 1865 case XNetConstants.LOCO_SET_FUNC_GROUP4: 1866 text = text + buildSetFunctionGroup4MonitorString(); 1867 break; 1868 case XNetConstants.LOCO_SET_FUNC_GROUP5: 1869 text = text + buildSetFunctionGroup5MonitorString(); 1870 break; 1871 case XNetConstants.LOCO_SET_FUNC_GROUP6: 1872 text = text + buildSetFunctionGroup6MonitorString(); 1873 break; 1874 case XNetConstants.LOCO_SET_FUNC_GROUP7: 1875 text = text + buildSetFunctionGroup7MonitorString(); 1876 break; 1877 case XNetConstants.LOCO_SET_FUNC_GROUP8: 1878 text = text + buildSetFunctionGroup8MonitorString(); 1879 break; 1880 case XNetConstants.LOCO_SET_FUNC_GROUP9: 1881 text = text + buildSetFunctionGroup9MonitorString(); 1882 break; 1883 case XNetConstants.LOCO_SET_FUNC_GROUP10: 1884 text = text + buildSetFunctionGroup10MonitorString(); 1885 break; 1886 case XNetConstants.LOCO_SET_FUNC_GROUP1_MOMENTARY: 1887 text = text + buildSetFunctionGroup1MomentaryMonitorString(); 1888 break; 1889 case XNetConstants.LOCO_SET_FUNC_GROUP2_MOMENTARY: 1890 text = text + buildSetFunctionGroup2MomentaryMonitorString(); 1891 break; 1892 case XNetConstants.LOCO_SET_FUNC_GROUP3_MOMENTARY: 1893 text = text + buildSetFunctionGroup3MomentaryMonitorString(); 1894 break; 1895 case XNetConstants.LOCO_SET_FUNC_GROUP4_MOMENTARY: 1896 text = text + buildSetFunctionGroup4MomentaryMonitorString(); 1897 break; 1898 case XNetConstants.LOCO_SET_FUNC_GROUP5_MOMENTARY: 1899 text = text + buildSetFunctionGroup5MomentaryMonitorString(); 1900 break; 1901 case XNetConstants.LOCO_SET_FUNC_GROUP6_MOMENTARY: 1902 text = text + buildSetFunctionGroup6MomentaryMonitorString(); 1903 break; 1904 case XNetConstants.LOCO_SET_FUNC_GROUP7_MOMENTARY: 1905 text = text + buildSetFunctionGroup7MomentaryMonitorString(); 1906 break; 1907 case XNetConstants.LOCO_SET_FUNC_GROUP8_MOMENTARY: 1908 text = text + buildSetFunctionGroup8MomentaryMonitorString(); 1909 break; 1910 case XNetConstants.LOCO_SET_FUNC_GROUP9_MOMENTARY: 1911 text = text + buildSetFunctionGroup9MomentaryMonitorString(); 1912 break; 1913 case XNetConstants.LOCO_SET_FUNC_GROUP10_MOMENTARY: 1914 text = text + buildSetFunctionGroup10MomentaryMonitorString(); 1915 break; 1916 case XNetConstants.LOCO_ADD_MULTI_UNIT_REQ: 1917 text = Bundle.getMessage("XNetMessageAddToConsistDirNormalRequest", 1918 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)), 1919 getElement(4)); 1920 break; 1921 case (XNetConstants.LOCO_ADD_MULTI_UNIT_REQ | 0x01): 1922 text = Bundle.getMessage("XNetMessageAddToConsistDirReverseRequest", 1923 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)), 1924 getElement(4)); 1925 break; 1926 case (XNetConstants.LOCO_REM_MULTI_UNIT_REQ): 1927 text = Bundle.getMessage("XNetMessageRemoveFromConsistRequest", 1928 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)), 1929 getElement(4)); 1930 break; 1931 case (XNetConstants.LOCO_IN_MULTI_UNIT_REQ_FORWARD): 1932 text = Bundle.getMessage("XNetMessageSearchCSStackForwardNextMULoco", 1933 getElement(2), 1934 LenzCommandStation.calcLocoAddress(getElement(3), getElement(4))); 1935 break; 1936 case (XNetConstants.LOCO_IN_MULTI_UNIT_REQ_BACKWARD): 1937 text = Bundle.getMessage("XNetMessageSearchCSStackBackwardNextMULoco", 1938 getElement(2), 1939 LenzCommandStation.calcLocoAddress(getElement(3), getElement(4))); 1940 break; 1941 default: 1942 text = toString(); 1943 } 1944 // Emergency Stop a locomotive 1945 } else if (getElement(0) == XNetConstants.EMERGENCY_STOP) { 1946 text = Bundle.getMessage("XNetMessageAddressedEmergencyStopRequest", 1947 LenzCommandStation.calcLocoAddress(getElement(1), getElement(2))); 1948 // Disolve or Establish a Double Header 1949 } else if (getElement(0) == XNetConstants.LOCO_DOUBLEHEAD 1950 && getElement(1) == XNetConstants.LOCO_DOUBLEHEAD_BYTE2) { 1951 int loco1 = LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)); 1952 int loco2 = LenzCommandStation.calcLocoAddress(getElement(4), getElement(5)); 1953 if (loco2 == 0) { 1954 text = Bundle.getMessage("XNetMessageDisolveDoubleHeaderRequest",loco1); 1955 } else { 1956 text = Bundle.getMessage("XNetMessageBuildDoubleHeaderRequest",loco1,loco2); 1957 } 1958 // Locomotive Status Request messages 1959 } else if (getElement(0) == XNetConstants.LOCO_STATUS_REQ) { 1960 switch (getElement(1)) { 1961 case XNetConstants.LOCO_INFO_REQ_FUNC: 1962 text = Bundle.getMessage("XNetMessageRequestLocoFunctionMomStatus", 1963 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1964 break; 1965 case XNetConstants.LOCO_INFO_REQ_FUNC_HI_ON: 1966 text = Bundle.getMessage("XNetMessageRequestLocoFunctionHighStatus", 1967 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1968 break; 1969 case XNetConstants.LOCO_INFO_REQ_FUNC_HI_MOM: 1970 text = Bundle.getMessage("XNetMessageRequestLocoFunctionHighMomStatus", 1971 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1972 break; 1973 case XNetConstants.LOCO_INFO_REQ_V3: 1974 text = Bundle.getMessage("XNetMessageRequestLocoInfo", 1975 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1976 break; 1977 case XNetConstants.LOCO_STACK_SEARCH_FWD: 1978 text = Bundle.getMessage("XNetMessageSearchCSStackForward", 1979 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1980 break; 1981 case XNetConstants.LOCO_STACK_SEARCH_BKWD: 1982 text = Bundle.getMessage("XNetMessageSearchCSStackBackward", 1983 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1984 break; 1985 case XNetConstants.LOCO_STACK_DELETE: 1986 text = Bundle.getMessage("XNetMessageDeleteAddressOnStack", 1987 LenzCommandStation.calcLocoAddress(getElement(2), getElement(3))); 1988 break; 1989 default: 1990 text = toString(); 1991 } 1992 } else if(getElement(0) == XNetConstants.CS_MULTI_UNIT_REQ) { 1993 if (getElement(1) == XNetConstants.CS_MULTI_UNIT_REQ_FWD){ 1994 text = Bundle.getMessage("XNetMessageSearchCSStackForwardConsistAddress", 1995 getElement(2)); 1996 } else if(getElement(1) == XNetConstants.CS_MULTI_UNIT_REQ_BKWD){ 1997 text = Bundle.getMessage("XNetMessageSearchCSStackBackwardConsistAddress", 1998 getElement(2)); 1999 } else { 2000 text = toString(); 2001 } 2002 // Accessory Info Request message 2003 } else if (getElement(0) == XNetConstants.ACC_INFO_REQ) { 2004 String nibblekey=(((getElement(2) & 0x01) == 0x01) ? "FeedbackEncoderUpperNibble" : "FeedbackEncoderLowerNibble"); 2005 text = Bundle.getMessage("XNetMessageFeedbackRequest", 2006 getElement(1), 2007 Bundle.getMessage(nibblekey)); 2008 } else if (getElement(0) == XNetConstants.ACC_OPER_REQ) { 2009 String messageKey =(((getElement(2) & 0x08) == 0x08) ? "XNetMessageAccessoryDecoderOnRequest" : "XNetMessageAccessoryDecoderOffRequest"); 2010 int baseaddress = getElement(1); 2011 int subaddress = ((getElement(2) & 0x06) >> 1); 2012 int address = (baseaddress * 4) + subaddress + 1; 2013 int output = (getElement(2) & 0x01); 2014 text = Bundle.getMessage(messageKey,address, baseaddress,subaddress,output); 2015 } else if (getElement(0) == XNetConstants.ALL_ESTOP) { 2016 text = Bundle.getMessage("XNetMessageRequestEmergencyStop"); 2017 } else { 2018 text = toString(); 2019 } 2020 return text; 2021 } 2022 2023 private String buildSetFunctionGroup1MonitorString() { 2024 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 1) + 2025 " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2026 int element4 = getElement(4); 2027 if ((element4 & 0x10) != 0) { 2028 text += "F0 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2029 } else { 2030 text += "F0 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2031 } 2032 if ((element4 & 0x01) != 0) { 2033 text += "F1 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2034 } else { 2035 text += "F1 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2036 } 2037 if ((element4 & 0x02) != 0) { 2038 text += "F2 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2039 } else { 2040 text += "F2 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2041 } 2042 if ((element4 & 0x04) != 0) { 2043 text += "F3 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2044 } else { 2045 text += "F3 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2046 } 2047 if ((element4 & 0x08) != 0) { 2048 text += "F4 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2049 } else { 2050 text += "F4 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2051 2052 } 2053 return text; 2054 } 2055 2056 private String buildSetFunctionGroup2MonitorString(){ 2057 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 2) + " " 2058 + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2059 int element4 = getElement(4); 2060 if ((element4 & 0x01) != 0) { 2061 text += "F5 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2062 } else { 2063 text += "F5 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2064 } 2065 if ((element4 & 0x02) != 0) { 2066 text += "F6 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2067 } else { 2068 text += "F6 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2069 } 2070 if ((element4 & 0x04) != 0) { 2071 text += "F7 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2072 } else { 2073 text += "F7 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2074 } 2075 if ((element4 & 0x08) != 0) { 2076 text += "F8 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2077 } else { 2078 text += "F8 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2079 } 2080 return text; 2081 } 2082 2083 private String buildSetFunctionGroup3MonitorString() { 2084 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 3) + " " 2085 + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2086 int element4 = getElement(4); 2087 if ((element4 & 0x01) != 0) { 2088 text += "F9 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2089 } else { 2090 text += "F9 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2091 } 2092 if ((element4 & 0x02) != 0) { 2093 text += "F10 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2094 } else { 2095 text += "F10 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2096 } 2097 if ((element4 & 0x04) != 0) { 2098 text += "F11 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2099 } else { 2100 text += "F11 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2101 } 2102 if ((element4 & 0x08) != 0) { 2103 text += "F12 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2104 } else { 2105 text += "F12 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2106 } 2107 return text; 2108 } 2109 2110 private String buildSetFunctionGroup4MonitorString() { 2111 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 4) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2112 int element4 = getElement(4); 2113 if ((element4 & 0x01) != 0) { 2114 text += "F13 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2115 } else { 2116 text += "F13 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2117 } 2118 if ((element4 & 0x02) != 0) { 2119 text += "F14 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2120 } else { 2121 text += "F14 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2122 } 2123 if ((element4 & 0x04) != 0) { 2124 text += "F15 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2125 } else { 2126 text += "F15 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2127 } 2128 if ((element4 & 0x08) != 0) { 2129 text += "F16 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2130 } else { 2131 text += "F16 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2132 } 2133 if ((element4 & 0x10) != 0) { 2134 text += "F17 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2135 } else { 2136 text += "F17 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2137 } 2138 if ((element4 & 0x20) != 0) { 2139 text += "F18 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2140 } else { 2141 text += "F18 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2142 } 2143 if ((element4 & 0x40) != 0) { 2144 text += "F19 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2145 } else { 2146 text += "F19 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2147 } 2148 if ((element4 & 0x80) != 0) { 2149 text += "F20 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2150 } else { 2151 text += "F20 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2152 } 2153 return text; 2154 } 2155 2156 private String buildSetFunctionGroup5MonitorString() { 2157 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 5) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2158 int element4 = getElement(4); 2159 if ((element4 & 0x01) != 0) { 2160 text += "F21 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2161 } else { 2162 text += "F21 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2163 } 2164 if ((element4 & 0x02) != 0) { 2165 text += "F22 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2166 } else { 2167 text += "F22 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2168 } 2169 if ((element4 & 0x04) != 0) { 2170 text += "F23 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2171 } else { 2172 text += "F23 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2173 } 2174 if ((element4 & 0x08) != 0) { 2175 text += "F24 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2176 } else { 2177 text += "F24 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2178 } 2179 if ((element4 & 0x10) != 0) { 2180 text += "F25 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2181 } else { 2182 text += "F25 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2183 } 2184 if ((element4 & 0x20) != 0) { 2185 text += "F26 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2186 } else { 2187 text += "F26 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2188 } 2189 if ((element4 & 0x40) != 0) { 2190 text += "F27 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2191 } else { 2192 text += "F27 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2193 } 2194 if ((element4 & 0x80) != 0) { 2195 text += "F28 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2196 } else { 2197 text += "F28 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2198 } 2199 return text; 2200 } 2201 2202 private String buildSetFunctionGroup6MonitorString() { 2203 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 6) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2204 int element4 = getElement(4); 2205 if ((element4 & 0x01) != 0) { 2206 text += "F29 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2207 } else { 2208 text += "F29 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2209 } 2210 if ((element4 & 0x02) != 0) { 2211 text += "F30 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2212 } else { 2213 text += "F30 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2214 } 2215 if ((element4 & 0x04) != 0) { 2216 text += "F31 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2217 } else { 2218 text += "F31 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2219 } 2220 if ((element4 & 0x08) != 0) { 2221 text += "F32 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2222 } else { 2223 text += "F32 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2224 } 2225 if ((element4 & 0x10) != 0) { 2226 text += "F33 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2227 } else { 2228 text += "F33 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2229 } 2230 if ((element4 & 0x20) != 0) { 2231 text += "F34 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2232 } else { 2233 text += "F34 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2234 } 2235 if ((element4 & 0x40) != 0) { 2236 text += "F35 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2237 } else { 2238 text += "F35 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2239 } 2240 if ((element4 & 0x80) != 0) { 2241 text += "F36 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2242 } else { 2243 text += "F36 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2244 } 2245 return text; 2246 } 2247 2248 private String buildSetFunctionGroup7MonitorString() { 2249 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 7) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2250 int element4 = getElement(4); 2251 if ((element4 & 0x01) != 0) { 2252 text += "F37 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2253 } else { 2254 text += "F37 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2255 } 2256 if ((element4 & 0x02) != 0) { 2257 text += "F38 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2258 } else { 2259 text += "F38 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2260 } 2261 if ((element4 & 0x04) != 0) { 2262 text += "F39 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2263 } else { 2264 text += "F39 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2265 } 2266 if ((element4 & 0x08) != 0) { 2267 text += "F40 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2268 } else { 2269 text += "F40 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2270 } 2271 if ((element4 & 0x10) != 0) { 2272 text += "F41 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2273 } else { 2274 text += "F41 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2275 } 2276 if ((element4 & 0x20) != 0) { 2277 text += "F42 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2278 } else { 2279 text += "F42 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2280 } 2281 if ((element4 & 0x40) != 0) { 2282 text += "F43 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2283 } else { 2284 text += "F43 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2285 } 2286 if ((element4 & 0x80) != 0) { 2287 text += "F44 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2288 } else { 2289 text += "F44 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2290 } 2291 return text; 2292 } 2293 2294 private String buildSetFunctionGroup8MonitorString() { 2295 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 8) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2296 int element4 = getElement(4); 2297 if ((element4 & 0x01) != 0) { 2298 text += "F45 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2299 } else { 2300 text += "F45 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2301 } 2302 if ((element4 & 0x02) != 0) { 2303 text += "F46 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2304 } else { 2305 text += "F46 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2306 } 2307 if ((element4 & 0x04) != 0) { 2308 text += "F47 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2309 } else { 2310 text += "F47 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2311 } 2312 if ((element4 & 0x08) != 0) { 2313 text += "F48 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2314 } else { 2315 text += "F48 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2316 } 2317 if ((element4 & 0x10) != 0) { 2318 text += "F49 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2319 } else { 2320 text += "F49 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2321 } 2322 if ((element4 & 0x20) != 0) { 2323 text += "F50 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2324 } else { 2325 text += "F50 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2326 } 2327 if ((element4 & 0x40) != 0) { 2328 text += "F51 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2329 } else { 2330 text += "F51 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2331 } 2332 if ((element4 & 0x80) != 0) { 2333 text += "F52 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2334 } else { 2335 text += "F52 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2336 } 2337 return text; 2338 } 2339 2340 private String buildSetFunctionGroup9MonitorString() { 2341 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 9) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2342 int element4 = getElement(4); 2343 if ((element4 & 0x01) != 0) { 2344 text += "F53 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2345 } else { 2346 text += "F53 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2347 } 2348 if ((element4 & 0x02) != 0) { 2349 text += "F54 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2350 } else { 2351 text += "F54 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2352 } 2353 if ((element4 & 0x04) != 0) { 2354 text += "F55 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2355 } else { 2356 text += "F55 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2357 } 2358 if ((element4 & 0x08) != 0) { 2359 text += "F56 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2360 } else { 2361 text += "F56 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2362 } 2363 if ((element4 & 0x10) != 0) { 2364 text += "F57 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2365 } else { 2366 text += "F57 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2367 } 2368 if ((element4 & 0x20) != 0) { 2369 text += "F58 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2370 } else { 2371 text += "F58 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2372 } 2373 if ((element4 & 0x40) != 0) { 2374 text += "F59 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2375 } else { 2376 text += "F59 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2377 } 2378 if ((element4 & 0x80) != 0) { 2379 text += "F60 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2380 } else { 2381 text += "F60 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2382 } 2383 return text; 2384 } 2385 2386 private String buildSetFunctionGroup10MonitorString() { 2387 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X, 10) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2388 int element4 = getElement(4); 2389 if ((element4 & 0x01) != 0) { 2390 text += "F61 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2391 } else { 2392 text += "F61 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2393 } 2394 if ((element4 & 0x02) != 0) { 2395 text += "F62 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2396 } else { 2397 text += "F62 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2398 } 2399 if ((element4 & 0x04) != 0) { 2400 text += "F63 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2401 } else { 2402 text += "F63 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2403 } 2404 if ((element4 & 0x08) != 0) { 2405 text += "F64 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2406 } else { 2407 text += "F64 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2408 } 2409 if ((element4 & 0x10) != 0) { 2410 text += "F65 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2411 } else { 2412 text += "F65 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2413 } 2414 if ((element4 & 0x20) != 0) { 2415 text += "F66 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2416 } else { 2417 text += "F66 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2418 } 2419 if ((element4 & 0x40) != 0) { 2420 text += "F67 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2421 } else { 2422 text += "F67 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2423 } 2424 if ((element4 & 0x80) != 0) { 2425 text += "F68 " + Bundle.getMessage(POWER_STATE_ON) + "; "; 2426 } else { 2427 text += "F68 " + Bundle.getMessage(POWER_STATE_OFF) + "; "; 2428 } 2429 return text; 2430 } 2431 2432 2433 2434 private String buildSetFunctionGroup1MomentaryMonitorString() { 2435 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 1) + " " 2436 + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2437 int element4 = getElement(4); 2438 if ((element4 & 0x10) == 0) { 2439 text += "F0 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2440 } else { 2441 text += "F0 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2442 } 2443 if ((element4 & 0x01) == 0) { 2444 text += "F1 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2445 } else { 2446 text += "F1 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2447 } 2448 if ((element4 & 0x02) == 0) { 2449 text += "F2 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2450 } else { 2451 text += "F2 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2452 } 2453 if ((element4 & 0x04) == 0) { 2454 text += "F3 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2455 } else { 2456 text += "F3 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2457 } 2458 if ((element4 & 0x08) == 0) { 2459 text += "F4 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2460 } else { 2461 text += "F4 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2462 } 2463 return text; 2464 } 2465 2466 private String buildSetFunctionGroup2MomentaryMonitorString() { 2467 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 2) + " " 2468 + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2469 int element4 = getElement(4); 2470 if ((element4 & 0x01) == 0) { 2471 text += "F5 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2472 } else { 2473 text += "F5 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2474 } 2475 if ((element4 & 0x02) == 0) { 2476 text += "F6 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2477 } else { 2478 text += "F6 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2479 } 2480 if ((element4 & 0x04) == 0) { 2481 text += "F7 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2482 } else { 2483 text += "F7 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2484 } 2485 if ((element4 & 0x08) == 0) { 2486 text += "F8 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2487 } else { 2488 text += "F8 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2489 } 2490 return text; 2491 } 2492 2493 private String buildSetFunctionGroup3MomentaryMonitorString() { 2494 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 3) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2495 int element4 = getElement(4); 2496 if ((element4 & 0x01) == 0) { 2497 text += "F9 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2498 } else { 2499 text += "F9 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2500 } 2501 if ((element4 & 0x02) == 0) { 2502 text += "F10 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2503 } else { 2504 text += "F10 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2505 } 2506 if ((element4 & 0x04) == 0) { 2507 text += "F11 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2508 } else { 2509 text += "F11 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2510 } 2511 if ((element4 & 0x08) == 0) { 2512 text += "F12 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2513 } else { 2514 text += "F12 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2515 } 2516 return text; 2517 } 2518 2519 private String buildSetFunctionGroup4MomentaryMonitorString() { 2520 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 4) + " " 2521 + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2522 int element4 = getElement(4); 2523 if ((element4 & 0x01) == 0) { 2524 text += "F13 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2525 } else { 2526 text += "F13 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2527 } 2528 if ((element4 & 0x02) == 0) { 2529 text += "F14 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2530 } else { 2531 text += "F14 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2532 } 2533 if ((element4 & 0x04) == 0) { 2534 text += "F15 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2535 } else { 2536 text += "F15 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2537 } 2538 if ((element4 & 0x08) == 0) { 2539 text += "F16 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2540 } else { 2541 text += "F16 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2542 } 2543 if ((element4 & 0x10) == 0) { 2544 text += "F17 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2545 } else { 2546 text += "F17 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2547 } 2548 if ((element4 & 0x20) == 0) { 2549 text += "F18 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2550 } else { 2551 text += "F18 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2552 } 2553 if ((element4 & 0x40) == 0) { 2554 text += "F19 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2555 } else { 2556 text += "F19 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2557 } 2558 if ((element4 & 0x80) == 0) { 2559 text += "F20 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2560 } else { 2561 text += "F20 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2562 } 2563 return text; 2564 } 2565 2566 private String buildSetFunctionGroup5MomentaryMonitorString() { 2567 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 5) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2568 int element4 = getElement(4); 2569 if ((element4 & 0x01) == 0) { 2570 text += "F21 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2571 } else { 2572 text += "F21 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2573 } 2574 if ((element4 & 0x02) == 0) { 2575 text += "F22 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2576 } else { 2577 text += "F22 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2578 } 2579 if ((element4 & 0x04) == 0) { 2580 text += "F23 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2581 } else { 2582 text += "F23 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2583 } 2584 if ((element4 & 0x08) == 0) { 2585 text += "F24 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2586 } else { 2587 text += "F24 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2588 } 2589 if ((element4 & 0x10) == 0) { 2590 text += "F25 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2591 } else { 2592 text += "F25 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2593 } 2594 if ((element4 & 0x20) == 0) { 2595 text += "F26 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2596 } else { 2597 text += "F26 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2598 } 2599 if ((element4 & 0x40) == 0) { 2600 text += "F27 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2601 } else { 2602 text += "F27 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2603 } 2604 if ((element4 & 0x80) == 0) { 2605 text += "F28 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2606 } else { 2607 text += "F28 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2608 } 2609 return text; 2610 } 2611 2612 private String buildSetFunctionGroup6MomentaryMonitorString() { 2613 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 6) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2614 int element4 = getElement(4); 2615 if ((element4 & 0x01) == 0) { 2616 text += "F29 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2617 } else { 2618 text += "F29 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2619 } 2620 if ((element4 & 0x02) == 0) { 2621 text += "F30 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2622 } else { 2623 text += "F30 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2624 } 2625 if ((element4 & 0x04) == 0) { 2626 text += "F31 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2627 } else { 2628 text += "F31 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2629 } 2630 if ((element4 & 0x08) == 0) { 2631 text += "F32 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2632 } else { 2633 text += "F32 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2634 } 2635 if ((element4 & 0x10) == 0) { 2636 text += "F33 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2637 } else { 2638 text += "F33 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2639 } 2640 if ((element4 & 0x20) == 0) { 2641 text += "F34 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2642 } else { 2643 text += "F34 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2644 } 2645 if ((element4 & 0x40) == 0) { 2646 text += "F35 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2647 } else { 2648 text += "F35 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2649 } 2650 if ((element4 & 0x80) == 0) { 2651 text += "F36 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2652 } else { 2653 text += "F36 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2654 } 2655 return text; 2656 } 2657 2658 private String buildSetFunctionGroup7MomentaryMonitorString() { 2659 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 7) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2660 int element4 = getElement(4); 2661 if ((element4 & 0x01) == 0) { 2662 text += "F37 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2663 } else { 2664 text += "F37 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2665 } 2666 if ((element4 & 0x02) == 0) { 2667 text += "F38 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2668 } else { 2669 text += "F38 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2670 } 2671 if ((element4 & 0x04) == 0) { 2672 text += "F39 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2673 } else { 2674 text += "F39 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2675 } 2676 if ((element4 & 0x08) == 0) { 2677 text += "F40 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2678 } else { 2679 text += "F40 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2680 } 2681 if ((element4 & 0x10) == 0) { 2682 text += "F41 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2683 } else { 2684 text += "F41 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2685 } 2686 if ((element4 & 0x20) == 0) { 2687 text += "F42 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2688 } else { 2689 text += "F42 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2690 } 2691 if ((element4 & 0x40) == 0) { 2692 text += "F43 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2693 } else { 2694 text += "F43 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2695 } 2696 if ((element4 & 0x80) == 0) { 2697 text += "F44 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2698 } else { 2699 text += "F44 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2700 } 2701 return text; 2702 } 2703 2704 private String buildSetFunctionGroup8MomentaryMonitorString() { 2705 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 8) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2706 int element4 = getElement(4); 2707 if ((element4 & 0x01) == 0) { 2708 text += "F45 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2709 } else { 2710 text += "F45 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2711 } 2712 if ((element4 & 0x02) == 0) { 2713 text += "F46 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2714 } else { 2715 text += "F46 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2716 } 2717 if ((element4 & 0x04) == 0) { 2718 text += "F47 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2719 } else { 2720 text += "F47 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2721 } 2722 if ((element4 & 0x08) == 0) { 2723 text += "F48 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2724 } else { 2725 text += "F48 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2726 } 2727 if ((element4 & 0x10) == 0) { 2728 text += "F49 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2729 } else { 2730 text += "F49 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2731 } 2732 if ((element4 & 0x20) == 0) { 2733 text += "F50 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2734 } else { 2735 text += "F50 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2736 } 2737 if ((element4 & 0x40) == 0) { 2738 text += "F51 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2739 } else { 2740 text += "F51 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2741 } 2742 if ((element4 & 0x80) == 0) { 2743 text += "F52 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2744 } else { 2745 text += "F52 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2746 } 2747 return text; 2748 } 2749 2750 private String buildSetFunctionGroup9MomentaryMonitorString() { 2751 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 9) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2752 int element4 = getElement(4); 2753 if ((element4 & 0x01) == 0) { 2754 text += "F53 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2755 } else { 2756 text += "F53 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2757 } 2758 if ((element4 & 0x02) == 0) { 2759 text += "F54 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2760 } else { 2761 text += "F54 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2762 } 2763 if ((element4 & 0x04) == 0) { 2764 text += "F55 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2765 } else { 2766 text += "F55 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2767 } 2768 if ((element4 & 0x08) == 0) { 2769 text += "F56 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2770 } else { 2771 text += "F56 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2772 } 2773 if ((element4 & 0x10) == 0) { 2774 text += "F57 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2775 } else { 2776 text += "F57 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2777 } 2778 if ((element4 & 0x20) == 0) { 2779 text += "F58 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2780 } else { 2781 text += "F58 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2782 } 2783 if ((element4 & 0x40) == 0) { 2784 text += "F59 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2785 } else { 2786 text += "F59 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2787 } 2788 if ((element4 & 0x80) == 0) { 2789 text += "F60 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2790 } else { 2791 text += "F60 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2792 } 2793 return text; 2794 } 2795 2796 private String buildSetFunctionGroup10MomentaryMonitorString() { 2797 String text = Bundle.getMessage(X_NET_MESSAGE_SET_FUNCTION_GROUP_X_MOMENTARY, 10) + " " + LenzCommandStation.calcLocoAddress(getElement(2), getElement(3)) + " "; 2798 int element4 = getElement(4); 2799 if ((element4 & 0x01) == 0) { 2800 text += "F61 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2801 } else { 2802 text += "F61 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2803 } 2804 if ((element4 & 0x02) == 0) { 2805 text += "F62 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2806 } else { 2807 text += "F62 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2808 } 2809 if ((element4 & 0x04) == 0) { 2810 text += "F63 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2811 } else { 2812 text += "F63 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2813 } 2814 if ((element4 & 0x08) == 0) { 2815 text += "F64 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2816 } else { 2817 text += "F64 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2818 } 2819 if ((element4 & 0x10) == 0) { 2820 text += "F65 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2821 } else { 2822 text += "F65 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2823 } 2824 if ((element4 & 0x20) == 0) { 2825 text += "F66 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2826 } else { 2827 text += "F66 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2828 } 2829 if ((element4 & 0x40) == 0) { 2830 text += "F67 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2831 } else { 2832 text += "F67 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2833 } 2834 if ((element4 & 0x80) == 0) { 2835 text += "F68 " + Bundle.getMessage(FUNCTION_CONTINUOUS) + "; "; 2836 } else { 2837 text += "F68 " + Bundle.getMessage(FUNCTION_MOMENTARY) + "; "; 2838 } 2839 return text; 2840 } 2841 2842 // initialize logging 2843 private static final Logger log = LoggerFactory.getLogger(XNetMessage.class); 2844 2845}