Ejemplo n.º 1
0
  public void run() { // start a new thread
    // this thread has one task.  It repeatedly reads from the input pipe
    // and writes modified data to the output pipe.  This is the heart
    // of the command station simulation.
    if (log.isDebugEnabled()) {
      log.debug("Simulator Thread Started");
    }

    Random rgen = new Random();

    ConnectionStatus.instance()
        .setConnectionState(this.getCurrentPortName(), ConnectionStatus.CONNECTION_UP);
    for (; ; ) {
      DCCppMessage m = readMessage();
      if (log.isDebugEnabled()) {
        log.debug("Simulator Thread received message " + m.toString());
      }
      DCCppReply r = generateReply(m);
      // If generateReply() returns null, do nothing. No reply to send.
      if (r != null) {
        writeReply(r);
        if (log.isDebugEnabled()) {
          log.debug("Simulator Thread sent Reply" + r.toString());
        }
      }

      // Once every SENSOR_MSG_RATE loops, generate a random Sensor message.
      int rand = rgen.nextInt(SENSOR_MSG_RATE);
      if (rand == 1) {
        generateRandomSensorReply();
      }
    }
  }
Ejemplo n.º 2
0
  /**
   * Get characters from the input source, and file a message.
   *
   * <p>Returns only when the message is complete.
   *
   * <p>Only used in the Receive thread.
   *
   * @returns filled message
   * @throws IOException when presented by the input source.
   */
  private DCCppMessage loadChars() throws java.io.IOException {
    // Spin waiting for start-of-frame '<' character (and toss it)
    String s = new String();
    byte char1;
    boolean found_start = false;

    while (!found_start) {
      char1 = readByteProtected(inpipe);
      if ((char1 & 0xFF) == '<') {
        found_start = true;
        log.debug("Found starting < ");
        break; // A bit redundant with setting the loop condition true (false)
      } else {
        char1 = readByteProtected(inpipe);
      }
    }
    // Now, suck in the rest of the message...
    for (int i = 0; i < DCCppConstants.MAX_MESSAGE_SIZE; i++) {
      char1 = readByteProtected(inpipe);
      if (char1 == '>') {
        log.debug("msg found > ");
        // Don't store the >
        break;
      } else {
        log.debug("msg read byte {}", char1);
        char c = (char) (char1 & 0x00FF);
        s += Character.toString(c);
      }
    }
    // TODO: Still need to strip leading and trailing whitespace.
    log.debug("Complete message = {}", s.toString());
    return (DCCppMessage.parseDCCppMessage(s));
  }
