]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Performance enhancements to tos.py, rename of TINYOS_NP=BNP to BOOTLOADER=tosboot...
authorrazvanm <razvanm>
Wed, 18 Jun 2008 20:22:51 +0000 (20:22 +0000)
committerrazvanm <razvanm>
Wed, 18 Jun 2008 20:22:51 +0000 (20:22 +0000)
21 files changed:
apps/tests/deluge/Blink/Makefile
apps/tests/deluge/GoldenImage/Makefile
apps/tests/deluge/SerialBlink/Makefile
support/make/Makedefaults
support/make/avr/avrisp.extra
support/make/avr/dapa.extra
support/make/avr/eprb.extra
support/make/avr/install.extra
support/make/avr/mib510.extra
support/make/avr/reinstall.extra
support/make/bnp.extra [deleted file]
support/make/msp/bsl.extra
support/make/msp/install.extra
support/make/msp/jtag.extra
support/make/msp/reinstall.extra
support/make/tinynode/gdb.extra
support/sdk/python/tos.py [new file with mode: 0644]
tools/tinyos/misc/Makefile.am
tools/tinyos/misc/tos-deluge
tools/tinyos/misc/tos-deluge.1
tools/tinyos/misc/tos.py [deleted file]

index 6f7acb3916edea0d19bff17972bcdbb21ce1b42c..5aad1f195c9fd346b102e1d236797a3448cce67f 100644 (file)
@@ -1,5 +1,5 @@
 COMPONENT=BlinkAppC
-TINYOS_NP=BNP
+BOOTLOADER=tosboot
 
 #CFLAGS += -DDELUGE_BASESTATION
 #CFLAGS += -DDELUGE_LIGHT_BASESTATION
index 3187376865629a41ddf12bf5e26af92002b6ff64..cbdea503867e808b070b18d8fc24fcf2089a2e7e 100644 (file)
@@ -1,5 +1,5 @@
 COMPONENT=GoldenImageC
-TINYOS_NP=BNP
+BOOTLOADER=tosboot
 
 CFLAGS += -DDELUGE_BASESTATION
 
index c77ce9665dde695cc0231eef0dba96b881c9a6a0..319a5d83661068dfbb40342d8670c3c6bc8a083f 100644 (file)
@@ -1,4 +1,4 @@
 COMPONENT=BlinkAppC
-TINYOS_NP=BNP
+BOOTLOADER=tosboot
 
 include $(MAKERULES)
index 334d154200238974b9631c292bd5aee4bdd58b51..70773c1729aefa36ea1dc21bbad430c1e813bacc 100644 (file)
@@ -4,7 +4,7 @@
 DEFAULT_LOCAL_GROUP ?= 0x22
 OPTFLAGS ?= -Os
 NESC_FLAGS ?= -Wnesc-all
-GOALS += ident_flags tos_image bnp
+GOALS += ident_flags tos_image tosboot
 
 define DEFAULT_HELP
 
index 0394adc44bda071e0bd4f17321ec01a5c516f930..875cb329d6065e1374f9612525cbe9fc71349ab5 100644 (file)
@@ -8,20 +8,20 @@ endif
 PROGRAM = avrisp
 
 ifeq ($(PROGRAMMER),avrdude)
-    ifdef BOOTLOADER
+    ifdef BOOTLOADER_IMG
       ifeq ($(shell [ -f /bin/cygwin1.dll ] && echo cygwin),cygwin)
-        BOOTLOADER := $(shell cygpath -m $(BOOTLOADER))
+        BOOTLOADER_IMG := $(shell cygpath -m $(BOOTLOADER_IMG))
       endif
     endif
     PROGRAMMER_FLAGS = -cstk500 -P$(MIB510) -U hfuse:w:$(AVR_FUSE_H):m $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_AVRISP)
     PROGRAMMER_INSTALL_SREC_FLAGS = -U flash:w:$(INSTALL_SREC):a
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER):a
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER_IMG):a
 endif
 
 ifeq ($(PROGRAMMER),uisp)
     PROGRAMMER_FLAGS = -dprog=stk500 -dserial=$(AVRISP) --wr_fuse_h=$(AVR_FUSE_H) $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_AVRISP)
     PROGRAMMER_INSTALL_SREC_FLAGS = --erase --upload if=$(INSTALL_SREC) --verify
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER) --verify
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER_IMG) --verify
 endif
 
 program: FORCE
index 20a6cb1583df8266857015f0745225298b7975b0..7bae57d608951334423bca12d8d8982f60ece6eb 100644 (file)
@@ -8,20 +8,20 @@
 PROGRAM = dapa
 
 ifeq ($(PROGRAMMER),avrdude)
-    ifdef BOOTLOADER
+    ifdef BOOTLOADER_IMG
       ifeq ($(shell [ -f /bin/cygwin1.dll ] && echo cygwin),cygwin)
-        BOOTLOADER := $(shell cygpath -m $(BOOTLOADER))
+        BOOTLOADER_IMG := $(shell cygpath -m $(BOOTLOADER_IMG))
       endif
     endif
     PROGRAMMER_FLAGS = -cdapa               -U hfuse:w:$(AVR_FUSE_H):m $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_MIB)
     PROGRAMMER_INSTALL_SREC_FLAGS = -U flash:w:$(INSTALL_SREC):a
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER):a
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER_IMG):a
 endif
 
 ifeq ($(PROGRAMMER),uisp)
     PROGRAMMER_FLAGS = -dprog=dapa                      --wr_fuse_h=$(AVR_FUSE_H) $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_MIB)
     PROGRAMMER_INSTALL_SREC_FLAGS = --erase --upload if=$(INSTALL_SREC) --verify
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER) --verify
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER_IMG) --verify
 endif
 
 program: FORCE
index e53bfc6036b1aa9b5d2a1324b500318cc55bfcd7..92d8982d2c376c4c959670f8b835a65bbf8b6802 100644 (file)
@@ -8,20 +8,20 @@ endif
 PROGRAM = eprb
 
 ifeq ($(PROGRAMMER),avrdude)
-    ifdef BOOTLOADER
+    ifdef BOOTLOADER_IMG
       ifeq ($(shell [ -f /bin/cygwin1.dll ] && echo cygwin),cygwin)
-        BOOTLOADER := $(shell cygpath -m $(BOOTLOADER))
+        BOOTLOADER_IMG := $(shell cygpath -m $(BOOTLOADER_IMG))
       endif
     endif
     PROGRAMMER_FLAGS = -cstk500 -P$(EPRB)   -U hfuse:w:$(AVR_FUSE_H):m $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_STK)
     PROGRAMMER_INSTALL_SREC_FLAGS = -U flash:w:$(INSTALL_SREC):a
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER):a
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER_IMG):a
 endif
 
 ifeq ($(PROGRAMMER),uisp)
     PROGRAMMER_FLAGS = -dprog=stk500 -dhost=$(EPRB)     --wr_fuse_h=$(AVR_FUSE_H) $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_STK)
     PROGRAMMER_INSTALL_SREC_FLAGS = --erase --upload if=$(INSTALL_SREC) --verify
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER) --verify
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER_IMG) --verify
 endif
 
 program: FORCE
index c212cbea7d75bfc74e2cac70a00686f8e033a1db..672ee9de0ade331dbdb2c74a565521135344659e 100644 (file)
@@ -4,8 +4,8 @@
 NODEID = $(INSTALL)
 BUILD_DEPS = srec tosimage bytes $(POST_BUILD_EXTRA_DEPS) setid program delsetid
 
-ifdef TINYOS_NP
-  ifeq ($(TINYOS_NP),BNP)
+ifdef BOOTLOADER
+  ifeq ($(BOOTLOADER),tosboot)
     BUILD_DEPS += program_bl
   endif
 endif
index 02af509b1418e30b82e3c22e39856bdfb902eec8..974b0e26cc521ad248c375b7adf0ba58be9acfa2 100644 (file)
@@ -8,20 +8,20 @@ endif
 PROGRAM = mib510
 
 ifeq ($(PROGRAMMER),avrdude)
-    ifdef BOOTLOADER
+    ifdef BOOTLOADER_IMG
       ifeq ($(shell [ -f /bin/cygwin1.dll ] && echo cygwin),cygwin)
-        BOOTLOADER := $(shell cygpath -m $(BOOTLOADER))
+        BOOTLOADER_IMG := $(shell cygpath -m $(BOOTLOADER_IMG))
       endif
     endif
     PROGRAMMER_FLAGS = -cmib510 -P$(MIB510) -U hfuse:w:$(AVR_FUSE_H):m $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_MIB)
     PROGRAMMER_INSTALL_SREC_FLAGS = -U flash:w:$(INSTALL_SREC):a
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER):a
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = -V -D -U flash:w:$(BOOTLOADER_IMG):a
 endif
 
 ifeq ($(PROGRAMMER),uisp)
     PROGRAMMER_FLAGS = -dprog=mib510 -dserial=$(MIB510) --wr_fuse_h=$(AVR_FUSE_H) $(PROGRAMMER_PART) $(PROGRAMMER_EXTRA_FLAGS) $(PROGRAMMER_EXTRA_FLAGS_MIB)
     PROGRAMMER_INSTALL_SREC_FLAGS = --erase --upload if=$(INSTALL_SREC) --verify
-    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER) --verify
+    PROGRAMMER_INSTALL_BOOTLOADER_FLAGS = --upload if=$(BOOTLOADER_IMG) --verify
 endif
 
 program: FORCE
index 1c8748f13299f83862e03c912961d8ba27c59863..cabb81cc6b0f824ee5f463bd8af1df2962f22e75 100644 (file)
@@ -4,8 +4,8 @@
 NODEID = $(REINSTALL)
 BUILD_DEPS = setid program delsetid
 
-ifdef TINYOS_NP
-  ifeq ($(TINYOS_NP),BNP)
+ifdef BOOTLOADER
+  ifeq ($(BOOTLOADER),tosboot)
     BUILD_DEPS += program_bl
   endif
 endif
diff --git a/support/make/bnp.extra b/support/make/bnp.extra
deleted file mode 100644 (file)
index 7368c19..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#-*-Makefile-*- vim:syntax=make
-#$Id$
-
-DELUGE_DIR ?= $(TOSDIR)/lib/net/Deluge
-DELUGE_EXTRA ?= $(DELUGE_DIR)/extra
-TOSBOOT_DIR ?= $(TOSDIR)/lib/tosboot/build
-
-ifeq ($(TINYOS_NP),BNP)
-
-  CFLAGS += -DDELUGE
-  CFLAGS += -I$(TOSDIR)/lib/net -I$(TOSDIR)/lib/net/drip -I$(DELUGE_DIR) -I$(DELUGE_DIR)/FlashVolumeManager -I$(DELUGE_DIR)/BlockStorageManager
-
-  ifneq ($(filter telosb tmote,$(TARGETS)),)
-    CFLAGS += -I$(DELUGE_EXTRA) -I$(DELUGE_EXTRA)/msp430 -I$(DELUGE_EXTRA)/telos -I$(DELUGE_EXTRA)/telosb
-    ifeq ($(filter docs,$(GOALS)),)
-      CFLAGS += -Wl,--section-start=.text=0x4a00,--defsym=_reset_vector__=0x4000
-    endif
-    BOOTLOADER ?= $(TOSBOOT_DIR)/telosb/main.ihex
-    ifeq ($(shell [ -f /bin/cygwin1.dll ] && echo cygwin),cygwin)
-      BOOTLOADER := $(shell cygpath -m $(BOOTLOADER))
-    endif
-  endif
-
-  ifeq ($(TARGETS),micaz)
-    CFLAGS += -I$(DELUGE_EXTRA) -I$(DELUGE_EXTRA)/avr -I$(DELUGE_EXTRA)/micaz -I$(DELUGE_EXTRA)/mica2
-    BOOTLOADER ?= $(TOSBOOT_DIR)/micaz/main.ihex
-    AVR_FUSE_H ?= 0xda
-  endif
-
-  ifeq ($(TARGETS),iris)
-    CFLAGS += -I$(DELUGE_EXTRA)/iris -I$(DELUGE_EXTRA)/micaz -I$(DELUGE_EXTRA)/mica2 -I$(DELUGE_EXTRA)/avr -I$(DELUGE_EXTRA)
-    BOOTLOADER ?= $(TOSBOOT_DIR)/iris/main.ihex
-    AVR_FUSE_H ?= 0xda
-  endif
-
-
-endif
index d5c0f54e3235877e3c4d51cc2281b28dfba6b5c2..4be2e8a2fc50b0eef61245aac747239f8f59b69b 100644 (file)
@@ -52,7 +52,7 @@ program_no_e: $(BSL_TARGETS) $(TELOS_PROGRAM_DEPS) FORCE
 
 program_bl: $(BSL_TARGETS) $(TELOS_PROGRAM_DEPS) FORCE
        @echo "    installing $(PLATFORM) bootloader using bsl"
-       $(MSP_BSL) $(MSP_BSL_FLAGS) -c $(BSL) -r -e -I -p $(BOOTLOADER)
+       $(MSP_BSL) $(MSP_BSL_FLAGS) -c $(BSL) -r -e -I -p $(BOOTLOADER_IMG)
 
 program_input: ihex
        @:
index 91ef45fc5ceedcb86cf6d7c60f7dc07884ca687d..9627a1c91a0fd0dbee9ecca3bd8408319620b470 100644 (file)
@@ -4,8 +4,8 @@
 NODEID = $(INSTALL)
 BUILD_DEPS = tosimage $(POST_BUILD_EXTRA_DEPS) bytes setid program 
 
-ifdef TINYOS_NP
-  ifeq ($(TINYOS_NP),BNP)
+ifdef BOOTLOADER
+  ifeq ($(BOOTLOADER),tosboot)
     BUILD_DEPS = tosimage $(POST_BUILD_EXTRA_DEPS) setid program_bl program_no_e 
   endif
 endif
index 35355ccd6a1ee875d5a3078ce1d0c2ebbfe91564..3a048ed0846d58cf2434bfb5a373e5aa3d5b7bf4 100644 (file)
@@ -17,7 +17,7 @@ program_no_e: FORCE
 
 program_bl: FORCE
        @echo "    installing $(PLATFORM) bootloader using jtag"
-       $(MSP_JTAG) $(MSP_JTAG_FLAGS) -r -e -I -p $(BOOTLOADER)
+       $(MSP_JTAG) $(MSP_JTAG_FLAGS) -r -e -I -p $(BOOTLOADER_IMG)
 
 program_input: ihex
        @:
index cf0d9d87afa650f7f6055bc674ccbaf4b9b6e085..360eb5de36ad5a9370e45d7abdc977cd64a436a7 100644 (file)
@@ -4,11 +4,11 @@
 NODEID = $(REINSTALL)
 BUILD_DEPS = setid program
 
-ifdef TINYOS_NP
-  ifeq ($(TINYOS_NP),BNP)
+ifdef BOOTLOADER
+  ifeq ($(BOOTLOADER),tosboot)
     BUILD_DEPS = setid program_bl program_no_e
   endif
 endif
 
-check_bnp: FORCE
-       @perl -e 'exit 0 if (<> =~ /^\:103000/); print "\nERROR: Trying to install with BNP support.\n       main.ihex was not built properly, please recompile.\n\n"; exit 1;' $(INSTALL_IHEX)
+check_tosboot: FORCE
+       @perl -e 'exit 0 if (<> =~ /^\:103000/); print "\nERROR: Trying to install with tosboot support.\n       main.ihex was not built properly, please recompile.\n\n"; exit 1;' $(INSTALL_IHEX)
index 2f27b9c90f5ffa23ec7c74d033b9590eabd9b808..76e3a3a0ddaacd0a2d388704408ed5bcadd1be18 100644 (file)
@@ -22,5 +22,5 @@ program_no_e: FORCE
 program_bl: FORCE
        @echo "    installing $(PLATFORM) bootloader using gdb"
        @echo "    installing $(PLATFORM) binary using gdb (without mass erase)"
-       cat $(INIT_GDB) $(FLASH_GDB) $(FLASH_GDB_NO_E) $(GDB_SCRIPT) | sed -e "s/@HOST@/$(PROXY_HOST)/g" -e "s#@EXE@#$(BOOTLOADER)#g" -e "s#@MAIN@#$(MAIN_EXE)#g" -e "s#@PROMPT@#msp-gdb $(COMPONENT)#g"> build/init.gdb;       \
+       cat $(INIT_GDB) $(FLASH_GDB) $(FLASH_GDB_NO_E) $(GDB_SCRIPT) | sed -e "s/@HOST@/$(PROXY_HOST)/g" -e "s#@EXE@#$(BOOTLOADER_IMG)#g" -e "s#@MAIN@#$(MAIN_EXE)#g" -e "s#@PROMPT@#msp-gdb $(COMPONENT)#g"> build/init.gdb;   \
        msp430-gdb $(GDB_ARGS) -silent -x build/init.gdb -se $(MAIN_EXE);
