[Tinyos-2-commits]
CVS: tinyos-2.x/tools/tinyos/misc tinyos.py, NONE,
1.1 tos-build-deluge-image, NONE, 1.1 tos-deluge, NONE, 1.1
Razvan Musaloiu-E.
razvanm at users.sourceforge.net
Tue May 22 13:34:22 PDT 2007
Update of /cvsroot/tinyos/tinyos-2.x/tools/tinyos/misc
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv24715/tools/tinyos/misc
Added Files:
tinyos.py tos-build-deluge-image tos-deluge
Log Message:
Initial commit of the Deluge T2. Some notes:
- TOSBoot includes some code to allow the MicaZ version to compile but it's not support for it it's not done yet.
- tools/tinyos/misc/Makefile.am is not updated yet so the new tools will not be installed by default.
--- NEW FILE: tinyos.py ---
import struct, time, serial, socket
# Copyright (c) 2007 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 Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
# @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
class Serial:
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
__s = None # An instance of serial.Serial object
__debug = False # Debug mode
def __init__(self, port, baudrate):
self.__s = serial.Serial(port, baudrate, rtscts=0, timeout=0.5)
def __format_packet(self, packet):
return " ".join(["%02x" % p for p in packet]) + " | " + \
" ".join(["%d" % p for p in packet])
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):
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
# Returns the next incoming serial packet
def sniff_packet(self):
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)
un_packet = self.__unescape(packet)
crc = self.crc16(0, un_packet[1:-3])
packet_crc = self.__decode(un_packet[-3:-1])
if self.__debug == True:
if crc != packet_crc:
print "Warning: wrong CRC!"
print "Recv:", self.__format_packet(un_packet)
return (ts, un_packet)
except socket.timeout:
return None
# Filters and returns the next incoming serial packet with
# specified AM group ID and AM ID
def read_packet(self, am_group, am_id):
packet = None
while True:
packet = self.sniff_packet()
if not packet == None and len(packet[1]) >= 10:
if (packet[1])[8] == am_group and (packet[1])[9] == am_id:
break
return packet
# Sends data with the specified AM group ID and AM ID. To have a "reliable"
# transfer, num_tries defines how many times to retry before giving up
def write_packet(self, am_group, am_id, data, num_tries=10):
for i in range(num_tries):
# The first byte after SERIAL_PROTO_PACKET_ACK is a sequence
# number that will be send back by the mote to ack the receive of
# the data.
packet = [self.SERIAL_PROTO_PACKET_ACK, 0, self.TOS_SERIAL_ACTIVE_MESSAGE_ID,
0xff, 0xff,
0, 0,
len(data), am_group, am_id] + data
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]
self.__put_bytes(packet)
if self.__debug == True:
print "Send:", self.__format_packet(packet)
# Waits for ACK
for j in range(3):
while True:
packet = self.sniff_packet()
if packet == None:
break
elif (packet[1])[1] == self.SERIAL_PROTO_ACK:
return True
# Debug messages
if self.__debug == True:
if i == (num_tries - 1):
print "Failed to send the packet!"
else:
print "Timeout waiting for ACK... Retry"
return False
def set_debug(self, debug):
self.__debug = debug
class GenericPacket:
""" GenericPacket """
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):
self.__dict__['_schema'] = [(t, s) for (n, t, s) in desc]
self.__dict__['_names'] = [n for (n, t, s) in desc]
self.__dict__['_values'] = []
offset = 10
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 == 'blob':
if s:
self._values.append(packet[offset:offset + s])
offset += s
else:
self._values.append(packet[offset:-3])
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):
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):
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
# Custom
def names(self):
return self._names
def sizes(self):
return self._schema
def payload(self):
r = []
for i in range(len(self._schema)):
(t, s) = self._schema[i]
if t == 'int':
r += self.__encode(self._values[i], s)
else:
r += self._values[i]
return r
--- NEW FILE: tos-build-deluge-image ---
#!/usr/bin/env python
# Copyright (c) 2007 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 Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
# @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
import sys, struct, operator
from xml.dom.minidom import parse
DELUGE_PKTS_PER_PAGE = 48
DELUGE_PKT_PAYLOAD_SIZE = 23
DELUGE_BYTES_PER_PAGE = DELUGE_PKTS_PER_PAGE * DELUGE_PKT_PAYLOAD_SIZE
DELUGE_MAX_PAGES = 128
DELUGE_METADATA_SIZE = 16
DELUGE_IDENT_SIZE = 128
def sencode(s, dim):
s = [ord(c) for c in s]
if len(s) > dim:
return s[:dim]
return s + [0] * (dim - len(s))
def encode(val, dim):
output = []
for i in range(dim):
output.append(val & 0xFF)
val = val >> 8
return output
def decode(v):
r = long(0)
for i in v[::-1]:
r = (r << 8) + i
return r
def int2byte(v):
return "".join([struct.pack("B", i) for i in v])
def crc16(data):
crc = 0
for b in 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 pages(data):
return (len(data) / DELUGE_BYTES_PER_PAGE) + \
(len(data) % DELUGE_BYTES_PER_PAGE != 0)
def align(data):
mod = len(data) % DELUGE_BYTES_PER_PAGE
if mod == 0:
return data
return data + [0] * (DELUGE_BYTES_PER_PAGE - mod)
def deluge_metadata(data, img_num):
uid = ident['uid_hash']
num_pages = pages(data)
image_number = img_num
crc = crc16([image_number] + [num_pages])
completed_pages = num_pages
return encode(uid, 4) + \
encode(version, 2) + \
[image_number] + \
[num_pages] + \
encode(crc, 2) + \
[completed_pages] + \
[0] + \
encode(len(data) + 16, 2) + \
([0] * 2)
def deluge_ident():
tmp = sencode(ident['program_name'], 16) + \
sencode(ident['user_id'], 16) + \
sencode(ident['hostname'], 16) + \
sencode(ident['platform'], 16) + \
encode(ident['size'], 4) + \
encode(ident['unix_time'], 4) + \
encode(ident['user_hash'], 4) + \
encode(ident['uid_hash'], 4)
return tmp + [0] * (DELUGE_IDENT_SIZE - len(tmp))
def deluge_crc(data):
crc = [0] * DELUGE_MAX_PAGES
crc[0] = crc16(data[2*DELUGE_MAX_PAGES:DELUGE_BYTES_PER_PAGE])
#sys.stderr.write("crc[0] = 0x%x\n" % (crc[0]))
j = 1
for i in range(DELUGE_BYTES_PER_PAGE, len(data)-1, DELUGE_BYTES_PER_PAGE):
crc[j] = crc16(data[i:i+DELUGE_BYTES_PER_PAGE])
#sys.stderr.write("crc[%d] = 0x%x\n" % (j, crc[j]))
j += 1
return reduce(operator.add, [encode(i, 2) for i in crc]) + data[2*DELUGE_MAX_PAGES:]
version = 0
for i in range(len(sys.argv)):
if sys.argv[i] == '-v':
version = int(sys.argv[i+1])
elif sys.argv[i] == '-i':
img_num = int(sys.argv[i+1])
dom = parse(sys.argv[-1])
ident = {}
ident_list = [(n.localName, n.firstChild.nodeValue)
for n in dom.getElementsByTagName('ident')[0].childNodes if n.localName != None]
for (k, v) in ident_list:
ident[k] = v
for p in ['unix_time', 'user_hash', 'uid_hash']:
ident[p] = int(ident[p][:-1], 16)
image = dom.getElementsByTagName('image')[0].firstChild.nodeValue
all = []
section = []
end_addr = None
for line in image.split():
#print "DEBUG:", line
length = int(line[1:3], 16)
addr = int(line[3:7], 16)
rectype = int(line[7:9], 16)
data = []
if len(line) > 11:
data = [int(line[i:i+2], 16) for i in range(9, len(line)-2, 2)]
crc = int(line[-2:], 16)
if rectype in [0x00, 0x03]:
if not end_addr:
end_addr = addr
start_addr = addr
if end_addr != addr:
all.append((start_addr, section))
if rectype == 0x03:
# This last record updates the first 4 bytes which
# holds some some low level configuration. They are
# the same all the time so I guess that's why they are
# skipped.
break
section = []
start_addr = addr
section += data
end_addr = addr + length
elif rectype == 0x01:
all.append((start_addr, section))
section = []
start_addr = addr
sys.stderr.write('Ihex read complete:\n')
sys.stderr.write(' Total bytes = %d\n' % reduce(operator.add, [len(l) for (_, l) in all]))
sys.stderr.write(' Sections = %d\n' % len(all))
# Usually, there are two sections: one for the code and one for the
# interrupt vector.
all_data = []
for (addr, data) in all:
all_data += encode(addr, 4) + \
encode(len(data), 4) + \
data
ident['size'] = len(all_data)
all_data = deluge_ident() + all_data
all_data = align([0] * 2 * DELUGE_MAX_PAGES + all_data)
all_data = deluge_crc(all_data)
sys.stdout.write(int2byte(deluge_metadata(all_data, img_num)) + \
int2byte(all_data))
--- NEW FILE: tos-deluge ---
#!/usr/bin/env python
# Copyright (c) 2007 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 Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
# @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
###############################################################################
# Deluge Python Toolchain
#
# 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"
###############################################################################
import sys, os, stat, struct, subprocess
import tinyos
from datetime import datetime
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')
# TinyOS serial communication parameters
SERIAL_AMGROUP = 0
SERIAL_AMID = 0xAB
SERIAL_DATA_PAYLOAD_SIZE = 80
# Serial message types
MSG_ERASE = 0
MSG_WRITE = 1
MSG_READ = 2
MSG_REPROG = 5
MSG_DISS = 6
ERROR_SUCCESS = 0
ERROR_FAIL = 1
# 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
class SerialReqPacket(tinyos.GenericPacket):
def __init__(self, packet = None):
tinyos.GenericPacket.__init__(self,
[('msg_type', 'int', 1),
('img_num', 'int', 1),
('offset', 'int', 2),
('len', 'int', 2),
('data', 'blob', None)],
packet)
class SerialReplyPacket(tinyos.GenericPacket):
def __init__(self, packet = None):
tinyos.GenericPacket.__init__(self,
[('error', 'int', 1),
('data', 'blob', None)],
packet)
# Displays an integer representation of byte stream to hex representation
def print_hex(start_addr, byte_stream):
num_iterations = int( (len(byte_stream) - 1) / HEX_OUTPUT_LINE_SIZE ) + 1
for i in range(num_iterations):
line = "%07x" % start_addr + " " # Prints memory address
for j in range(HEX_OUTPUT_LINE_SIZE):
if (i * HEX_OUTPUT_LINE_SIZE + j) < len(byte_stream):
line += "%02x" % byte_stream[i * HEX_OUTPUT_LINE_SIZE + j] + " "
print line
start_addr += HEX_OUTPUT_LINE_SIZE
# Computes 16-bit CRC
def crc16(data):
crc = 0
for b in 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
# Converts a byte-stream array to int representation
def toInt(byte_stream):
r = long(0)
for i in byte_stream[::-1]:
r = (r << 8) + i
return r
# Converts a byte-stream array to string representation
def toString(byte_stream):
r = ""
for i in range(len(byte_stream)):
if byte_stream[i] == 0:
r += " "
else:
r += struct.pack("B", byte_stream[i])
return r
# Converts a byte-stream array to image status string representation
def toStatusStr(num_space, binary_stream):
r = "%sProg Name: %s\n" % (" " * num_space,
toString(binary_stream[16:32]))
r += "%sCompiled On: %s\n" % (" " * num_space,
datetime.fromtimestamp(toInt(binary_stream[84:88])).strftime('%a %h %d %T %Y'))
r += "%sPlatform: %s\n" % (" " * num_space,
toString(binary_stream[64:80]))
r += "%sUser ID: %s\n" % (" " * num_space,
toString(binary_stream[32:48]))
r += "%sHost Name: %s\n" % (" " * num_space,
toString(binary_stream[48:64]))
r += "%sUser Hash: %s\n" % (" " * num_space,
hex(toInt(binary_stream[88:92])))
r += "%sNum Pages: %d/%d" % (" " * num_space,
toInt(binary_stream[7:8]),
toInt(binary_stream[10:11]))
r += "\n\n"
r += "%sSize: %d\n" % (" " * num_space,
toInt(binary_stream[12:14]))
r += "%sUID: %d\n" % (" " * num_space,
toInt(binary_stream[0:4]))
r += "%sVersion: %d" % (" " * num_space,
toInt(binary_stream[4:6]))
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):
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"
else:
print "ERROR: Unable to retrieve image information"
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
print "No proper Deluge image found!"
return False
# Erases an image volume
def op_erase(s, img_num):
sreqpkt = SerialReqPacket((MSG_ERASE, 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 erase the flash volume"
return False
print "ERROR: Unable to send the command"
return False
# Writes to an image volume
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)
sreqpkt.offset = 0
while length > 0:
# Calculates the payload size for the current packet
if length >= SERIAL_DATA_PAYLOAD_SIZE:
sreqpkt.len = SERIAL_DATA_PAYLOAD_SIZE
else:
sreqpkt.len = length
sreqpkt.data = []
# Reads in the file we want to transmit
for i in range(sreqpkt.len):
sreqpkt.data.append(struct.unpack("B", binary_stream[sreqpkt.offset + i])[0])
# Sends over serial to the mote
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
return False
# Waiting for confirmation
packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
sreplypkt = SerialReplyPacket(packet[1])
if sreplypkt.error != ERROR_SUCCESS:
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
return True
# Injects an image (specified by tos_image_xml) to an image volume
def op_inject(s, img_num, tos_image_xml):
# 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
if not metadata == None:
version = toInt(metadata[4:6]) + 1 # Increments the version
print toStatusStr(2, metadata)
else:
print " No proper Deluge image found!"
print "--------------------------------------------------"
# 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.stderr.read(),
print "--------------------------------------------------"
# Writes the new binary image
if op_erase(s, img_num):
if op_write(s, img_num, p.stdout.read()):
metadata = getMetaData(s, img_num)
if not metadata == None:
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"
return False
# 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
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
return False
# Waiting for confirmation
packet = s.read_packet(SERIAL_AMGROUP, SERIAL_AMID)
sreplypkt = SerialReplyPacket(packet[1])
if sreplypkt.error != ERROR_SUCCESS:
print "ERROR: Unable to write new versioning information"
return False
return True
def print_usage():
print "Usage: %s <device> <-p|-i|-r|-d|-e|-s> image_number [options]" % sys.argv[0]
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 " -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
if len(sys.argv) >= num_req_arg:
try:
sys.argv[3] = int(sys.argv[3])
except:
print "ERROR: Volume ID 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
except:
print "ERROR: Unable to initialize serial port connection"
os._exit(-1)
if sys.argv[2] 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):
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]):
print "Command sent"
elif sys.argv[2] in ["-d", "--dissemination"]:
if op_diss(s, sys.argv[3]):
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]):
print "Successfully reset image versioning information"
else:
print_usage()
else:
print_usage()
More information about the Tinyos-2-commits
mailing list