]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tools/tinyos/misc/tos-deluge
Rename the TOSBoot to tosboot.
[tinyos-2.x.git] / tools / tinyos / misc / tos-deluge
index ec12aad2fcb7dc78b93bf2b3be6f25549d80d048..ae1bb1aa31d35e944682426b925adf0f3d0eb0aa 100755 (executable)
 #
 # A command line utility to interact with nodes via a direct serial connection.
 # For the usage menu, please run this tool without any arguments. For example, 
-# "./tos-deluge.py"
+# "./tos-deluge"
 ###############################################################################
 
-import sys, os, stat, struct, subprocess
+import sys, os, stat, struct, subprocess, time
 import tinyos
 from datetime import datetime
 import os.path 
@@ -39,29 +39,32 @@ import os.path
 # Script-specific parameters
 HEX_OUTPUT_LINE_SIZE = 16
 # Path to the python script that builds Deluge image from XML
-PY_PATH_BUILD_IMAGE  = os.path.join(os.path.dirname(sys.argv[0]), 'tos-build-deluge-image')
+PATH_PY_BUILD_IMAGE  = os.path.join(os.path.dirname(sys.argv[0]), 'tos-build-deluge-image')
 
 # TinyOS serial communication parameters
-SERIAL_AMGROUP           = 0
-SERIAL_AMID              = 0xAB
-SERIAL_DATA_PAYLOAD_SIZE = 80
+SERIAL_AMGROUP     = 0
+SERIAL_AMID        = 0xAB
+SERIAL_DATA_LENGTH = 28 - 1 - 1 - 2 - 2
 
 # Serial message types
-MSG_ERASE    = 0
-MSG_WRITE    = 1
-MSG_READ     = 2
-MSG_REPROG   = 5
-MSG_DISS     = 6
+MSG_ERASE     = 0
+MSG_WRITE     = 1
+MSG_READ      = 2
+MSG_REPROG    = 5
+MSG_DISS      = 6
+MSG_REPROG_BS = 7
 
-ERROR_SUCCESS = 0
-ERROR_FAIL    = 1
+ERROR_SUCCESS = 0   # T2-compatible
+ERROR_FAIL    = 1   # T2-compatible
 
 # Deluge-specific parameters
-DELUGE_PKTS_PER_PAGE    = 48
-DELUGE_PKT_PAYLOAD_SIZE = 23
-DELUGE_MAX_PAGES        = 128
-DELUGE_METADATA_SIZE    = 16 + 16 + 16 + 16 + 4 + 4 + 4 + 4   # Metadata size in binary 
-                                                              # image
+DELUGE_PLATFORMS       = ["telosb", "micaz"]   # Currently supported platforms
+DELUGE_MAX_PAGES       = 128
+DELUGE_METADATA_OFFSET = 0   # Location offset in the image
+DELUGE_METADATA_SIZE   = 16
+DELUGE_IDENT_OFFSET    = 16 + (2 * DELUGE_MAX_PAGES)
+DELUGE_IDENT_SIZE      = 16 + 16 + 16 + 16 + 4 + 4 + 4 + 4   # Metadata size in binary 
+                                                             # image
 
 class SerialReqPacket(tinyos.GenericPacket):
     def __init__(self, packet = None):
@@ -154,51 +157,74 @@ def toStatusStr(num_space, binary_stream):
     
     return r
 
-# Returns the metadata (first 16 bytes of the image) plus the "ident" 
-# (DELUGE_METADATA_SIZE bytes after CRC)
-def getMetaData(s, img_num):
+# Reads a portion from the image in the external flash
+def op_read(s, img_num, offset, length):
     r = []
+    
     # Gets the metadata (first 16 bytes of the image)