\ No newline at end of file
diff --git a/support/sdk/python/tos.py b/support/sdk/python/tos.py
new file mode 100644 (file)
index 0000000..19fd2d3
--- /dev/null
@@ -0,0 +1,985 @@
+# Copyright (c) 2008 Johns Hopkins University.
+# All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose, without fee, and without written
+# agreement is hereby granted, provided that the above copyright
+# notice, the (updated) modification history and the author appear in
+# all copies of this source code.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+# OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+# @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+
+"""A library that implements the T2 serial communication.
+
+This library has two parts: one that deals with sending and receiving
+packets using the serial format from T2 (TEP113) and a second one that
+tries to simplifies the work with arbitrary packets.
+
+"""
+
+import sys, struct, time, serial, socket, operator, thread
+from Queue import Queue
+from threading import Lock, Condition
+
+__version__ = "$Id$"
+
+__all__ = ['Serial', 'AM',
+           'Packet', 'RawPacket',
+           'AckFrame', 'DataFrame', 'NoAckDataFrame',
+           'ActiveMessage']
+
+ACK_WAIT = 0.2 # Maximum amount of time to wait for an ack
+ACK_WARN = 0.2 # Warn if acks take longer than this to arrive
+
+def list2hex(v):
+    return " ".join(["%02x" % p for p in v])
+
+
+class Error(Exception):
+    """Base error class for this module"""
+    pass
+
+
+class TimeoutError(Error):
+    """Thrown when a serial operation times out"""
+    pass
+
+
+class ReadError(Error):
+    """Base class for read error exceptions"""
+    pass
+
+
+class WriteError(Error):
+    """Base class for write error exceptions"""
+    pass
+
+
+class ReadTimeoutError(TimeoutError, ReadError):
+    """Thrown when a serial read operation times out"""
+    pass
+
+
+class ReadCRCError(ReadError):
+    """Thrown when a read packet fails a CRC check"""
+    pass
+
+
+class BadAckSeqnoError(ReadError):
+    """Thrown if an ack packet has an unexpected sequenc number"""
+    pass
+
+
+class WriteTimeoutError(TimeoutError, WriteError):
+    """Thrown when a serial write operation times out"""
+    pass
+
+
+class SimpleSerial:
+    """
+    A SimpleSerial object offers a way to send and data using a HDLC-like
+    formating.
+
+    Use SimpleSerial objects for basic low-level serial communications. Use
+    Serial objects for higher level logic (retry sends, log printfs, etc).
+    """
+
+    HDLC_FLAG_BYTE = 0x7e
+    HDLC_CTLESC_BYTE = 0x7d
+
+    TOS_SERIAL_ACTIVE_MESSAGE_ID = 0
+    TOS_SERIAL_CC1000_ID = 1
+    TOS_SERIAL_802_15_4_ID = 2
+    TOS_SERIAL_UNKNOWN_ID = 255
+
+    SERIAL_PROTO_ACK = 67
+    SERIAL_PROTO_PACKET_ACK = 68
+    SERIAL_PROTO_PACKET_NOACK = 69
+    SERIAL_PROTO_PACKET_UNKNOWN = 255
+
+    def __init__(self, port, baudrate, flush=False, debug=False, qsize=10,
+                 timeout=None):
+        self._debug = debug
+        self._in_queue = []
+        self._qsize = qsize
+        self._ack = None
+        self._write_counter = 0
+        self._write_counter_failures = 0
+        self._read_counter = 0
+        self._ts = None
+        self.timeout = timeout # Public attribute
+        self._received_packet_filters = [] # filter functions for received packets
+
+        # Remember sent (and unacknowledged) seqno numbers for 15 seconds:
+        self._unacked_seqnos = SeqTracker(15.0)
+
+        self._s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5)
+        self._s.flushInput()
+        if flush:
+            print >>sys.stdout, "Flushing the serial port",
+            endtime = time.time() + 1
+            while time.time() < endtime:
+                try:
+                    self._read()
+                except ReadError:
+                    pass
+                sys.stdout.write(".")
+            if not self._debug:
+                sys.stdout.write("\n")
+        self._s.close()
+        self._s = serial.Serial(port, baudrate, rtscts=0, timeout=timeout)
+
+        # Add a filter for received 'write ack' packets
+        self.add_received_packet_filter(self._write_ack_filter)
+
+    # Returns the next incoming serial packet
+    def _read(self, timeout=None):
+        """Wait for a packet and return it as a RawPacket.
+
+        Throws:
+         - ReadCRCError if a CRC check fails
+         - ReadTimeoutError if the timeout expires.
+
+        """
+
+        # Developer notes:
+        #
+        # Packet data read from Serial is in this format:
+        # [HDLC_FLAG_BYTE][Escaped data][HDLC_FLAG_BYTE]
+        #
+        # [Escaped data] is encoded so that [HDLC_FLAG_BYTE] byte
+        # values cannot occur within it. When [Escaped data] has been
+        # unescaped, the last 2 bytes are a 16-bit CRC of the earlier
+        # part of the packet (excluding the initial HDLC_FLAG_BYTE
+        # byte)
+        #
+        # It's also possible that the serial device was half-way
+        # through transmitting a packet when this function was called
+        # (app was just started). So we also neeed to handle this case:
+        #
+        # [Incomplete escaped data][HDLC_FLAG_BYTE][HDLC_FLAG_BYTE][Escaped data][HDLC_FLAG_BYTE]
+        #
+        # In this case we skip over the first (incomplete) packet.
+        #
+
+        if self._s.timeout != timeout and timeout != None:
+            if self._debug:
+                print "Set the timeout to %s, previous one was %s" % (timeout, self._s.timeout)
+            self._s.timeout = timeout
+
+        try:
+            # Read bytes until we get to a HDLC_FLAG_BYTE value
+            # (either the end of a packet, or the start of a new one)
+            d = self._get_byte(timeout)
+            ts = time.time()
+            if self._debug and d != self.HDLC_FLAG_BYTE:
+                print "Skipping incomplete packet"
+            while d != self.HDLC_FLAG_BYTE:
+                d = self._get_byte(timeout)
+                ts = time.time()
+
+            # Store HDLC_FLAG_BYTE at the start of the retrieved packet
+            # data:
+            packet = [d]
+
+            # Is the next byte also HDLC_FLAG_BYTE?
+            d = self._get_byte(timeout)
+            if d == self.HDLC_FLAG_BYTE:
+                # Yes. This means that the previous byte was for
+                # the end of the previous packet, and this byte is for
+                # the start of the next packet.
+
+                # Get the 2nd byte of the new packet:
+                d = self._get_byte(timeout)
+                ts = time.time()
+
+            # We are now on the 2nd byte of the packet. Add it to
+            # our retrieved packet data:
+            packet.append(d)
+
+            # Read bytes from serial until we read another
+            # HDLC_FLAG_BYTE value (end of the current packet):
+            while d != self.HDLC_FLAG_BYTE:
+                d = self._get_byte(timeout)
+                packet.append(d)
+
+            # Done reading a whole packet from serial
+            if self._debug:
+                print "SimpleSerial:_read: unescaped", packet
+
+            # Decode the packet, and check CRC:
+            packet = self._unescape(packet)
+
+            crc = self._crc16(0, packet[1:-3])
+            packet_crc = self._decode(packet[-3:-1])
+
+            if crc != packet_crc:
+                print "Warning: wrong CRC! %x != %x %s" % (crc, packet_crc, ["%2x" % i for i in packet])
+                raise ReadCRCError
+            if self._debug:
+                if self._ts == None:
+                    self._ts = ts
+                else:
+                    print "Serial:_read: %.4f (%.4f) Recv:" % (ts, ts - self._ts), self._format_packet(packet[1:-3])
+                self._ts = ts
+
+            # Packet was successfully retrieved, so return it in a
+            # RawPacket wrapper object (but leave out the
+            # HDLC_FLAG_BYTE and CRC bytes)
+            return RawPacket(ts, packet[1:-3])
+        except socket.timeout:
+            raise ReadTimeoutError
+
+    def _write_ack_filter(self, packet):
+        """Filter for recieved write acknowledgement packets"""
+        ack = AckFrame(packet.data)
+        if ack.protocol == self.SERIAL_PROTO_ACK:
+            if self._debug:
+                print "_filter_read: got an ack:", ack
+            self._ack = ack
+            packet = None # No further processing of received ack packet
+        return packet
+
+    def _filter_read(self, timeout=None):
+        """Read a packet from the serial device, perform filtering, and return
+        the packet if it hasn't been processed yet.
+
+        """
+        p = self._read(timeout)
+        self._read_counter += 1
+        if self._debug:
+            print "_filter_read: got a packet(%d): %s" % (self._read_counter, p)
+
+        # Pass the received packet through the filter functions:
+        if p is not None:
+            for filter_func in self._received_packet_filters:
+                p = filter_func(p)
+                # Stop now if the packet doesn't need further processing:
+                if p is None:
+                    break
+
+        # Return the packet (if there was no timeout and it wasn't filtered)
+        return p
+
+    def _get_ack(self, timeout, expected_seqno):
+        """Get the next ack packet
+
+        Read packets from the serial device until we get the next ack (which
+        then gets stored in self._ack), or the timeout expires. non-ack packets
+        are buffered.
+
+        Throws:
+         - ReadTimeoutError if the timeout expires.
+         - BadAckSeqnoError if an ack with a bad sequence number is received
+
+        """
+        endtime = time.time() + timeout
+        while time.time() < endtime:
+            # Read the a packet over serial
+            self._ack = None
+            remaining = endtime - time.time()
+            p = self._filter_read(timeout)
+
+            # Was the packet filtered?
+            if p:
+                # Got an unfiltered packet
+                if len(self._in_queue) >= self._qsize:
+                    print "Warning: Buffer overflow"
+                    self._in_queue.pop(0)
+                self._in_queue.append(p)
+            else:
+                # Packet was filtered. Was it an ack?
+                if self._ack is not None:
+                    # The packet was an ack, so remove it from our
+                    # 'unacknowledged seqnos' list (or raise a BadAckSeqnoError
+                    # error if it isn't in the list)
+                    self._unacked_seqnos.seqno_acked(self._ack.seqno)
+
+                    # Stop reading packets if it's the ack we are waiting for:
+                    if self._ack.seqno == expected_seqno:
+                        return
+
+        # Timed out
+        raise ReadTimeoutError
+
+    def close(self):
+        """Close the serial device"""
+        self._s.close()
+
+    def read(self, timeout=None):
+        """Read a packet, either from the input buffer or from the serial
+        device.
+
+        Returns a RawPacket object, otherwise None if the packet was filtered
+        (by eg: Serial's printf-filtering function)
+
+        Does not retry reads if the first one fails. Use Serial.read() for
+        that.
+
+        """
+        if self._in_queue:
+            return self._in_queue.pop(0)
+        else:
+            return self._filter_read(timeout)
+
+    def write(self, payload, seqno, timeout=0.2):
+        """
+        Write a packet. If the payload argument is a list, it is
+        assumed to be exactly the payload. Otherwise the payload is
+        assume to be a Packet and the real payload is obtain by
+        calling the .payload().
+
+        Only attempts to write once, and times out if an ack packet is not
+        received within [timeout] seconds. Use Serial.write() if you want
+        automatic write retries.
+
+        seqno should be an integer between 0 and 99 which changes each time you
+        send a new packet. The value should remain the same when you are
+        retrying a packet write that just failed.
+
+        Raises WriteTimeoutError if the write times out (ack packet doesn't
+        arrive within [timeout] seconds).
+
+        """
+        if type(payload) != type([]):
+            # Assume this will be derived from Packet
+            payload = payload.payload()
+        packet = DataFrame();
+        packet.protocol = self.SERIAL_PROTO_PACKET_ACK
+        packet.seqno = seqno
+        packet.dispatch = 0
+        packet.data = payload
+        packet = packet.payload()
+        crc = self._crc16(0, packet)
+        packet.append(crc & 0xff)
+        packet.append((crc >> 8) & 0xff)
+        packet = [self.HDLC_FLAG_BYTE] + self._escape(packet) + [self.HDLC_FLAG_BYTE]
+
+        # Write the packet:
+        self._unacked_seqnos.seqno_sent(seqno) # Keep track of sent seqno's
+        self._put_bytes(packet)
+        self._write_counter += 1
+
+        # Wait for an ack packet:
+        if self._debug:
+            print "Send(%d/%d): %s" % (self._write_counter, self._write_counter_failures, packet)
+            print "Wait for ack %d ..." % (seqno)
+
+        try:
+            self._get_ack(timeout, seqno)
+        except ReadTimeoutError:
+            # Re-raise read timeouts (of ack packets) as write timeouts (of
+            # the write operation)
+            self._write_counter_failures += 1
+            raise WriteTimeoutError
+
+        # Received an ack packet, with the expected sequence number
+        if self._debug:
+            print "Wait for ack %d done. Latest ack:" % (seqno), self._ack
+            print "The packet was acked."
+            print "Returning from SimpleSerial.write..."
+
+    def add_received_packet_filter(self, filter_func):
+        """Register a received packet-filtering callback function
+
+        _filter_read() calls all of the registered filter functions for each
+        packet received over serial. Registered filter functions are called in
+        the order they were registered.
+
+        Filter functions are called like this: filter_func(packet)
+
+        When a filter function recognises and handles a received packet it
+        should return a None value to indicate that no further processing
+        is required for the packet.
+
+        When a filter function skips a packet (or for some reason you want
+        further processing to happen on a packet you've just processed), the
+        function should return the packet that was passed to it as an argument.
+
+        """
+        self._received_packet_filters.append(filter_func)
+
+    def remove_received_packet_filter(self, filter_func):
+        """Remove a filter function added with add_received_packet_filter()"""
+        self._received_packet_filters.remove(filter_func)
+
+    def _format_packet(self, payload):
+        f = NoAckDataFrame(payload)
+        if f.protocol == self.SERIAL_PROTO_ACK:
+            rpacket = AckFrame(payload)
+            return "Ack seqno: %d" % (rpacket.seqno)
+        else:
+            rpacket = ActiveMessage(f.data)
+            return "D: %04x S: %04x L: %02x G: %02x T: %02x | %s" % \
+                   (rpacket.destination, rpacket.source,
+                    rpacket.length, rpacket.group, rpacket.type,
+                    list2hex(rpacket.data))
+
+    def _crc16(self, base_crc, frame_data):
+        crc = base_crc
+        for b in frame_data:
+            crc = crc ^ (b << 8)
+            for i in range(0, 8):
+                if crc & 0x8000 == 0x8000:
+                    crc = (crc << 1) ^ 0x1021
+                else:
+                    crc = crc << 1
+                crc = crc & 0xffff
+        return crc
+
+    def _encode(self, val, dim):
+        output = []
+        for i in range(dim):
+            output.append(val & 0xFF)
+            val = val >> 8
+        return output
+
+    def _decode(self, v):
+        r = long(0)
+        for i in v[::-1]:
+            r = (r << 8) + i
+        return r
+
+    def _get_byte(self, timeout=None):
+#        old_timeout = self._s.timeout
+#        if timeout is not None:
+#            self._s.timeout = timeout
+        try:
+            r = struct.unpack("B", self._s.read())[0]
+            return r
+        except struct.error:
+            # Serial port read timeout
+            raise socket.timeout
+#        finally:
+#            self._s.timeout = old_timeout
+
+    def _put_bytes(self, data):
+        #print "DEBUG: _put_bytes:", data
+        for b in data:
+            self._s.write(struct.pack('B', b))
+
+    def _unescape(self, packet):
+        r = []
+        esc = False
+        for b in packet:
+            if esc:
+                r.append(b ^ 0x20)
+                esc = False
+            elif b == self.HDLC_CTLESC_BYTE:
+                esc = True
+            else:
+                r.append(b)
+        return r
+
+    def _escape(self, packet):
+        r = []
+        for b in packet:
+            if b == self.HDLC_FLAG_BYTE or b == self.HDLC_CTLESC_BYTE:
+                r.append(self.HDLC_CTLESC_BYTE)
+                r.append(b ^ 0x20)
+            else:
+                r.append(b)
+        return r
+
+    def debug(self, debug):
+        self._debug = debug
+
+
+class SeqTracker:
+    """Class for keeping track of unacknowledged packet sequence numbers.
+
+    SeqTracker is used by SimpleSerial to keep track of sequence numbers which
+    have been sent with write packets, but not yet acknowledged by received
+    write ack packets.
+
+    """
+    def __init__(self, keep_for):
+        """Initialise a SeqTracker object.
+
+        args:
+
+         - keep_for is the length of time for which unacknowledged sequence
+           numbers should be remembered. After this period has elapsed, the
+           sequence numbers should be forgotten. If the sequence number is
+           acknowledged later, it will be treated as unkown
+
+        """
+        self._keep_for = keep_for
+        self._queue = []
+
+    def seqno_sent(self, seqno):
+        """Register that a packet with the specified sequence number was just
+           sent."""
+        self._gc()
+        self._queue.append((seqno, time.time()))
+
+    def seqno_acked(self, seqno):
+        """Register that a sequence number was just acknowledged.
+
+        Find the oldest-known occurance of seqno in the queue and remove it. If
+        not found then raise a BadAckSeqnoError to inform applications that
+        the sequence number is not known.
+
+        """
+        self._gc()
+        for item in self._queue:
+            if item[0] == seqno:
+                # Found seqno
+                self._queue.remove(item)
+                return
+        # seqno not found!
+        raise BadAckSeqnoError
+
+    def get_seqno_sent_times(self, seqno):
+        """Return the times when packets with the given sequence number were
+        sent."""
+        self._gc()
+        return [item[1] for item in self._queue if item[0] == seqno]
+
+    def __contains__(self, seqno):
+        """Return True if the seqno was sent recently (and not acknowledged
+        yet)"""
+        self._gc()
+        for item in self._queue:
+            if item[0] == seqno:
+                return True
+        return False
+
+    def _gc(self):
+        """Remove old items from the queue"""
+        remove_before = time.time() - self._keep_for
+        for item in self._queue:
+            # Time for the sequence to be removed?
+            if item[1] < remove_before:
+                # Sequence data is old, so remove it
+                self._queue.remove(item)
+            else:
+                # Sequence number was added recently, so don't remove it. Also
+                # stop processing the queue because all later items will be
+                # newer
+                break
+
+
+class Serial:
+    """
+    Wraps a SimpleSerial object, and provides some higher-level functionality
+    like retrying writes and logging printf packets.
+    """
+    def __init__(self, port, baudrate, flush=False, debug=False, qsize=10,
+                 timeout=None):
+        """Initialise a Serial object"""
+        self._debug = debug
+        self.timeout = timeout # Public attribute
+        self._seqno = 0
+        self._simple_serial = SimpleSerial(port, baudrate, flush, debug, qsize,
+                                           timeout)
+
+        # Setup automatic logging of received printf packets:
+        self._printf_msg = ""
+        self._simple_serial.add_received_packet_filter(self._printf_filter)
+
+    def close(self):
+        """Close the serial device"""
+        self._simple_serial.close()
+
+    def read(self, timeout=None):
+        """Read a packet from the serial port.
+
+        Retries packet reads until the timeout expires.
+
+        Throws ReadTimeoutError if a a packet can't be read within the timeout.
+
+        """
+        if timeout is None:
+            timeout = self.timeout
+        endtime = None
+
+        if timeout is not None:
+            endtime = time.time() + timeout
+
+        while endtime is None or time.time() < endtime:
+            remaining = None
+            if endtime is not None:
+                remaining = endtime - time.time()
+            try:
+                p = self._simple_serial.read(remaining)
+            except ReadError:
+                if self._debug:
+                    print "Packet read failed. Try again."
+            else:
+                # Was the packet filtered?
+                if p is not None:
+                    # Not filtered, so return it.
+                    # In the current TinyOS the packets from the mote are
+                    # always NoAckDataFrame
+                    return NoAckDataFrame(p.data)
+
+        # Read timeout expired
+        raise ReadTimeoutError
+
+    def write(self, payload, timeout=None):
+        """Write a packet to the serial port
+
+        Keeps retrying endlessly, unless a timeout is set. If the timeout
+        expires then WriteTimeoutError is thrown.
+
+        """
+        if timeout is None:
+            timeout = self.timeout
+
+        endtime = None
+        if timeout is not None:
+            endtime = time.time() + timeout
+
+        # Generate the next sequence number:
+        self._seqno = (self._seqno + 1) % 100
+
+        while endtime is None or time.time() < endtime:
+            try:
+                ackwait = ACK_WAIT
+                if endtime is not None:
+                    remaining = endtime - time.time()
+                    ackwait = min(ACK_WAIT, remaining)
+
+                before = time.time()
+                self._simple_serial.write(payload, self._seqno, ackwait)
+                length = time.time() - before
+
+                if length >= ACK_WARN:
+                    print "Warning: Packet write took %.3fs!" % (length)
+                return True
+            except Error:
+                if self._debug:
+                    print "The packet was not acked. Try again."
+
+        # Write operation timed out
+        raise WriteTimeoutError
+
+    def _printf_filter(self, packet):
+        """Filter for recieved printf packets"""
+        ampkt = ActiveMessage(NoAckDataFrame(packet.data).data)
+        if ampkt.type == 100:
+            self._printf_msg += "".join([chr(i) for i in ampkt.data]).strip('\0')
+            # Split printf data on newline character:
+            # (last string in the split list doesn't have a newline after
+            # it, so we keep it until next time)
+            lines = self._printf_msg.split('\n')
+            for line in lines[:-1]:
+                print "PRINTF:", line
+            self._printf_msg = lines[-1]
+            packet = None # No further processing for the printf packet
+        return packet
+
+class SFClient:
+    def __init__(self, host, port, qsize=10):
+        self._in_queue = Queue(qsize)
+        self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self._s.connect((host, port))
+        data = self._s.recv(2)
+        if data != 'U ':
+            print "Wrong handshake"
+        self._s.send("U ")
+        print "Connected"
+        thread.start_new_thread(self.run, ())
+
+    def run(self):
+        while True:
+            length = ord(self._s.recv(1))
+            data = self._s.recv(length)
+            data = [ord(c) for c in data][1:]
+            #print "Recv %d bytes" % (length), ActiveMessage(data)
+            if self._in_queue.full():
+                print "Warning: Buffer overflow"
+                self._in_queue.get()
+            p = RawPacket()
+            p.data = data
+            self._in_queue.put(p, block=False)
+
+    def read(self, timeout=0):
+        return self._in_queue.get()
+
+    def write(self, payload):
+        print "SFClient: write:", payload
+        if type(payload) != type([]):
+            # Assume this will be derived from Packet
+            payload = payload.payload()
+        payload = [0] + payload
+        self._s.send(chr(len(payload)))
+        self._s.send(''.join([chr(c) for c in payload]))
+        return True
+
+class AM:
+    def __init__(self, s):
+        self._s = s
+
+    def read(self, timeout=None):
+        return ActiveMessage(self._s.read(timeout).data)
+
+    def write(self, packet, amid, timeout=None):
+        return self._s.write(ActiveMessage(packet, amid=amid), timeout=timeout)
+
+
+class SimpleSerialAM(SimpleSerial):
+    """A derived class of SimpleSerial so that apps can read and write using
+    higher-level packet structures.
+
+    Serves a simalar purpose to the AM class, but for SimpleSerial objects
+    instead instead of Serial.
+
+    """
+
+    def read_am(self, timeout=None):
+        """Read a RawPacket object (or None), convert it to ActiveMessage
+        (or None), and return to the caller"""
+
+        # Get a tos.Rawpacket (or None, if filtered) object
+        p = self.read(timeout)
+        if p is not None:
+            assert isinstance(p, RawPacket)
+            # Convert tos.RawPacket object into an ActiveMessage:
+            p = NoAckDataFrame(p.data)
+            p = ActiveMessage(p.data)
+
+        # Return the ActiveMessage (or None) packet:
+        return p
+
+    def write_am(self, packet, amid, seqno, timeout=2.0):
+        """Convert app packet format to ActiveMessage, and write the
+        ActiveMessage packet to serial"""
+
+        # Convert from app-specific packet to ActiveMessage:
+        p = ActiveMessage(packet, amid=amid)
+
+        # Write to the serial device
+        self.write(p, seqno, timeout)
+
+
+class Packet:
+    """
+    The Packet class offers a handy way to build pack and unpack
+    binary data based on a given pattern.
+    """
+
+    def _decode(self, v):
+        r = long(0)
+        for i in v:
+            r = (r << 8) + i
+        return r
+
+    def _encode(self, val, dim):
+        output = []
+        for i in range(dim):
+            output.append(int(val & 0xFF))
+            val = val >> 8
+        output.reverse()
+        return output
+
+    def __init__(self, desc, packet = None):
+        offset = 0
+        boffset = 0
+        sum = 0
+        for i in range(len(desc)-1, -1, -1):
+            (n, t, s) = desc[i]
+            if s == None:
+                if sum > 0:
+                    desc[i] = (n, t, -sum)
+                break
+            sum += s
+        self.__dict__['_schema'] = [(t, s) for (n, t, s) in desc]
+        self.__dict__['_names'] = [n for (n, t, s) in desc]
+        self.__dict__['_values'] = []
+        if type(packet) == type([]):
+            for (t, s) in self._schema:
+                if t == 'int':
+                    self._values.append(self._decode(packet[offset:offset + s]))
+                    offset += s
+                elif t == 'bint':
+                    doffset = 8 - (boffset + s)
+                    self._values.append((packet[offset] >> doffset) & ((1<<s) - 1))
+                    boffset += s
+                    if boffset == 8:
+                        offset += 1
+                        boffset = 0
+                elif t == 'string':
+                    self._values.append(''.join([chr(i) for i in packet[offset:offset + s]]))
+                    offset += s
+                elif t == 'blob':
+                    if s:
+                        if s > 0:
+                            self._values.append(packet[offset:offset + s])
+                            offset += s
+                        else:
+                            self._values.append(packet[offset:s])
+                            offset = len(packet) + s
+                    else:
+                        self._values.append(packet[offset:])
+        elif type(packet) == type(()):
+            for i in packet:
+                self._values.append(i)
+        else:
+            for v in self._schema:
+                self._values.append(None)
+
+    def __repr__(self):
+        return self._values.__repr__()
+
+    def __str__(self):
+        r = ""
+        for i in range(len(self._names)):
+            r += "%s: %s " % (self._names[i], self._values[i])
+        for i in range(len(self._names), len(self._values)):
+            r += "%s" % self._values[i]
+        return r
+#        return self._values.__str__()
+
+    # Implement the map behavior
+    def __getitem__(self, key):
+        return self.__getattr__(key)
+
+    def __setitem__(self, key, value):
+        self.__setattr__(key, value)
+
+    def __len__(self):
+        return len(self._values)
+
+    def keys(self):
+        return self._names
+
+    def values(self):
+        return self._names
+
+    # Implement the struct behavior
+    def __getattr__(self, name):
+        #print "DEBUG: __getattr__", name
+        if type(name) == type(0):
+            return self._names[name]
+        else:
+            return self._values[self._names.index(name)]
+
+    def __setattr__(self, name, value):
+        if type(name) == type(0):
+            self._values[name] = value
+        else:
+            self._values[self._names.index(name)] = value
+
+    def __ne__(self, other):
+        if other.__class__ == self.__class__:
+            return self._values != other._values
+        else:
+            return True
+
+    def __eq__(self, other):
+        if other.__class__ == self.__class__:
+            return self._values == other._values
+        else:
+            return False
+
+    def __nonzero__(self):
+        return True;
+
+    # Custom
+    def names(self):
+        return self._names
+
+    def sizes(self):
+        return self._schema
+
+    def payload(self):
+        r = []
+        boffset = 0
+        for i in range(len(self._schema)):
+            (t, s) = self._schema[i]
+            if t == 'int':
+                r += self._encode(self._values[i], s)
+                boffset = 0
+            elif t == 'bint':
+                doffset = 8 - (boffset + s)
+                if boffset == 0:
+                    r += [self._values[i] << doffset]
+                else:
+                    r[-1] |= self._values[i] << doffset
+                boffset += s
+                if boffset == 8:
+                    boffset = 0
+            elif self._values[i] != []:
+                r += self._values[i]
+        for i in self._values[len(self._schema):]:
+            r += i
+        return r
+
+
+class RawPacket(Packet):
+    def __init__(self, ts = None, data = None):
+        Packet.__init__(self,
+                        [('ts' ,  'int', 4),
+                         ('data', 'blob', None)],
+                        None)
+        self.ts = ts;
+        self.data = data
+
+class AckFrame(Packet):
+    def __init__(self, payload = None):
+        Packet.__init__(self,
+                        [('protocol', 'int', 1),
+                         ('seqno',    'int', 1)],
+                        payload)
+
+class DataFrame(Packet):
+    def __init__(self, payload = None):
+        if payload != None and type(payload) != type([]):
+            # Assume is a Packet
+            payload = payload.payload()
+        Packet.__init__(self,
+                        [('protocol',  'int', 1),
+                         ('seqno',     'int', 1),
+                         ('dispatch',  'int', 1),
+                         ('data',      'blob', None)],
+                        payload)
+
+class NoAckDataFrame(Packet):
+    def __init__(self, payload = None):
+        if payload != None and type(payload) != type([]):
+            # Assume is a Packet
+            payload = payload.payload()
+        Packet.__init__(self,
+                        [('protocol',  'int', 1),
+                         ('dispatch',  'int', 1),
+                         ('data',      'blob', None)],
+                        payload)
+
+class ActiveMessage(Packet):
+    def __init__(self, gpacket = None, amid = 0x00, dest = 0xFFFF):
+        if type(gpacket) == type([]):
+            payload = gpacket
+        else:
+            # Assume this will be derived from Packet
+            payload = None
+        Packet.__init__(self,
+                        [('destination', 'int', 2),
+                         ('source',   'int', 2),
+                         ('length',   'int', 1),
+                         ('group',    'int', 1),
+                         ('type',     'int', 1),
+                         ('data',     'blob', None)],
+                        payload)
+        if payload == None:
+            self.destination = dest
+            self.source = 0x0000
+            self.group = 0x00
+            self.type = amid
+            self.data = []
+            if gpacket:
+                self.data = gpacket.payload()
+            self.length = len(self.data)
+
index 295fad4f0db5448baefeec802dd48d2075164369..76498bb1cb5ffba95e638544ba5f76d64d43ac13 100644 (file)
@@ -34,6 +34,3 @@ bin_SCRIPTS = tos-ident-flags \
              tos-deluge
 
 bin_PROGRAMS = tos-serial-debug