Ejemplo n.º 3
0
  // generateReply is the heart of the simulation.  It translates an
  // incoming DCCppMessage into an outgoing DCCppReply.
  @SuppressWarnings("fallthrough")
  private DCCppReply generateReply(DCCppMessage msg) {
    String s, r;
    Pattern p;
    Matcher m;
    DCCppReply reply = null;

    log.debug("Generate Reply to message type {} string = {}", msg.getElement(0), msg.toString());

    switch (msg.getElement(0)) {
      case DCCppConstants.THROTTLE_CMD:
        log.debug("THROTTLE_CMD detected");
        s = msg.toString();
        try {
          p = Pattern.compile(DCCppConstants.THROTTLE_CMD_REGEX);
          m = p.matcher(s);
          if (!m.matches()) {
            log.error("Malformed Throttle Command: {}", s);
            return (null);
          }
          r = "T " + m.group(1) + " " + m.group(3) + " " + m.group(4);
          reply = DCCppReply.parseDCCppReply(r);
          log.debug("Reply generated = {}", reply.toString());
        } catch (PatternSyntaxException e) {
          log.error("Malformed pattern syntax! ");
          return (null);
        } catch (IllegalStateException e) {
          log.error("Group called before match operation executed string= " + s);
          return (null);
        } catch (IndexOutOfBoundsException e) {
          log.error("Index out of bounds string= " + s);
          return (null);
        }
        break;

      case DCCppConstants.TURNOUT_CMD:
        if (msg.isTurnoutAddMessage()) {
          log.debug("Add Turnout Message");
          r = "O";
        } else if (msg.isTurnoutDeleteMessage()) {
          log.debug("Delete Turnout Message");
          r = "O";
        } else if (msg.isListTurnoutsMessage()) {
          log.debug("List Turnouts Message");
          r = "H 1 27 3 1";
        } else {
          log.debug("TURNOUT_CMD detected");
          r = "H" + msg.getTOIDString() + " " + msg.getTOStateString();
        }
        reply = DCCppReply.parseDCCppReply(r);
        log.debug("Reply generated = {}", reply.toString());
        break;

      case DCCppConstants.SENSOR_CMD:
        if (msg.isSensorAddMessage()) {
          log.debug("SENSOR_CMD Add detected");
          s = msg.toString();
          r = "O"; // TODO: Randomize?
        } else if (msg.isSensorDeleteMessage()) {
          log.debug("SENSOR_CMD Delete detected");
          s = msg.toString();
          r = "O"; // TODO: Randomize?
        } else if (msg.isListSensorsMessage()) {
          r = "Q 1 4 1"; // TODO: DO this for real.
        } else {
          log.debug("Invalid SENSOR_CMD detected");
          r = "X";
        }
        reply = DCCppReply.parseDCCppReply(r);
        log.debug("Reply generated = {}", reply.toString());
        break;

      case DCCppConstants.PROG_WRITE_CV_BYTE:
        log.debug("PROG_WRITE_CV_BYTE detected");
        s = msg.toString();
        try {
          p = Pattern.compile(DCCppConstants.PROG_WRITE_BYTE_REGEX);
          m = p.matcher(s);
          if (!m.matches()) {
            log.error("Malformed ProgWriteCVByte Command: {}", s);
            return (null);
          }
          r = "r " + m.group(3) + " " + m.group(4) + " " + m.group(2);
          CVs[Integer.parseInt(m.group(1))] = Integer.parseInt(m.group(2));
          reply = DCCppReply.parseDCCppReply(r);
          log.debug("Reply generated = {}", reply.toString());
        } catch (PatternSyntaxException e) {
          log.error("Malformed pattern syntax! ");
          return (null);
        } catch (IllegalStateException e) {
          log.error("Group called before match operation executed string= " + s);
          return (null);
        } catch (IndexOutOfBoundsException e) {
          log.error("Index out of bounds string= " + s);
          return (null);
        }
        break;

      case DCCppConstants.PROG_WRITE_CV_BIT:
        log.debug("PROG_WRITE_CV_BIT detected");
        s = msg.toString();
        try {
          p = Pattern.compile(DCCppConstants.PROG_WRITE_BIT_REGEX);
          m = p.matcher(s);
          if (!m.matches()) {
            log.error("Malformed ProgWriteCVBit Command: {}", s);
            return (null);
          }
          r = "r " + m.group(4) + " " + m.group(5) + " " + m.group(3);
          int idx = Integer.parseInt(m.group(1));
          int bit = Integer.parseInt(m.group(2));
          int v = Integer.parseInt(m.group(3));
          if (v == 1) CVs[idx] = CVs[idx] | (0x0001 << bit);
          else CVs[idx] = CVs[idx] & ~(0x0001 << bit);
          reply = DCCppReply.parseDCCppReply(r);
          log.debug("Reply generated = {}", reply.toString());
        } catch (PatternSyntaxException e) {
          log.error("Malformed pattern syntax! ");
          return (null);
        } catch (IllegalStateException e) {
          log.error("Group called before match operation executed string= " + s);
          return (null);
        } catch (IndexOutOfBoundsException e) {
          log.error("Index out of bounds string= " + s);
          return (null);
        }
        break;

      case DCCppConstants.PROG_READ_CV:
        log.debug("PROG_READ_CV detected");
        s = msg.toString();
        try {
          p = Pattern.compile(DCCppConstants.PROG_READ_REGEX);
          m = p.matcher(s);
          if (!m.matches()) {
            log.error("Malformed PROG_READ_CV Command: {}", s);
            return (null);
          }
          // TODO: Work Magic Here to retrieve stored value.
          int cv = CVs[Integer.parseInt(m.group(1))];
          r = "r " + m.group(2) + " " + m.group(3) + " " + Integer.toString(cv);
          reply = DCCppReply.parseDCCppReply(r);
          log.debug("Reply generated = {}", reply.toString());
        } catch (PatternSyntaxException e) {
          log.error("Malformed pattern syntax! ");
          return (null);
        } catch (IllegalStateException e) {
          log.error("Group called before match operation executed string= " + s);
          return (null);
        } catch (IndexOutOfBoundsException e) {
          log.error("Index out of bounds string= " + s);
          return (null);
        }
        break;

      case DCCppConstants.TRACK_POWER_ON:
        log.debug("TRACK_POWER_ON detected");
        TrackPowerState = true;
        reply = DCCppReply.parseDCCppReply("p1");
        log.debug("Reply generated = {}", reply.toString());
        break;

      case DCCppConstants.TRACK_POWER_OFF:
        log.debug("TRACK_POWER_OFF detected");
        TrackPowerState = false;
        reply = DCCppReply.parseDCCppReply("p0");
        log.debug("Reply generated = {}", reply.toString());
        break;

      case DCCppConstants.READ_TRACK_CURRENT:
        log.debug("READ_TRACK_CURRENT detected");
        int randint = 480 + rgen.nextInt(64);
        reply =
            DCCppReply.parseDCCppReply("a " + (TrackPowerState ? Integer.toString(randint) : "0"));
        log.debug("Reply generated = {}", reply.toString());
        break;

      case DCCppConstants.READ_CS_STATUS:
        log.debug("READ_CS_STATUS detected");
        generateReadCSStatusReply(); // Handle this special.
        break;

        /*
               case DCCppConstants.QUERY_SENSOR_STATE:
            // Obsolete ??
            log.debug("QUERY_SENSOR_STATUS detected");
            s = msg.toString();
            try {
        	p = Pattern.compile(DCCppConstants.QUERY_SENSOR_REGEX);
        	m = p.matcher(s);
        	if (!m.matches()) {
        	    log.error("Malformed Sensor Query Command: {}", s);
        	    return(null);
        	}
        	r = "Q " + m.group(1) + " ";
        	// Fake reply: Odd sensors always active, even always inactive.
        	r += ((Integer.parseInt(m.group(1)) % 2) == 1 ? "1" : "0");
        	reply = new DCCppReply(r);
        	log.debug("Reply generated = {}", reply.toString());
            } catch (PatternSyntaxException e) {
        	log.error("Malformed pattern syntax! ");
        	return(null);
            } catch (IllegalStateException e) {
        	log.error("Group called before match operation executed string= " + s);
        	return(null);
            } catch (IndexOutOfBoundsException e) {
        	log.error("Index out of bounds string= " + s);
        	return(null);
            }
            break;
        */
      case DCCppConstants.FUNCTION_CMD:
      case DCCppConstants.ACCESSORY_CMD:
      case DCCppConstants.OPS_WRITE_CV_BYTE:
      case DCCppConstants.OPS_WRITE_CV_BIT:
      case DCCppConstants.WRITE_DCC_PACKET_MAIN:
      case DCCppConstants.WRITE_DCC_PACKET_PROG:
        log.debug("non-reply message detected");
        // Send no reply.
        return (null);

      default:
        return (null);
    }
    return (reply);
  }