-    sreqpkt = SerialReqPacket((MSG_READ, img_num, 0, 16, []))
-  
-    if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()):
-        packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
-        sreplypkt = SerialReplyPacket(packet[1])
-        if sreplypkt.error == ERROR_SUCCESS:
-            r.extend(sreplypkt.data)
-      
-            # Gets the "ident" portion of the image
-            sreqpkt["offset"] = 16 + (2 * DELUGE_MAX_PAGES)
-            sreqpkt["len"] = DELUGE_METADATA_SIZE
-            if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()):
-                packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
-                sreplypkt = SerialReplyPacket(packet[1])
-                if sreplypkt.error == ERROR_SUCCESS:
-                    r.extend(sreplypkt.data)
-                    
-                    # Checks for valid CRC and timestamp
-                    if crc16(r[6:8]) == toInt(r[8:10]) and r[84:88] != [0xFF, 0xFF, 0xFF, 0xFF]:
-                        return r
-                else:
-                    print "ERROR: Unable to retrieve image information"
+    sreqpkt = SerialReqPacket((MSG_READ, img_num, offset, length, []))
+    while True:
+        if sreqpkt['len'] > SERIAL_DATA_LENGTH:
+            sreqpkt['len'] = SERIAL_DATA_LENGTH
+        
+        if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()):
+            packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
+            sreplypkt = SerialReplyPacket(packet[1])
+            if sreplypkt.error == ERROR_SUCCESS:
+                r.extend(sreplypkt.data)
+            else:
+                r = None
+                break
+        else:
+            r = None
+            break
+        
+        sreqpkt['offset'] = sreqpkt['offset'] + sreqpkt['len']
+        if sreqpkt['offset'] >= (offset + length):
+            break
+        sreqpkt['len'] = (offset + length) - sreqpkt['offset']
+        
+    return r
+    
+# Checks for valid CRC and image timestamp
+def verifyMetaData(r):
+    if r != None:
+        if crc16(r[6:8]) == toInt(r[8:10]) and r[84:88] != [0xFF, 0xFF, 0xFF, 0xFF]:
+            return True
         else:
-            print "ERROR: Unable to retrieve image information"
+            print "WARNING: Invalid image format detected"
+    
+    return False
 
+# Returns the metadata (first 16 bytes of the image) plus the "ident" 
+# (DELUGE_IDENT_SIZE bytes after CRC)
+def getMetaData(s, img_num):
+    # Gets the metadata (first 16 bytes of the image)
+    r = op_read(s, img_num, DELUGE_METADATA_OFFSET, DELUGE_METADATA_SIZE)
+
+    # Gets the "ident" portion of the image
+    if r != None:
+        temp = op_read(s, img_num, DELUGE_IDENT_OFFSET, DELUGE_IDENT_SIZE)
+        if temp != None:
+            r.extend(temp)
+            return r
+    
+    print "ERROR: Unable to retrieve image information over serial"
     return None
 
 # Prints status of the image in the external flash
 def op_ping(s, img_num):
     metadata = getMetaData(s, img_num)
     if not metadata == None:
-        print "Connected to Deluge node."
-        # Prints out image status
-        print "--------------------------------------------------"
-        print "Stored image %d" % img_num
-        print toStatusStr(2, metadata)
-        print "--------------------------------------------------"
-        return True
+        if verifyMetaData(metadata) == True:
+            print "Connected to Deluge node."
+            # Prints out image status
+            print "--------------------------------------------------"
+            print "Stored image %d" % img_num
+            print toStatusStr(2, metadata)
+            print "--------------------------------------------------"
+            return True
         
-    print "No proper Deluge image found!"
     return False
 
 # Erases an image volume
@@ -222,12 +248,22 @@ def op_write(s, img_num, binary_stream):
     sreqpkt = SerialReqPacket((MSG_WRITE, img_num, 0, 0, []))
     local_crc = 0   # Running CRC
     length = len(binary_stream)
+    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_PAYLOAD_SIZE:
-            sreqpkt.len = SERIAL_DATA_PAYLOAD_SIZE
+        if length >= SERIAL_DATA_LENGTH:
+            sreqpkt.len = SERIAL_DATA_LENGTH
         else:
             sreqpkt.len = length
         sreqpkt.data = []
@@ -238,6 +274,7 @@ def op_write(s, img_num, binary_stream):
         
         # Sends over serial to the mote
         if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) == False:
+            print
             print "ERROR: Unable to send the last serial packet (file offset: %d)" % sreqpkt.offset
             return False
         
@@ -245,97 +282,124 @@ def op_write(s, img_num, binary_stream):
         packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
         sreplypkt = SerialReplyPacket(packet[1])
         if sreplypkt.error != ERROR_SUCCESS:
+            print
             print "ERROR: Unable to write to the flash volume (file offset: %d)" % sreqpkt.offset
             return False
             
         local_crc = s.crc16(local_crc, sreqpkt.data)   # Computes running CRC
         length -= sreqpkt.len
         sreqpkt.offset += sreqpkt.len
-        
+
+    print '\r' + ' ' * 52,
+    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
 
 # Injects an image (specified by tos_image_xml) to an image volume
 def op_inject(s, img_num, tos_image_xml):
+    # Checks for valid file path
+    try:
+        os.stat(tos_image_xml)         # Checks whether tos_image_xml is a valid file
+    except:
+        print "ERROR: Unable to find the TOS image XML, \"%s\"" % tos_image_xml
+        return False
+    try:
+        os.stat(PATH_PY_BUILD_IMAGE)   # Checks whether PATH_PY_BUILD_IMAGE is a valid file
+    except:
+        print "ERROR: Unable to find the image building utility, \"%s\"" % PATH_PY_BUILD_IMAGE
+        return False
+  
     # Gets status information of stored image
-    metadata = getMetaData(s, img_num)
-    print "Connected to Deluge nodes."
-    print "--------------------------------------------------"
-    print "Stored image %d" % img_num
     version = 0
+    metadata = getMetaData(s, img_num)
     if not metadata == None:
-        version = toInt(metadata[4:6]) + 1   # Increments the version
-        print toStatusStr(2, metadata)
+        print "Connected to Deluge nodes."
+        if verifyMetaData(metadata) == True:
+            print "--------------------------------------------------"
+            print "Stored image %d" % img_num
+            print toStatusStr(2, metadata)
+            version = toInt(metadata[4:6]) + 1   # Increments the version
     else:
-        print "  No proper Deluge image found!"
-    print "--------------------------------------------------"
+        return False
     
     # Creates binary image from the TOS image XML
-    try:
-        os.stat(tos_image_xml)         # Checks whether tos_image_xml is a valid file
-        os.stat(PY_PATH_BUILD_IMAGE)   # Checks whether PY_PATH_BUILD_IMAGE is a valid file
-    except:
-        print "ERROR: Unable to create a binary image from the TOS image XML, \"%s\"" % tos_image_xml
-        return False
-    p = subprocess.Popen([PY_PATH_BUILD_IMAGE, "-v", str(version), "-i", str(img_num), tos_image_xml], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    print "--------------------------------------------------"
+    p = subprocess.Popen([PATH_PY_BUILD_IMAGE, "-v", str(version), "-i", str(img_num), tos_image_xml], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     print p.stderr.read(),
     print "--------------------------------------------------"
     
     # Writes the new binary image
     if op_erase(s, img_num):
         if op_write(s, img_num, p.stdout.read()):
+            print "--------------------------------------------------"
             metadata = getMetaData(s, img_num)
-            if not metadata == None:       
-                print "Replace image with:"
-                print toStatusStr(2, metadata)
-                print "--------------------------------------------------"
-        
-                return True
+            if not metadata == None:
+                if verifyMetaData(metadata) == True:
+                    print "Replace image with:"
+                    print toStatusStr(2, metadata)
+                    print "--------------------------------------------------"
+                    return True
     
     return False
 
-# Requests the mote to reboot and reprogram itself
-def op_reprog(s, img_num):
-    if getMetaData(s, img_num) == None:
-        print "ERROR: No proper Deluge image found!"
-    else:
-        sreqpkt = SerialReqPacket((MSG_REPROG, img_num, 0, 0, []))
-        success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload())
-        if success == True:
-            packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
-            sreplypkt = SerialReplyPacket(packet[1])
-            if sreplypkt.error == ERROR_SUCCESS:
-                return True
-            else:
-                print "ERROR: Unable to reboot the mote"
-                return False
-            
-        print "ERROR: Unable to send the command"
+# Requests the base station to reprogram itself
+def op_reprog_bs(s, img_num):
+    metadata = getMetaData(s, img_num)
+    if not metadata == None:
+        if verifyMetaData(metadata) == True:
+            sreqpkt = SerialReqPacket((MSG_REPROG_BS, img_num, 0, 0, []))
+            success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload())
+            if success == True:
+                packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
+                sreplypkt = SerialReplyPacket(packet[1])
+                if sreplypkt.error == ERROR_SUCCESS:
+                    return True
+                else:
+                    print "ERROR: Unable to reprogram the base station"
+                
+            print "ERROR: Unable to send the command"
+    
     return False
 
+# Requests the network to reprogram with the specified image number
+def op_reprog(s, img_num):
+    sreqpkt = SerialReqPacket((MSG_REPROG, img_num, 0, 0, []))
+    success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload())
+    if success == True:
+        packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
+        sreplypkt = SerialReplyPacket(packet[1])
+        if sreplypkt.error == ERROR_SUCCESS:
+            return True
+        else:
+            print "ERROR: Unable to reprogram the network"
+            return False
+        
+    print "ERROR: Unable to send the command"
+
 # Requests the mote to disseminate an image
 def op_diss(s, img_num):
-    if getMetaData(s, img_num) == None:
-        print "ERROR: No proper Deluge image found!"
-    else:
-        sreqpkt = SerialReqPacket((MSG_DISS, img_num, 0, 0, []))
-        success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload())
-        if success == True:
-            packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
-            sreplypkt = SerialReplyPacket(packet[1])
-            if sreplypkt.error == ERROR_SUCCESS:
-                return True
-            else:
-                print "ERROR: Unable to start the command dissemination"
-                return False
+    metadata = getMetaData(s, img_num)
+    if not metadata == None:
+        if verifyMetaData(metadata) == True:
+            sreqpkt = SerialReqPacket((MSG_DISS, img_num, 0, 0, []))
+            success = s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload())
+            if success == True:
+                packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
+                sreplypkt = SerialReplyPacket(packet[1])
+                if sreplypkt.error == ERROR_SUCCESS:
+                    return True
+                else:
+                    print "ERROR: Unable to start the command dissemination"
+                
+            print "ERROR: Unable to send the command"
             
-        print "ERROR: Unable to send the command"
     return False
-      
+
 # Resets image versioning information
 def op_reset(s, img_num):
     sreqpkt = SerialReqPacket((MSG_WRITE, img_num, 4, 2, [0, 0]))
     if s.write_packet(SERIAL_AMGROUP, SERIAL_AMID, sreqpkt.payload()) == False:
-        print "ERROR: Unable to send the last serial packet (file offset: %d)" % sreqpkt.offset
+        print "ERROR: Unable to send the command"
         return False
         
     # Waiting for confirmation
@@ -346,51 +410,63 @@ def op_reset(s, img_num):
         return False
             
     return True
-      
+
 def print_usage():
-    print "Usage: %s <device> <-p|-i|-r|-d|-e|-s> image_number [options]" % sys.argv[0]
+    print "Usage: %s <device_port> <baud_rate> <-p|-i|-r|-d|-e|-s> image_number [options]" % sys.argv[0]
+    print "  <baud_rate>\n     Either the platform name or the baud rate value"
+    print "      -------------------"
+    print "      | micaz  |  57600 |"
+    print "      ---------+---------"
+    print "      | telosb | 115200 |"
+    print "      -------------------"
+    print ""
     print "  -p --ping\n     Provide status of the image in the external flash"
     print "  -i --inject\n     Inject a compiled TinyOS application"
-    print "      [options]: <tos_image.xml file path>"
-    print "  -r --reboot\n     Reboot and reprogram the directly-connected mote"
+    print "      [options]: tos_image.xml file path"
+    print "  -r --reprogram\n     Reprogram the network"
+    print "  -b --reprogram_bs\n     Reprogram only the directly-connected mote"
     print "  -d --dissemination\n     Disseminate the image in the external flash to the network"
     print "  -e --erase\n     Erase an image in the external flash"
     print "  -s --reset\n     Reset the versioning information for a given image"
 
 # ======== MAIN ======== #
-num_req_arg = 4   # Minimum number of required arguments for this script
+num_req_arg = 5   # Minimum number of required arguments for this script
 if len(sys.argv) >= num_req_arg:
+    # Checks for valid image number format
     try:
-        sys.argv[3] = int(sys.argv[3])
+        sys.argv[4] = int(sys.argv[4])
     except:
-        print "ERROR: Volume ID is not valid"
+        print "ERROR: Image number is not valid"
         os._exit(-1)
     
     # Initializes serial port communication
     try:
-        s = tinyos.Serial(sys.argv[1], 115200)
-        s.set_debug(False)   # Disables debug msg
+        s = tinyos.Serial(sys.argv[1], sys.argv[2])
+        s.set_debug(False)
     except:
-        print "ERROR: Unable to initialize serial port connection"
+        print "ERROR: Unable to initialize serial port connection to", sys.argv[1]
         os._exit(-1)
     
-    if sys.argv[2] in ["-p", "--ping"]:
+    if sys.argv[3] in ["-p", "--ping"]:
         print "Pinging node ..."
-        op_ping(s, sys.argv[3]) 
-    elif sys.argv[2] in ["-i", "--inject"] and len(sys.argv) == (num_req_arg + 1):
+        op_ping(s, sys.argv[4]) 
+    elif sys.argv[3] in ["-i", "--inject"] and len(sys.argv) == (num_req_arg + 1):
         print "Pinging node ..."
-        op_inject(s, sys.argv[3], sys.argv[4])
-    elif sys.argv[2] in ["-r", "--reboot"]:
-        if op_reprog(s, sys.argv[3]):
+        op_inject(s, sys.argv[4], sys.argv[5])
+    elif sys.argv[3] in ["-r", "--reprogram"]:
+        if op_reprog(s, sys.argv[4]):
+            print "Command sent"
+    elif sys.argv[3] in ["-b", "--reprogram_bs"]:
+        if op_reprog_bs(s, sys.argv[4]):
             print "Command sent"
-    elif sys.argv[2] in ["-d", "--dissemination"]:
-        if op_diss(s, sys.argv[3]):
+    elif sys.argv[3] in ["-d", "--dissemination"]:
+        if op_diss(s, sys.argv[4]):
             print "Command sent"
-    elif sys.argv[2] in ["-e", "--erase"]:
-        if op_erase(s, sys.argv[3]):
-            print "Image number %d erased" % sys.argv[3]
-    elif sys.argv[2] in ["-s", "--reset"]:
-        if op_reset(s, sys.argv[3]):
+    elif sys.argv[3] in ["-e", "--erase"]:
+        if op_erase(s, sys.argv[4]):
+            print "Image number %d erased" % sys.argv[4]
+    elif sys.argv[3] in ["-s", "--reset"]:
+        if op_reset(s, sys.argv[4]):
             print "Successfully reset image versioning information"
     else:
         print_usage()