-
-pythondir = $(bindir)
-python_DATA = tos.py
index a6c99785b13590f02b0c2215703c0b847508f125..b8e79ce4759217f3865b56ab42a21deffd5b4b1d 100755 (executable)
 # @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
 # @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
 
-import sys, stat, struct, subprocess, time
-import tos
+import sys, stat, struct, subprocess, time, os.path
+try:
+    import tos
+except ImportError:
+    import posix
+    sys.path = [os.path.join(posix.environ['TOSROOT'], 'support', 'sdk', 'python')] + sys.path
+    import tos
 from datetime import datetime
-import os.path 
 
 # Path to the python script that builds Deluge image from XML
 PATH_PY_BUILD_IMAGE  = os.path.join(os.path.dirname(sys.argv[0]), 'tos-build-deluge-image')
@@ -125,12 +129,12 @@ def crc16(data):
             else:
                 crc = crc << 1
             crc = crc & 0xffff
-    
+
     return crc
 
 def handleResponse(success, msg):
     if success == True:
-        packet = am.read(timeout=1)
+        packet = am.read(timeout=2)
         while packet and packet.type == 100:
             print "".join([chr(i) for i in packet.data])
             packet = am.read()
@@ -143,14 +147,14 @@ def handleResponse(success, msg):
         else:
             print msg, reply
             return False
