📄 tossimnescdecls.py
字号:
if len(bytes) != self.size:
raise Exception("Byte conversion error: %s %d bytes to %d" %
(self.nescType, len(bytes), self.size) )
return bytes
def setBytes(self, bytes) :
if len(bytes) < self.size:
raise Exception("Byte conversion error: %s %d bytes to %d" %
( self.nescType, len(bytes), self.size) )
return bytes[self.size:]
###########
# Struct of basic nesc types,
###########
class nescStruct( object ) :
"""A python representation of a nesc structure.
usage:
struct = nescStruct(myTypes, xmlDecl)
struct = nescStruct(structName, (fieldName, type) (fieldName, type), ...)
X = struct.field
struct.field = X
bytes = struct.getBytes()
struct.setBytes(bytes)
struct
print struct
"""
def __init__( self, *varargs) :
"""initialize all fields to 0"""
self.__dict__["value"] = {}
self.fields = []
self.size = 0
if len(varargs) == 0 :
self.nescType = ""
#create the struct from nescType args
elif len(varargs) >= 1 and ( type(varargs[0]) == str or
type(varargs[0]) == unicode ) :
self.nescType = varargs[0]
self._parseNescTypeFields(varargs[1:])
## parse the struct def from xml
elif len(varargs) == 2 and type(varargs[1]) != tuple :
(nescTypes, xmlDefinition) = varargs[:]
if xmlDefinition.tagName != "struct" :
raise Exception("Not struct definition")
if xmlDefinition.hasAttribute("name") == False:
raise Exception("Anonymous struct")
self.nescType = xmlDefinition.getAttribute("name")
if xmlDefinition.getAttribute("size")[2:]:
self.size = int(xmlDefinition.getAttribute("size")[2:])
else:
self.size = 0
self._parseXMLFields(nescTypes, xmlDefinition)
else :
raise Exception("Illegal nescStruct constructor args")
self.cType = self.nescType
self.pythonType = self.nescType
self.__initialized = True
def __getattr__(self, name) :
if self.__dict__.has_key("value") :
if self.value.has_key(name) :
if self.value[name].__class__ == nescType :
return self.value[name].value
else :
return self.value[name]
else :
raise AttributeError("No such field \"%s\" in the nescStruct \"%s\"" % (name, self.nescType))
def __setattr__(self, name, value) :
if not self.__dict__.has_key("_nescStruct__initialized") :
self.__dict__[name] = value
return
if self.value.has_key(name) :
if self.value[name].__class__ == nescType :
self.value[name].value = value;
else :
self.value[name] = value;
elif self.__dict__.has_key(name) :
self.__dict__[name] = value
else :
raise AttributeError("No such field \"%s\" in the nescStruct \"%s\"" % (name, self.nescType))
def __repr__(self) :
return "%s object at %s:\n\n\t%s" % (self.__class__, hex(id(self)), str(self))
def __str__(self) :
"""All fields and values as a readable string"""
string = self.nescType + ": \n"
for field in self.fields :
string += "%30s : %s\n" % (
"%s %s" % (self.value[field["name"]].nescType, field["name"]),
self.value[field["name"]].oneLineStr() )
return string
def oneLineStr(self) :
"""A one-line representation of the struct"""
return self.nescType
def __deepcopy__(self, memo={}) :
result = self.__class__()
memo[id(self)] = result
self._copyFields(result, memo)
return result
def _copyFields(self, other, memo=None) :
other.size = self.size
other.nescType = self.nescType
other.cType = self.cType
other.pythonType = self.pythonType
if memo == None :
other.value = deepcopy(self.value)
other.fields = deepcopy(self.fields)
else :
other.value = deepcopy(self.value, memo)
other.fields = deepcopy(self.fields, memo)
other.__initialized = True
def _parseXMLFields(self, nescTypes, xmlDefinition) :
"""Create a list of fields & values given a struct xml declaration."""
fields = [node for node in xmlDefinition.getElementsByTagName("field")]
fields.sort( lambda A, B : int(A.getAttribute("bit-offset")[2:]) - int(B.getAttribute("bit-offset")[2:]))
for fieldDef in fields:
field = {}
field["name"] = fieldDef.getAttribute("name")
field["bitOffset"] = int(fieldDef.getAttribute("bit-offset")[2:])
if fieldDef.hasAttribute("bit-size"):
field["bitSize"] = int(fieldDef.getAttribute("bit-size")[2:])
elif fieldDef.hasAttribute("size"):
field["bitSize"] = int(fieldDef.getAttribute("size")[2:])*8
self.fields.append(field)
self.value[fieldDef.getAttribute("name")] = nescTypes.getTypeFromXML(fieldDef)
#here's a weird bug in the nesc.xml generation where the "size" attribute
#for packed structs is actually the size of the unpacked struct.
if xmlDefinition.hasAttribute("packed") :
self.size = self.packedSize()
elif xmlDefinition.getAttribute("size")[2:]:
self.size = int(xmlDefinition.getAttribute("size")[2:])
else:
self.size = 0
def _parseNescTypeFields(self, fields) :
"""Create a list of fields & values given a tuple of
fieldname,value sequences."""
self.size = 0
for fieldDef in fields:
field = {}
(field["name"],fType) = fieldDef
field["bitOffset"] = self.size*8
field["bitSize"] = fType.size*8
self.fields.append(field)
self.value[field["name"]] = fType
self.size += fType.size
def isType(self, xmlDefinition) :
"""returns 1 if the xml definition describes this type.
Returns 0 otherwise."""
if xmlDefinition == None :
return 0
child = getUniqueChild(xmlDefinition)
if ( ( xmlDefinition.tagName == "struct" and
xmlDefinition.getAttribute("name") == self.nescType) or
( xmlDefinition.tagName == "type-tag" and child != None and
child.tagName == "struct-ref" and
child.getAttribute("name") == self.nescType ) ) :
return 1
else :
return 0
def getBytes(self) :
"""Hexidecimal representation of struct"""
# We have to be careful in here about:
# 1. bit fields (ie. bitSize shorter than nominal type size)
# 2. packing (ie. bits that are not part of any particular field)
bits = ""
for field in self.fields :
for i in range(len(bits), field["bitOffset"]) :
bits += "0"
newBits = hex2bin(self.value[field["name"]].getBytes())
bits += newBits[-field["bitSize"]:]
#the following loop is just type checking for bit fields. Can we do this on setattr?
for i in range(len(newBits)-field["bitSize"]):
if newBits[i] == "1":
print "Bit-field type error: value of %s.%s being truncated" % (self.nescType,
field["name"])
for i in range(len(bits), self.size*8) :
bits += "0"
bytes = bin2hex(bits)
if len(bytes) != self.size:
raise Exception("Byte conversion error: %s %d bytes to %d" %
( self.nescType, len(bytes), self.size))
return bytes
def setBytes(self, bytes) :
"""Set all values using hexidecimal representation"""
# We have to be careful in here about:
# 1. bit fields (ie. bitSize shorter than nominal type size)
# 2. packing (ie. bits that are not part of any particular field)
if len(bytes) < self.size:
raise Exception("Byte conversion error: %s %d bytes to %d" %
(self.nescType, len(bytes), self.size) )
bits = hex2bin(bytes)
for field in self.fields :
newBits = ""
for i in range(self.value[field["name"]].size*8) :
newBits += "0"
selectedBits=bits[field["bitOffset"]:field["bitOffset"]+field["bitSize"]]
newBits = newBits[:-field["bitSize"]] + selectedBits
newBytes = ""
for i in range(self.value[field["name"]].size) :
newBytes += '\x00'
tmpBytes = bin2hex(newBits)
newBytes = newBytes[:-len(tmpBytes)] + tmpBytes
self.value[field["name"]].setBytes(newBytes);
return bytes[self.size:]
def packedSize(self) :
if len(self.fields) == 0 :
trueSize = 0
else :
a,b,lastField = self._findLastNestedField()
trueSize = (lastField["bitOffset"] + lastField["bitSize"]) /8
return trueSize
def _findLastNestedField(self) :
lastField = self
parents = []
#find the last (possibly nested) field
while issubclass(type(lastField), nescStruct) and len(lastField.fields) > 0 :
parent = lastField
lastFieldDef = parent.fields[-1]
lastField = parent.value[lastFieldDef["name"]]
parents.append( parent )
return (lastField, parents, lastFieldDef)
class TosMsg ( nescStruct ) :
"""A python representation of a TosMsg.
Is a nescStruct object.
Can be used with
pytos.comm.send, pytos.comm.register, pytos.comm.unregister.
usage:
msg = TosMsg(amType)
msg = TosMsg(amType, nescStruct)
msg = TosMsg(amType, <nescStruct constructor args>)
print msg
msg.field = X
comm.send(msg)
comm.register(msg, f)
comm.unregister(msg, f)
migMsg = msg.createMigMsg()
msg.parseMigMsg(migMsg)
"""
def __init__(self, amType, *varargs):
self.amType = amType
self.parentMsg = None
#if this is a nescStruct argument, make myself a clone of it
if len(varargs) == 1 and issubclass(type(varargs[0]), nescStruct) :
nescStruct._copyFields(varargs[0],self)
#otherwise, make myself into a struct with the struct args
elif len(varargs) >= 1:
nescStruct.__init__(self, *varargs)
def __deepcopy__(self, memo={}) :
result = self.__class__(self.amType)
memo[id(self)] = result
self._copyFields(result, memo)
result.parentMsg = deepcopy(self.parentMsg, memo)
return result
def getParentMsg(self, amOrName) :
"""This function will get the parent message with the amType or name specified"""
if self.parentMsg == None :
return None
elif self.parentMsg.nescType == amOrName or self.parentMsg.amType == amOrName :
return self.parentMsg
else :
return self.parentMsg.getParentMsg(amOrName)
def createMigMsg(self) :
"""Returns a java BaseTOSMsg with same amType and length
and with data payload of same bytes"""
Message = tinyos.message.Message()
msg = Message(self.size)
msg.dataSet(unpack( str(self.size) + 'b', self.getBytes() ) )
msg.amTypeSet(self.amType)
# msg.set_type( self.amType )
# msg.set_length(self.size)
return msg
def parseMigMsg(self, msg) :
"""Takes a java BaseTOSMsg and creates TosMsg
with same amType and length and with data payload of same bytes"""
self.amType = msg.amType()
data = list(msg.dataGet())
self.setBytes(pack(str(len(data)) + 'b', *data))
def __repr__(self) :
return "%s object at %s:\n\n\t%s" % (self.__class__, hex(id(self)), str(self))
def __str__(self) :
"""All fields and values as a readable string"""
return "TosMsg(am=%d) " % self.amType + nescStruct.__str__(self)
def setBytes(self, bytes) :
"""Extend this msg to be longer, if necessary to accomodate extra data.
This only happens if the last field is a nescArray of length 0.
Unlike nescStructs, TosMsg objects are not nested recursively, so it is
Ok to do this."""
if len(bytes) > self.size : #trueSize() :
#print "there are more bytes than fit in this msg... trying to grow msg"
lastField, parents,b = self._findLastNestedField()
#see if it is an array of size 0
if type(lastField) == nescArray and lastField.len == 0 :
#make it bigger
#print "last field is nescArray[0]... growing"
lastFieldSize = lastField.elementType.size
numExtraBytes = len(bytes) - self.size #trueSize()
if numExtraBytes % lastFieldSize == 0:
requiredArraySize = int( numExtraBytes/lastFieldSize )
lastField = nescArray(requiredArraySize, lastField.elementType)
#print "new size is %d" % numExtraBytes
#and set it, changing the size of all parent structs
parents.reverse()
for parent in parents :
# trueSize = parent.trueSize()
parent.value[parent.fields[-1]["name"]] = lastField
parent.fields[-1]["bitSize"] = lastField.size*8
parent.size = self.packedSize()# + lastField.size
lastField = parent
else:
#print "last field is not nescArray[0]. Cannot grow. Ignoring extra data."
pass
#make sure everything worked out correctly and call parent's function
if len(bytes) != self.size :#trueSize() :
raise Exception("Incorrect number of bytes for TosMsg. Byte conversion error: %s %d bytes to %d" % ( self.nescType, len(bytes), self.size) )
#print "passing to child to set bytes."
nescStruct.setBytes(self,bytes)
def getUniqueChild(xmlDefinition) :
child = None
for childNode in xmlDefinition.childNodes :
if childNode.nodeType == 1 :
child = childNode
break
return child
def bin2hex(bits) :
bytes = ""
for i in range(0, len(bits), 8 ):
bytes += pack('B',int(bits[i:i+8],2))
return bytes
def hex2bin(bytes) :
bits = ""
for i in range(len(bytes)) :
val, = unpack('B',bytes[i])
for j in range(7,-1,-1):
if val>= pow(2,j):
bits += "1"
val -= pow(2,j)
else :
bits += "0"
return bits
def TestAppTypes() :
testRpc = appTypes('/home/kamin/tinyos-1.x/contrib/hood/apps/TestRpc/build/telosb/nesc.xml')
print testRpc
if __name__ == "__main__": TestAppTypes()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -