예제 #1
0
public class Drip implements MessageListener {

  public static int SEND_COUNT = 12;
  public static int SEND_RATE = DripConsts.DRIP_TIMER_PERIOD;

  public static int WAKEUP_SEND_COUNT = 25;
  public static int WAKEUP_SEND_RATE = 40;

  private Logger log = Logger.getLogger(Drip.class.getName());

  private static final int IDLE = 0;
  private static final int PROBING = 1;
  private static final int SENDING_SEQNO = 2;
  private static final int SENT_SEQNO = 3;
  private static final int SENDING_NEW = 4;

  private int state = IDLE;

  int id;
  int seqno;
  int sendCount = 0;
  int maxSendCount;

  Timer trickle;
  TimerTask trickleTask;

  MoteIF moteIF;
  DripMsg dripMsg;
  boolean hasMessage = false;
  boolean sentOK = true;

  boolean wakeupMsg = false;

  public Drip(int id) {

    log.info("Started id=" + id);
    try {
      moteIF = new MoteIF();
      moteIF.registerListener(new DripMsg(), this);
    } catch (Exception e) {
      System.out.println("ERROR: Couldn't contact serial forwarder.");
      System.exit(1);
    }

    this.id = id;
  }

  public Drip(int id, MoteIF p_moteIF) {

    log.info("Started with own moteIF id=" + id);

    try {
      moteIF = p_moteIF;
      moteIF.registerListener(new DripMsg(), this);
    } catch (Exception e) {
      System.out.println("ERROR: Couldn't contact serial forwarder.");
      System.exit(1);
    }

    this.id = id;
  }

  void setupDrip(Message msg, int msgSize) {
    trickle = new Timer();
    trickleTask = new DripSender();
    dripMsg = new DripMsg(DripMsg.DEFAULT_MESSAGE_SIZE + msgSize);
    dripMsg.dataSet(msg.dataGet(), 0, dripMsg.offset_data(0), msgSize);
    sendCount = 0;
  }

  Message buildAddrMsg(int dest, Message msg, int msgSize) {
    AddressMsg addrMsg = new AddressMsg(AddressMsg.DEFAULT_MESSAGE_SIZE + msgSize);
    String moteid = Env.getenv("MOTEID");
    int source = 0xFFFF;

    if (moteid != null) {
      source = Integer.parseInt(moteid);
    }

    addrMsg.dataSet(msg.dataGet(), 0, addrMsg.offset_data(0), msgSize);

    addrMsg.set_dest(dest);
    addrMsg.set_source(source);

    return addrMsg;
  }

  public synchronized void send(Message msg, int msgSize) {
    setupDrip(msg, msgSize);

    state = PROBING;
    wakeupMsg = false;
    sendCount = 0;
    maxSendCount = SEND_COUNT;
    trickle.schedule(trickleTask, 0, 500);
    try {
      wait();
    } catch (InterruptedException e) {
      // return
    }
  }

  public synchronized void sendAddressed(int dest, Message msg, int msgSize) {

    AddressMsg addrMsg = (AddressMsg) buildAddrMsg(dest, msg, msgSize);
    send(addrMsg, msgSize + AddressMsg.DEFAULT_MESSAGE_SIZE);
  }

  public synchronized void sendUnreliable(Message msg, int msgSize) {
    setupDrip(msg, msgSize);

    state = SENDING_NEW;
    wakeupMsg = false;
    sendCount = 0;
    maxSendCount = 1;
    trickle.schedule(trickleTask, 0, SEND_RATE);
    try {
      wait();
    } catch (InterruptedException e) {
      // return
    }
  }

  public synchronized void sendAddressedUnreliable(int dest, Message msg, int msgSize) {
    AddressMsg addrMsg = (AddressMsg) buildAddrMsg(dest, msg, msgSize);
    sendUnreliable(addrMsg, msgSize + AddressMsg.DEFAULT_MESSAGE_SIZE);
  }

  public synchronized void sendWakeup(Message msg, int msgSize) {
    setupDrip(msg, msgSize);

    state = SENDING_NEW;
    wakeupMsg = true;
    sendCount = 0;
    maxSendCount = WAKEUP_SEND_COUNT;
    trickle.schedule(trickleTask, 0, WAKEUP_SEND_RATE);
    try {
      wait();
    } catch (InterruptedException e) {
      // return
    }
  }

  private synchronized void sendDone() {
    notifyAll();
    state = IDLE;
  }

  class DripSender extends TimerTask {

    public void run() {

      boolean stopSending = false;

      log.debug("DripSender.run(state=" + state + " sendCount= " + sendCount + ")");

      dripMsg.set_metadata_id((short) id);

      switch (state) {
        case PROBING:
          if (sendCount < maxSendCount) {
            log.debug("probing");
            dripMsg.set_metadata_seqno((byte) DripConsts.DRIP_SEQNO_OLDEST);
          } else {
            log.debug("probing finished");
            stopSending = true;
          }
          break;
        case SENDING_SEQNO:
          if (sendCount < maxSendCount) {
            log.debug("sending new seqno " + seqno);
            dripMsg.set_metadata_seqno((byte) seqno);
          } else {
            log.debug("sending finished");
            stopSending = true;
          }
          break;
        case SENDING_NEW:
          if (sendCount < maxSendCount) {
            log.debug("sending unreliably");
            dripMsg.set_metadata_seqno((byte) DripConsts.DRIP_SEQNO_NEWEST);
          } else {
            log.debug("sending unreliably finished");
            stopSending = true;
          }
          break;
        case SENT_SEQNO:
          log.debug("done sending");
          stopSending = true;
          return;
        default:
      }

      if (wakeupMsg == true) {
        dripMsg.set_metadata_seqno((short) ((dripMsg.get_metadata_seqno() + 1) % 256));
      }

      if (stopSending) {
        trickle.cancel();
        trickleTask.cancel();
        sendDone();
      } else {
        log.info(
            "Sending Msg " + sendCount + ": id=" + id + ",seqno=" + dripMsg.get_metadata_seqno());
        send(dripMsg);
        sendCount++;
      }
    }
  }

  private void send(Message m) {
    try {
      moteIF.send(MoteIF.TOS_BCAST_ADDR, m);
    } catch (IOException e) {
      e.printStackTrace();
      System.out.println("ERROR: Can't send message");
      System.exit(1);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void messageReceived(int to, Message m) {

    DripMsg msg = (DripMsg) m;

    int newId = msg.get_metadata_id();
    int newSeqno = msg.get_metadata_seqno();

    log.debug("Received Msg: id=" + newId + ",seqno=" + newSeqno);

    if (newId != id) {
      log.debug("dropped, not ID " + id);
      return;
    }

    if ((newSeqno & ~DripConsts.DRIP_WAKEUP_BIT) == DripConsts.DRIP_SEQNO_NEWEST) {
      log.debug("dropped, a special seqno " + newSeqno);
      return;
    }

    switch (state) {
      case PROBING:
        seqno = newSeqno;
        log.info(
            "Receive: id=" + id + ",seqno=" + dripMsg.get_metadata_seqno() + " Heard Old Seqno");
        incrementSeqno();
        state = SENDING_SEQNO;
      case SENDING_SEQNO:
        if (seqno == newSeqno) {
          log.info(
              "Receive: id=" + id + ",seqno=" + dripMsg.get_metadata_seqno() + " Heard New Seqno");
          trickle.cancel();
          trickleTask.cancel();
          sendDone();
        }
      default:
    }
  }

  private void incrementSeqno() {
    if (wakeupMsg && ((seqno & DripConsts.DRIP_WAKEUP_BIT) == 0)) {
      seqno = (seqno + 1) % 256;
    }

    if (!wakeupMsg && ((seqno & DripConsts.DRIP_WAKEUP_BIT) == 1)) {
      seqno = (seqno + 1) % 256;
    }

    seqno = (seqno + 1) % 256;
    seqno = (seqno + 1) % 256;

    while ((seqno & ~DripConsts.DRIP_WAKEUP_BIT) == DripConsts.DRIP_SEQNO_OLDEST
        || (seqno & ~DripConsts.DRIP_WAKEUP_BIT) == DripConsts.DRIP_SEQNO_NEWEST
        || (seqno & ~DripConsts.DRIP_WAKEUP_BIT) == DripConsts.DRIP_SEQNO_UNKNOWN) {

      seqno = (seqno + 1) % 256;
      seqno = (seqno + 1) % 256;
    }
  }

  private static int data = 1000;
  private static int channel = 254;
  private static boolean wakeup = false;

  public static void main(String[] args) {

    parseArgs(args);

    Drip drip = new Drip(channel);
    TestDripMsg msg = new TestDripMsg();
    msg.set_data((short) data);

    if (wakeup) {
      drip.sendWakeup(msg, TestDripMsg.DEFAULT_MESSAGE_SIZE);
    } else {
      drip.send(msg, TestDripMsg.DEFAULT_MESSAGE_SIZE);
    }
    System.exit(0);
  }

  private static void parseArgs(String args[]) {

    ArrayList cleanedArgs = new ArrayList();

    for (int i = 0; i < args.length; i++) {
      if (args[i].startsWith("--")) {

        // Parse Long Options
        String longopt = args[i].substring(2);

        if (longopt.equals("help")) {
          usage();
        }

      } else if (args[i].startsWith("-")) {

        // Parse Short Options
        String opt = args[i].substring(1);

        if (opt.equals("d")) {
          data = Integer.parseInt(args[++i]);
        } else if (opt.equals("w")) {
          wakeup = true;
        } else if (opt.equals("c")) {
          channel = Integer.parseInt(args[++i]);
        } else if (opt.equals("h")) {
          usage();
        }

      } else {

        // Place into args string
        cleanedArgs.add(args[i]);
      }
    }
  }

  private static void usage() {
    System.err.println("usage: java net.tinyos.drain.Drip <opts>");
    System.err.println("  -d <data value>");
    System.err.println("  -c <channel id>");
    System.err.println("  -w : send message with wakeup bit set");
    System.err.println("  -h, --help : this information");
    System.exit(1);
  }
}
예제 #2
0
public class DrainConnector implements MessageListener {

  public static int TOS_UART_ADDR = 0x7e;
  public static int DEFAULT_MOTE_ID = 0xfffe;
  public static int BCAST_ID = 0xff;

  private MoteIF moteIF;

  private Logger log = Logger.getLogger(DrainConnector.class.getName());

  private int spAddr;

  private Hashtable seqNos = new Hashtable();
  private HashMap idTable = new HashMap();

  public DrainConnector() {
    this(DrainLib.setSPAddr(), DrainLib.startMoteIF());
  }

  public DrainConnector(int p_spAddr, MoteIF p_moteIF) {
    spAddr = p_spAddr;
    moteIF = p_moteIF;
    moteIF.registerListener(new DrainMsg(), this);
    log.info("Started myAddr = " + spAddr + ", listening for DrainMsg");
  }

  public void registerListener(int id, MessageListener m) {
    HashSet listenerSet = (HashSet) idTable.get(new Integer(id));

    if (listenerSet == null) {
      listenerSet = new HashSet();
      idTable.put(new Integer(id), listenerSet);
    }
    listenerSet.add(m);
    log.info("New Listener for id=" + id);
  }

  public void deregisterListener(int id, MessageListener m) {
    HashSet listenerSet = (HashSet) idTable.get(new Integer(id));

    if (listenerSet == null) {
      throw new IllegalArgumentException("No listeners registered for message type " + id);
    }
    listenerSet.remove(m);
  }

  public synchronized void messageReceived(int to, Message m) {

    DrainMsg mhMsg = (DrainMsg) m;

    log.debug(
        "incoming: localDest: "
            + to
            + " type:"
            + mhMsg.get_type()
            + " hops:"
            + (16 - mhMsg.get_ttl())
            + " seqNo:"
            + mhMsg.get_seqNo()
            + " source:"
            + mhMsg.get_source()
            + " finalDest:"
            + mhMsg.get_dest());

    // lets assume that the network cannot buffer more than 25 drain msgs from a single source at a
    // time (should be more than reasonable)
    if (seqNos.containsKey(new Integer(mhMsg.get_source()))) {
      int oldSeqNo = ((Integer) seqNos.get(new Integer(mhMsg.get_source()))).intValue();
      int upperBound = mhMsg.get_seqNo() + 25;
      int wrappedUpperBound = 25 - (255 - mhMsg.get_seqNo());
      if ((oldSeqNo >= mhMsg.get_seqNo() && oldSeqNo < upperBound)
          || (oldSeqNo >= 0 && oldSeqNo < wrappedUpperBound)) {
        log.debug(
            "Dropping message from "
                + mhMsg.get_source()
                + " with duplicate seqNo: "
                + mhMsg.get_seqNo());
        return;
      }
    }
    seqNos.put(new Integer(mhMsg.get_source()), new Integer(mhMsg.get_seqNo()));

    if (to != spAddr && to != MoteIF.TOS_BCAST_ADDR && to != TOS_UART_ADDR) {
      log.debug("Dropping message not for me.");
      return;
    }

    HashSet promiscuousSet = (HashSet) idTable.get(new Integer(BCAST_ID));
    HashSet listenerSet = (HashSet) idTable.get(new Integer(mhMsg.get_type()));

    if (listenerSet != null && promiscuousSet != null) {
      listenerSet.addAll(promiscuousSet);
    } else if (listenerSet == null && promiscuousSet != null) {
      listenerSet = promiscuousSet;
    }

    if (listenerSet == null) {
      log.debug("No Listener for type: " + mhMsg.get_type());
      return;
    }

    for (Iterator it = listenerSet.iterator(); it.hasNext(); ) {
      MessageListener ml = (MessageListener) it.next();
      ml.messageReceived(to, mhMsg);
    }
  }

  public static void main(String args[]) {
    DrainConnector dc = new DrainConnector();
  }
}