-        
+
     print "ERROR: Unable to send the command"
     return False
 
-def ident():
+def ident(timeout=None):
     sreqpkt = FMReqPacket((FM_CMD_IDENT, 0, 0, 0, []))
-    if am.write(sreqpkt, FM_AMID):
-        packet = am.read()
+    if am.write(sreqpkt, FM_AMID, timeout=timeout):
+        packet = am.read(timeout=timeout)
         reply = SerialReplyPacket(packet.data)
         if reply.error == ERROR_SUCCESS:
             return ShortIdent(reply.data)
@@ -158,12 +162,12 @@ def ident():
 
 def read(imgNum, offset, length):
     r = []
-    
+
     sreqpkt = FMReqPacket((FM_CMD_READ, imgNum, offset, length, []))
     while True:
         if sreqpkt.length > SERIAL_DATA_LENGTH:
             sreqpkt.length = SERIAL_DATA_LENGTH
-        
+
         if am.write(sreqpkt, FM_AMID):
             packet = am.read()
             reply = SerialReplyPacket(packet.data)
@@ -175,7 +179,7 @@ def read(imgNum, offset, length):
         else:
             r = None
             break
-        
+
         sreqpkt.offset += sreqpkt.length
         if sreqpkt.offset >= (offset + length):
             break
@@ -199,29 +203,29 @@ def write(imgNum, data):
     total_length = length   # For progress bar
     next_tick = 100         # For progress bar
     start_time = time.time()
-    
+
     print "[0%        25%         50%         75%         100%]\r[",
+
     sreqpkt.offset = 0
     while length > 0:
         if ((length * 100) / total_length) < next_tick:
             next_tick = next_tick - 2
             sys.stdout.write('-')
             sys.stdout.flush()
-    
+
         # Calculates the payload size for the current packet
         if length >= SERIAL_DATA_LENGTH:
             sreqpkt.length = SERIAL_DATA_LENGTH
         else:
             sreqpkt.length = length
         sreqpkt.data = data[sreqpkt.offset:sreqpkt.offset+sreqpkt.length]
-        
+
         # Sends over serial to the mote
         if not am.write(sreqpkt, FM_AMID):
             print
             print "ERROR: Unable to send the last serial packet (file offset: %d)" % sreqpkt.offset
             return False
-        
+
         # Waiting for confirmation
         packet = am.read()
         reply = SerialReplyPacket(packet.data)
@@ -229,7 +233,7 @@ def write(imgNum, data):
             print
             print "ERROR: Unable to write to the flash volume (file offset: %d)" % sreqpkt.offset
             return False
-            
+
         length -= sreqpkt.length
         sreqpkt.offset += sreqpkt.length
 
@@ -237,7 +241,7 @@ def write(imgNum, data):
     elasped_time = time.time() - start_time
     print "\r%s bytes in %.2f seconds (%.4f bytes/s)" % (total_length, elasped_time, int(total_length) / (elasped_time))
     return True
-    
+
 # Checks for valid CRC and timestamp
 def verifyIdent(i):
     if i != None:
@@ -286,7 +290,7 @@ def inject(imgNum, tos_image_xml):
     except:
         print "ERROR: Unable to find the image building utility, \"%s\"" % PATH_PY_BUILD_IMAGE
         return False
-  
+
     # Gets status information of stored image
     i = getIdent(imgNum)
     if ident:
@@ -306,7 +310,7 @@ def inject(imgNum, tos_image_xml):
     (out, err) = p.communicate(None)
     print err,
     print "--------------------------------------------------"
-    
+
     # Writes the new binary image
     image = [struct.unpack("B", c)[0] for c in out]
     if len(image) > 0 and erase(imgNum):
@@ -316,7 +320,7 @@ def inject(imgNum, tos_image_xml):
                 print "Replace image with:"
                 print formatIdent(getIdent(imgNum))
                 print "--------------------------------------------------"
-    
+
     return False
 
 def ping(imgNum):
@@ -331,7 +335,7 @@ def ping(imgNum):
         print formatIdent(i)
         print "--------------------------------------------------"
         return True
-        
+
     print "--------------------------------------------------"
     return False
 
@@ -403,7 +407,7 @@ if len(sys.argv) >= 4:
         except:
             print "ERROR: Wrong baudrate"
             sys.exit(-1)
-            
+
     # Initializes serial port communication
     try:
         s = tos.Serial(sys.argv[1], baudrate, flush=True, debug=False)
@@ -412,10 +416,18 @@ if len(sys.argv) >= 4:
         print "ERROR: Unable to initialize serial port connection to", sys.argv[1]
         sys.exit(-1)
 
+    # Check if the mote has the Deluge T2 basestation component:
+    try:
+        print "Checking if node is a Deluge T2 base station ..."
+        ident(timeout=5)
+    except tos.TimeoutError:
+        print "ERROR: Timeout. Is the node a Deluge T2 base station?"
+        sys.exit(-1)
+
     if sys.argv[3] in ["-p", "--ping"]:
         checkImgNum()
         print "Pinging node ..."
-        ping(imgNum) 
+        ping(imgNum)
     elif sys.argv[3] in ["-i", "--inject"] and len(sys.argv) == 6:
         checkImgNum()
         print "Pinging node ..."
index 33813baaacc8f04349a048273f6fe2d00c1ce410..b8037cf462aed832eab35dbfe389d16a083c795a 100644 (file)
@@ -26,7 +26,7 @@ COM10
 
 .TP
 .I baudrate
-Two shortcuts are available: \fBmicaz\fR for 57600 and \fBtelosb\fR for 115200.
+Three shortcuts are available: \fBmicaz\fR and \fBiris\fR for 57600 and \fBtelosb\fR for 115200.
 .TP
 .I image_number
 A integer number. 0 is the first image.
@@ -34,22 +34,25 @@ A integer number. 0 is the first image.
 .SH OPTIONS
 .TP
 .B -p, --ping
-Provide status of the image in the external flash
+This command is useful for checking the status of program images on a mote. It provides information such as program name, compile time, size of the image, and so on.
 .TP
 .B -i, --inject
-Inject a compiled TinyOS application. The tos_image.xml file path
+This command creates a program image from the supplied tos_image.xml file, and it injects the image into specified volume on the mote.
 .TP
 .B -r, --reprogram
-Reprogram the network
+This command sets up the directly-connected mote to reprogram itself after reboot, and then it reboots the mote.
 .TP
-.B -b, --reprogram_bs
-Reprogram only the directly-connected mote
+.B -d, --disseminate
+This command instructs the base station mote to disseminate an image to the network. This image is specified by the volume ID.
 .TP
-.B -d, --dissemination
-Disseminate the image in the external flash to the network
+.B -dr, --disseminate-and-reprogram
+This command asks the motes in the network not only to disseminate an image but also to start running it. This is accomplish using a reboot.
 .TP
 .B -e, --erase
-Erase an image in the external flash
+This command erases a flash volume on the base station mote.
 .TP
-.B -s, --reset
-Reset the versioning information for a given image
+.B -s, --stop
+The effect of -d and -dr is continuous which means a new mote will become infected if he is nearby. This command stops the infection.
+.TP
+.B -ls, --local-stop
+When -d or -dr are in effect, the volume used by them is locked. This command can be used to unlock the volume in order to erase or inject a new image. 
diff --git a/tools/tinyos/misc/tos.py b/tools/tinyos/misc/tos.py
deleted file mode 100644 (file)
index e01e7ec..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-# Copyright (c) 2008 Johns Hopkins University.
-# All rights reserved.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose, without fee, and without written
-# agreement is hereby granted, provided that the above copyright
-# notice, the (updated) modification history and the author appear in
-# all copies of this source code.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
-# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
-# OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-# THE POSSIBILITY OF SUCH DAMAGE.
-
-# @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
-
-"""A library that implements the T2 serial communication.
-
-This library has two parts: one that deals with sending and receiving
-packets using the serial format from T2 (TEP113) and a second one that
-tries to simplifies the work with arbitrary packets.
-
-"""
-
-import sys, struct, time, serial, socket, operator, thread
-from Queue import Queue
-from threading import Lock, Condition
-
-__version__ = "$Id$"
-
-__all__ = ['Serial', 'AM',
-           'Packet', 'RawPacket',
-           'AckFrame', 'DataFrame', 'NoAckDataFrame',
-           'ActiveMessage']
-
-def list2hex(v):
-    return " ".join(["%02x" % p for p in v])
-
-class Serial:
-    """
-    A Serial object offers a way to send and data using a HDLC-like
-    formating.
-    """
-    
-    HDLC_FLAG_BYTE = 0x7e
-    HDLC_CTLESC_BYTE = 0x7d
-    
-    TOS_SERIAL_ACTIVE_MESSAGE_ID = 0
-    TOS_SERIAL_CC1000_ID = 1
-    TOS_SERIAL_802_15_4_ID = 2
-    TOS_SERIAL_UNKNOWN_ID = 255
-    
-    SERIAL_PROTO_ACK = 67
-    SERIAL_PROTO_PACKET_ACK = 68
-    SERIAL_PROTO_PACKET_NOACK = 69
-    SERIAL_PROTO_PACKET_UNKNOWN = 255
-  
-    def __init__(self, port, baudrate, flush=False, debug=False, qsize=10):
-        self._debug = debug
-        self._in_queue = Queue(qsize)
-        self._out_lock = Lock()
-        self._out_ack = Condition()
-        self._seqno = 0
-        self._ack = None
-        self._write_counter = 0
-        self._write_counter_failures = 0
-        self._read_counter = 0
-        self._ts = None
-
-        self._s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5)
-        self._s.flushInput()
-        start = time.time();
-        if flush:
-            print >>sys.stdout, "Flushing the serial port",
-            while time.time() - start < 1:
-                p = self._read()
-                sys.stdout.write(".")
-            if not self._debug:
-                sys.stdout.write("\n")
-        self._s.close()
-        self._s = serial.Serial(port, baudrate, rtscts=0, timeout=None)
-
-        thread.start_new_thread(self.run, ())
-
-    def run(self):
-        
-        while True:
-            p = self._read()
-            self._read_counter += 1
-            if self._debug:
-                print "Serial:run: got a packet(%d): %s" % (self._read_counter, p)
-            ack = AckFrame(p.data)
-            if ack.protocol == self.SERIAL_PROTO_ACK:
-                if not self._ack:
-                    self._ack = ack
-                if self._debug:
-                    print "Serial:run: got an ack:", ack
-                self._ack = ack
-                # Wake up the writer
-                self._out_ack.acquire()
-                self._out_ack.notify()
-                self._out_ack.release()
-            else:
-                ampkt = ActiveMessage(NoAckDataFrame(p.data).data)
-                if ampkt.type == 100:
-                    for t in "".join([chr(i) for i in ampkt.data]).strip('\n\0').split('\n'):
-                        print "PRINTF:", t.strip('\n')
-                else:
-                    if self._in_queue.full():
-                        print "Warning: Buffer overflow"
-                        self._in_queue.get()
-                    self._in_queue.put(p, block=False)
-
-
-    # Returns the next incoming serial packet
-    def _read(self):
-        """Wait for a packet and return it as a RawPacket."""
-        
-        try:
-            d = self._get_byte()
-            ts = time.time()
-            while d != self.HDLC_FLAG_BYTE:
-                d = self._get_byte()
-                ts = time.time()
-            packet = [d]
-            d = self._get_byte()
-            if d == self.HDLC_FLAG_BYTE:
-                d = self._get_byte()
-                ts = time.time()
-            else:
-                packet.append(d)
-            while d != self.HDLC_FLAG_BYTE:
-                d = self._get_byte()
-                packet.append(d)
-            if self._debug == True:
-                print "Serial:_read: unescaped", packet
-            packet = self._unescape(packet)
-            
-            crc = self._crc16(0, packet[1:-3])
-            packet_crc = self._decode(packet[-3:-1])
-            
-            if crc != packet_crc:
-                print "Warning: wrong CRC! %x != %x %s" % (crc, packet_crc, ["%2x" % i for i in packet])
-            if self._debug:
-                if self._ts == None:
-                    self._ts = ts
-                else:
-                    print "Serial:_read: %.4f (%.4f) Recv:" % (ts, ts - self._ts), self._format_packet(packet[1:-3])
-                self._ts = ts
-            return RawPacket(ts, packet[1:-3], crc == packet_crc)
-        except socket.timeout:
-            return None
-
-
-    def read(self, timeout=0):
-        start = time.time();
-        done = False
-        while not done:
-            p = None
-            while p == None:
-                if timeout == 0 or time.time() - start < timeout:
-                    p = self._in_queue.get()
-                else:
-                    return None
-            if p.crc:
-                done = True
-            else:
-                p = None
-        # In the current TinyOS the packets from the mote are always NoAckDataFrame
-        return NoAckDataFrame(p.data)
-
-    def write(self, payload):
-        """
-        Write a packet. If the payload argument is a list, it is
-        assumed to be exactly the payload. Otherwise the payload is
-        assume to be a Packet and the real payload is obtain by
-        calling the .payload().
-        """
-        
-        if type(payload) != type([]):
-            # Assume this will be derived from Packet
-            payload = payload.payload()
-        self._out_lock.acquire()
-        self._seqno = (self._seqno + 1) % 100
-        packet = DataFrame();
-        packet.protocol = self.SERIAL_PROTO_PACKET_ACK
-        packet.seqno = self._seqno
-        packet.dispatch = 0
-        packet.data = payload
-        packet = packet.payload()
-        crc = self._crc16(0, packet)
-        packet.append(crc & 0xff)
-        packet.append((crc >> 8) & 0xff)
-        packet = [self.HDLC_FLAG_BYTE] + self._escape(packet) + [self.HDLC_FLAG_BYTE]
-
-        while True:
-            self._put_bytes(packet)
-            self._write_counter += 1
-            if self._debug == True:
-                print "Send(%d/%d): %s" % (self._write_counter, self._write_counter_failures, packet)
-                print "Wait for ack %d ..." % (self._seqno)
-            self._out_ack.acquire()
-            self._out_ack.wait(0.2)
-            if self._debug:
-                print "Wait for ack %d done. Latest ack:" % (self._seqno), self._ack
-            self._out_ack.release()
-            if self._ack and self._ack.seqno == self._seqno:
-                if self._debug:
-                    print "The packet was acked."
-                self._out_lock.release()
-                if self._debug:
-                    print "Returning from Serial.write..."
-                return True
-            else:
-                self._write_counter_failures += 1
-                if self._debug:
-                    print "The packet was not acked. Try again."
-            # break # make only one sending attempt
-        self._out_lock.release()
-        return False
-
-
-    def _format_packet(self, payload):
-        f = NoAckDataFrame(payload)
-        if f.protocol == self.SERIAL_PROTO_ACK:
-            rpacket = AckFrame(payload)
-            return "Ack seqno: %d" % (rpacket.seqno)
-        else:
-            rpacket = ActiveMessage(f.data)
-            return "D: %04x S: %04x L: %02x G: %02x T: %02x | %s" % \
-                   (rpacket.destination, rpacket.source,
-                    rpacket.length, rpacket.group, rpacket.type,
-                    list2hex(rpacket.data))
-
-    def _crc16(self, base_crc, frame_data):
-        crc = base_crc
-        for b in frame_data:
-            crc = crc ^ (b << 8)
-            for i in range(0, 8):
-                if crc & 0x8000 == 0x8000:
-                    crc = (crc << 1) ^ 0x1021
-                else:
-                    crc = crc << 1
-                crc = crc & 0xffff
-        return crc
-    
-    def _encode(self, val, dim):
-        output = []
-        for i in range(dim):
-            output.append(val & 0xFF)
-            val = val >> 8
-        return output
-    
-    def _decode(self, v):
-        r = long(0)
-        for i in v[::-1]:
-            r = (r << 8) + i
-        return r
-    
-    def _get_byte(self):
-        try:
-            r = struct.unpack("B", self._s.read())[0]
-            return r
-        except struct.error:
-            # Serial port read timeout
-            raise socket.timeout
-    
-    def _put_bytes(self, data):
-        #print "DEBUG: _put_bytes:", data
-        for b in data:
-            self._s.write(struct.pack('B', b))
-    
-    def _unescape(self, packet):
-        r = []
-        esc = False
-        for b in packet:
-            if esc:
-                r.append(b ^ 0x20)
-                esc = False
-            elif b == self.HDLC_CTLESC_BYTE:
-                esc = True
-            else:
-                r.append(b)
-        return r
-    
-    def _escape(self, packet):
-        r = []
-        for b in packet:
-            if b == self.HDLC_FLAG_BYTE or b == self.HDLC_CTLESC_BYTE:
-                r.append(self.HDLC_CTLESC_BYTE)
-                r.append(b ^ 0x20)
-            else:
-                r.append(b)
-        return r
-    
-    def debug(self, debug):
-        self._debug = debug
-
-
-class SFClient:
-    def __init__(self, host, port, qsize=10):
-        self._in_queue = Queue(qsize)
-        self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self._s.connect((host, port))
-        data = self._s.recv(2)
-        if data != 'U ':
-            print "Wrong handshake"
-        self._s.send("U ")
-        print "Connected"
-        thread.start_new_thread(self.run, ())
-
-    def run(self):
-        while True:
-            length = ord(self._s.recv(1))
-            data = self._s.recv(length)
-            data = [ord(c) for c in data][1:]
-            #print "Recv %d bytes" % (length), ActiveMessage(data)
-            if self._in_queue.full():
-                print "Warning: Buffer overflow"
-                self._in_queue.get()
-            p = RawPacket()
-            p.crc = 1
-            p.data = data
-            self._in_queue.put(p, block=False)
-
-    def read(self, timeout=0):
-        return self._in_queue.get()
-
-    def write(self, payload):
-        print "SFClient: write:", payload
-        if type(payload) != type([]):
-            # Assume this will be derived from Packet
-            payload = payload.payload()
-        payload = [0] + payload
-        self._s.send(chr(len(payload)))
-        self._s.send(''.join([chr(c) for c in payload]))
-        return True
-
-class AM:
-    def __init__(self, s):
-        self._s = s
-
-    def read(self, timeout=0):
-        return ActiveMessage(self._s.read().data)
-
-    def write(self, packet, amid):
-        return self._s.write(ActiveMessage(packet, amid=amid))
-
-
-class Packet:
-    """
-    The Packet class offers a handy way to build pack and unpack
-    binary data based on a given pattern.
-    """
-
-    def _decode(self, v):
-        r = long(0)
-        for i in v:
-            r = (r << 8) + i
-        return r
-    
-    def _encode(self, val, dim):
-        output = []
-        for i in range(dim):
-            output.append(int(val & 0xFF))
-            val = val >> 8
-        output.reverse()
-        return output
-    
-    def __init__(self, desc, packet = None):
-        offset = 0
-        boffset = 0
-        sum = 0
-        for i in range(len(desc)-1, -1, -1):
-            (n, t, s) = desc[i]
-            if s == None:
-                if sum > 0:
-                    desc[i] = (n, t, -sum)
-                break
-            sum += s
-        self.__dict__['_schema'] = [(t, s) for (n, t, s) in desc]
-        self.__dict__['_names'] = [n for (n, t, s) in desc]
-        self.__dict__['_values'] = []
-        if type(packet) == type([]):
-            for (t, s) in self._schema:
-                if t == 'int':
-                    self._values.append(self._decode(packet[offset:offset + s]))
-                    offset += s
-                elif t == 'bint':
-                    doffset = 8 - (boffset + s)
-                    self._values.append((packet[offset] >> doffset) & ((1<<s) - 1))
-                    boffset += s
-                    if boffset == 8:
-                        offset += 1
-                        boffset = 0
-                elif t == 'string':
-                    self._values.append(''.join([chr(i) for i in packet[offset:offset + s]]))
-                    offset += s
-                elif t == 'blob':
-                    if s:
-                        if s > 0:
-                            self._values.append(packet[offset:offset + s])
-                            offset += s
-                        else:
-                            self._values.append(packet[offset:s])
-                            offset = len(packet) + s
-                    else:
-                        self._values.append(packet[offset:])
-        elif type(packet) == type(()):
-            for i in packet:
-                self._values.append(i)
-        else:
-            for v in self._schema:
-                self._values.append(None)
-
-    def __repr__(self):
-        return self._values.__repr__()
-
-    def __str__(self):
-        r = ""
-        for i in range(len(self._names)):
-            r += "%s: %s " % (self._names[i], self._values[i])
-        for i in range(len(self._names), len(self._values)):
-            r += "%s" % self._values[i]
-        return r
-#        return self._values.__str__()
-
-    # Implement the map behavior
-    def __getitem__(self, key):
-        return self.__getattr__(key)
-
-    def __setitem__(self, key, value):
-        self.__setattr__(key, value)
-
-    def __len__(self):
-        return len(self._values)
-
-    def keys(self):
-        return self._names
-
-    def values(self):
-        return self._names
-
-    # Implement the struct behavior
-    def __getattr__(self, name):
-        #print "DEBUG: __getattr__", name
-        if type(name) == type(0):
-            return self._names[name]
-        else:
-            return self._values[self._names.index(name)]
-
-    def __setattr__(self, name, value):
-        if type(name) == type(0):
-            self._values[name] = value
-        else:
-            self._values[self._names.index(name)] = value
-
-    def __ne__(self, other):
-        if other.__class__ == self.__class__:
-            return self._values != other._values
-        else:
-            return True
-
-    def __eq__(self, other):
-        if other.__class__ == self.__class__:
-            return self._values == other._values
-        else:
-            return False
-
-    def __nonzero__(self):
-        return True;
-
-    # Custom
-    def names(self):
-        return self._names
-
-    def sizes(self):
-        return self._schema
-
-    def payload(self):
-        r = []
-        boffset = 0
-        for i in range(len(self._schema)):
-            (t, s) = self._schema[i]
-            if t == 'int':
-                r += self._encode(self._values[i], s)
-                boffset = 0
-            elif t == 'bint':
-                doffset = 8 - (boffset + s)
-                if boffset == 0:
-                    r += [self._values[i] << doffset]
-                else:
-                    r[-1] |= self._values[i] << doffset
-                boffset += s
-                if boffset == 8:
-                    boffset = 0
-            elif self._values[i] != []:
-                r += self._values[i]
-        for i in self._values[len(self._schema):]:
-            r += i
-        return r
-
-
-class RawPacket(Packet):
-    def __init__(self, ts = None, data = None, crc = None):
-        Packet.__init__(self,
-                        [('ts' ,  'int', 4),
-                         ('crc',  'int', 1),
-                         ('data', 'blob', None)],
-                        None)
-        self.ts = ts;
-        self.data = data
-        self.crc = crc
-        
-class AckFrame(Packet):
-    def __init__(self, payload = None):
-        Packet.__init__(self,
-                        [('protocol', 'int', 1),
-                         ('seqno',    'int', 1)],
-                        payload)
-
-class DataFrame(Packet):
-    def __init__(self, payload = None):
-        if payload != None and type(payload) != type([]):
-            # Assume is a Packet
-            payload = payload.payload()
-        Packet.__init__(self,
-                        [('protocol',  'int', 1),
-                         ('seqno',     'int', 1),
-                         ('dispatch',  'int', 1),
-                         ('data',      'blob', None)],
-                        payload)
-
-class NoAckDataFrame(Packet):
-    def __init__(self, payload = None):
-        if payload != None and type(payload) != type([]):
-            # Assume is a Packet
-            payload = payload.payload()
-        Packet.__init__(self,
-                        [('protocol',  'int', 1),
-                         ('dispatch',  'int', 1),
-                         ('data',      'blob', None)],
-                        payload)
-
-class ActiveMessage(Packet):
-    def __init__(self, gpacket = None, amid = 0x00, dest = 0xFFFF):
-        if type(gpacket) == type([]):
-            payload = gpacket
-        else:
-            # Assume this will be derived from Packet
-            payload = None
-        Packet.__init__(self,
-                        [('destination', 'int', 2),
-                         ('source',   'int', 2),
-                         ('length',   'int', 1),
-                         ('group',    'int', 1),
-                         ('type',     'int', 1),
-                         ('data',     'blob', None)],
-                        payload)
-        if payload == None:
-            self.destination = dest
-            self.source = 0x0000
-            self.group = 0x00
-            self.type = amid
-            self.data = []
-            if gpacket:
-                self.data = gpacket.payload()
-            self.length = len(self.data)
-