From e0e9318f12a927d27728c7e4a5ddf50d472b5f7a Mon Sep 17 00:00:00 2001 From: Fabrice Theoleyre Date: Fri, 26 Jan 2018 11:00:52 +0100 Subject: [PATCH 1/5] stats for openserial --- .../bin/openVisualizerApp/logging.conf | 4 +- .../moteConnector/OpenParser.py | 9 +- .../moteConnector/ParserStat.py | 383 ++++++++++++++++++ 3 files changed, 393 insertions(+), 3 deletions(-) create mode 100644 software/openvisualizer/openvisualizer/moteConnector/ParserStat.py diff --git a/software/openvisualizer/bin/openVisualizerApp/logging.conf b/software/openvisualizer/bin/openVisualizerApp/logging.conf index f0d545eab..9ee46167e 100644 --- a/software/openvisualizer/bin/openVisualizerApp/logging.conf +++ b/software/openvisualizer/bin/openVisualizerApp/logging.conf @@ -21,7 +21,7 @@ keys=std,console [handler_std] class=handlers.RotatingFileHandler # args: filename, open mode, max file size, backup file count -args=('%(logDir)s/openVisualizer.log', 'a', 2000000, 5) +args=('%(logDir)s/openVisualizer.log', 'a', 20000000, 5) formatter=std [handler_console] @@ -32,7 +32,7 @@ formatter=console #============================ loggers ========================================= [loggers] -keys=root,eventBusMonitor,openTun,openTunWindows,openTunLinux,eventBusClient,lbrClient,moteConnector,moteProbe,moteProbeUtils,moteState,openLbr,OpenParser,Parser,OpenHdlc,ParserData,ParserInfoErrorCritical,ParserStatus,RPL,SourceRoute,udpInject,JRC,openVisualizerApp,openVisualizerGui,openVisualizerCli,openVisualizerWeb,OVtracer +keys=root,eventBusMonitor,openTun,openTunWindows,openTunLinux,eventBusClient,lbrClient,moteConnector,moteProbe,moteProbeUtils,moteState,openLbr,OpenParser,Parser,OpenHdlc,ParserData,ParserInfoErrorCritical,ParserStatus,ParserStat,RPL,SourceRoute,udpInject,JRC,openVisualizerApp,openVisualizerGui,openVisualizerCli,openVisualizerWeb,OVtracer [logger_root] level=ERROR diff --git a/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py b/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py index 423383367..1647ff2da 100644 --- a/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py +++ b/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py @@ -14,6 +14,7 @@ import ParserInfoErrorCritical as ParserIEC import ParserData import ParserPacket +import ParserStat class OpenParser(Parser.Parser): @@ -51,6 +52,7 @@ def __init__(self): self.parserCritical = ParserIEC.ParserInfoErrorCritical(self.SERFRAME_MOTE2PC_CRITICAL) self.parserData = ParserData.ParserData() self.parserPacket = ParserPacket.ParserPacket() + self.parserStat = ParserStat.ParserStat() # register subparsers self._addSubParser( @@ -83,6 +85,11 @@ def __init__(self): val = self.SERFRAME_MOTE2PC_SNIFFED_PACKET, parser = self.parserPacket.parseInput, ) + self._addSubParser( + index = 0, + val = self.SERFRAME_MOTE2PC_STAT, + parser = self.parserStat.parseInput, + ) #======================== public ========================================== - #======================== private ========================================= \ No newline at end of file + #======================== private ========================================= diff --git a/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py new file mode 100644 index 000000000..a2d351a9c --- /dev/null +++ b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py @@ -0,0 +1,383 @@ +# Copyright (c) 2015, CNRS. +# All rights reserved. +# +# Released under the BSD 3-Clause license as published at the link below. +# https://openwsn.atlassian.net/wiki/display/OW/License + +import logging +log = logging.getLogger('ParserStat') +log.setLevel(logging.INFO) +log.addHandler(logging.NullHandler()) + +import struct + +from pydispatch import dispatcher + +from ParserException import ParserException +import Parser + +from array import array + +class ParserStat(Parser.Parser): + + HEADER_LENGTH = 2 + MSPERSLOT = 15 #ms per slot. + + #type of stat message + SERTYPE_PKT_TX = 1 + SERTYPE_PKT_RX = 2 + SERTYPE_CELL = 3 + SERTYPE_ACK = 4 + SERTYPE_PKT_DROPPED = 5 + SERTYPE_DIO = 6 + SERTYPE_DAO = 7 + SERTYPE_NODESTATE = 8 + SERTYPE_6PCMD = 9 + + + + def __init__(self): + + # log + log.debug('create ParserStat instance') + + # initialize parent class + Parser.Parser.__init__(self,self.HEADER_LENGTH) + + self._asn= ['asn_4', # B + 'asn_2_3', # H + 'asn_0_1', # H + ] + + + + + + #======================== public ========================================== + + #======================== conversion ========================================== + + + #returns a string with the decimal value of a uint16_t + def BytesToString(self, bytes): + str = '' + i = 0 + + #print bytes + + for byte in bytes: + str = format(eval('{0} + {1} * 256 ** {2}'.format(str, byte, i))) + #print ('{0}:{1}'.format(i, str)) + i = i + 1 + + return(str) + + def BytesToAddr(self, bytes): + str = '' + i = 0 + + for byte in bytes: + str = str + '{:02x}'.format(byte) + #if (i < len(bytes)-1): + # str = str + '-' + i += 1 + + return(str) + + def ByteToCellMode(self, byte): + CELLMODE = { + 'ADD' : 1, + 'DEL' : 2 + } + for key, value in CELLMODE.iteritems(): + if value == byte: + return(key) + return("UNKNOWN") + + + def ByteToCellType(self, byte): + CELLTYPE = { + 'OFF' : 0, + 'TX' : 1, + 'RX' : 2, + 'TXRX' : 3, + 'SERIALRX' : 4, + 'MORESERIALRX' : 5 + } + for key, value in CELLTYPE.iteritems(): + if value == byte: + return(key) + return("UNKNOWN") + + + + + def ByteToSixtopCode(self, byte): + SIXTOPCODE = { + 'CELLADD_REQ' : 1, + 'CELLADD_REP' : 2, + 'CELLDEL_REQ' : 3, + 'CELLDEL_REP' : 4, + 'CELLLIST_REP' : 5, + 'CELLLIST_REQ' : 6, + 'CELLCLEAR_REP' : 7, + 'CELLCLEAR_REQ' : 8, + 'CELLCOUNT_REP' : 9, + 'CELLCOUNT_REQ' : 10 + } + + for key, value in SIXTOPCODE.iteritems(): + if value == byte: + return(key) + return("UNKNOWN") + + + def ByteToStatus(self, byte): + CODE = { + 'ENQUEUED' : 1, + 'TXED' : 2, + 'RCVD' : 3, + 'FAILED' : 4 + } + + for key, value in CODE.iteritems(): + if value == byte: + return(key) + return("UNKNOWN") + + + def ByteToL4protocol(self, byte): + + IANA = { + 'IANA_IPv6HOPOPT' : 0x00, + 'IANA_TCP' : 0x06, + 'IANA_UDP' : 0x11, + 'IANA_IPv6ROUTE' : 0x2b, + 'IANA_ICMPv6' : 0x3a, + 'IANA_ICMPv6_ECHO_REQUEST' : 128, + 'IANA_ICMPv6_ECHO_REPLY' : 129, + 'IANA_ICMPv6_RS' : 133, + 'IANA_ICMPv6_RA' : 134, + 'IANA_ICMPv6_RA_PREFIX_INFORMATION' : 3, + 'IANA_ICMPv6_RPL' : 155, + 'IANA_ICMPv6_RPL_DIO' : 0x01, + 'IANA_ICMPv6_RPL_DAO' : 0x02, + 'IANA_RSVP' : 46, + 'IANA_UNDEFINED' : 250 + } + + for key, value in IANA.iteritems(): + if value == byte: + return(key) + return("IANA_UNKNOWN") + + def ByteToFrameType(self, byte): + IEEE154_TYPE = { + 'IEEE154_TYPE_BEACON' : 0, + 'IEEE154_TYPE_DATA' : 1, + 'IEEE154_TYPE_ACK' : 2, + 'IEEE154_TYPE_CMD' : 3, + 'IEEE154_TYPE_UNDEFINED' : 5 + } + + for key, value in IEEE154_TYPE.iteritems(): + if value == byte: + return(key) + return("FTYPE_UNKNOWN") + + + def ByteToUDPPort(self, bytes): + + result = eval(self.BytesToString(bytes)) + + WKP = { + 'WKP_TCP_HTTP' : 80, + 'WKP_TCP_ECHO' : 7, + 'WKP_UDP_COAP' : 5683, + 'WKP_UDP_ECHO' : 7, + 'WKP_UDP_RINGMASTER' : 15000 + } + + for key, value in WKP.iteritems(): + if value == result: + return(key) + return("WKP_UNKNOWN") + + def BytesToCells(selfself, bytes): + result = '' + num = 0 + + for i in range(0, len(bytes) / 5) : + if (bytes[5*i] == 1): + result = result + format('choffset[{0}]={1}|slotoffset[{0}]={2}|'.format( + num, + bytes[5*i+1], + bytes[5*i+3] + )) + num = num + 1 + return(result) + + #======================== write logs (factroized) ========================================== + + #info to write when a packet is transmitted + def LogPktTx(self, addr, asnbytes, input, message): + log.info('{9}|addr={0}|asn={1}|length={2}|frameType={3}|slotOffset={4}|frequency={5}|l2Dest={6}|txpower={7}|numTxAttempts={8}|L3Src={10}|L3Dest={11}|L4Proto={12}|L4SrcPort={13}|L4DestPort={14}'.format( + self.BytesToAddr(addr), + self.BytesToString(asnbytes), + input[8], + self.ByteToFrameType(input[9]), + self.BytesToString(input[10:12]), + input[12], + self.BytesToAddr(input[13:21]), + input[21], + input[22], + message, + self.BytesToAddr(input[23:39]), + self.BytesToAddr(input[39:55]), + self.ByteToL4protocol(input[55]), + self.BytesToString(input[56:58]), + self.BytesToString(input[58:61]) + )); + + + #info to write when a packet is received + def LogPktRx(self, addr, asnbytes, input, message): + log.info('{10}|addr={0}|asn={1}|length={2}|frameType={3}|slotOffset={4}|frequency={5}|l2Src={6}|rssi={7}|lqi={8}|crc={9}'.format( + self.BytesToAddr(addr), + self.BytesToString(asnbytes), + input[8], + self.ByteToFrameType(input[9]), + self.BytesToString(input[10:12]), + input[12], + self.BytesToAddr(input[13:21]), + input[21], + input[22], + input[23], + message, + )); + + #info to write when a packet is dropped + def LogPktDropped(self, addr, asnbytes, input): + log.info('{5}|addr={0}|asn={1}|length={2}|frameType={3}|l2Src={4}|L3Src={11}|L3Dest={12}|L4Proto={13}|L4SrcPort={14}|L4DestPort={15}'.format( + self.BytesToAddr(addr), + self.BytesToString(asnbytes), + input[8], + input[9], + input[10], + self.BytesToAddr(input[11:19]), + message, + self.BytesToAddr(input[23:39]), + self.BytesToAddr(input[39:55]), + self.ByteToL4protocol(input[55]), + self.BytesToString(input[56:58]), + self.BytesToString(input[58:61]) + )); + + + + #======================== parses and writes the logs ========================================== + + def parseInput(self,input): + + # log + if log.isEnabledFor(logging.DEBUG): + log.debug('received stat {0}'.format(input)) + + + + #headers + addr = input[0:2] + asnbytes = input[2:7] + (self._asn) = struct.unpack(' 0): + dcr = float(TicsOn) / float(TicsTotal) * 100 + else: + dcr = 100 + + log.info('STAT_NODESTATE|addr={0}|asn={1}|DutyCycleRatio={2}|NumDeSync={3}'.format( + self.BytesToAddr(addr), + self.BytesToString(asnbytes), + dcr, + input[16] + )); + + elif (statType == self.SERTYPE_6PCMD): + log.info('STAT_6PCMD|addr={0}|asn={1}|command={2}|status={3}|neigh={4}|{5}'.format( + self.BytesToAddr(addr), + self.BytesToString(asnbytes), + self.ByteToSixtopCode(input[8]), + self.ByteToStatus(input[9]), + self.BytesToAddr(input[10:18]), + self.BytesToCells(input[18:]) + )); + + + else: + print('Unknown stat type: type {0} addr {1} asn {2}'.format( + statType, + self.BytesToAddr(addr), + self.BytesToString(asnbytes))) + + + return ('error', input) + + + + #======================== private ========================================= + + From 889368fcc61e95e054e39f5ca6500c59502224ba Mon Sep 17 00:00:00 2001 From: Fabrice Theoleyre Date: Fri, 26 Jan 2018 11:42:17 +0100 Subject: [PATCH 2/5] logging for parserStat --- software/openvisualizer/bin/openVisualizerApp/logging.conf | 6 ++++++ .../openvisualizer/moteConnector/OpenParser.py | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/software/openvisualizer/bin/openVisualizerApp/logging.conf b/software/openvisualizer/bin/openVisualizerApp/logging.conf index 9ee46167e..4ebad33bb 100644 --- a/software/openvisualizer/bin/openVisualizerApp/logging.conf +++ b/software/openvisualizer/bin/openVisualizerApp/logging.conf @@ -140,6 +140,12 @@ handlers=std propagate=0 qualname=ParserStatus +[logger_ParserStat] +level=INFO +handlers=std +propagate=0 +qualname=ParserStat + [logger_RPL] level=INFO handlers=std diff --git a/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py b/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py index 1647ff2da..98cfc9054 100644 --- a/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py +++ b/software/openvisualizer/openvisualizer/moteConnector/OpenParser.py @@ -27,7 +27,8 @@ class OpenParser(Parser.Parser): SERFRAME_MOTE2PC_CRITICAL = ParserIEC.ParserInfoErrorCritical.SEVERITY_CRITICAL SERFRAME_MOTE2PC_REQUEST = ord('R') SERFRAME_MOTE2PC_SNIFFED_PACKET = ord('P') - + SERFRAME_MOTE2PC_STAT = ord('T') + SERFRAME_PC2MOTE_SETDAGROOT = ord('R') SERFRAME_PC2MOTE_DATA = ord('D') SERFRAME_PC2MOTE_TRIGGERSERIALECHO = ord('S') From e6053842dbfe1becc3cb8f9477e11e90eeb6bddd Mon Sep 17 00:00:00 2001 From: Fabrice Theoleyre Date: Wed, 25 Apr 2018 17:19:23 +0200 Subject: [PATCH 3/5] removed the log for dropped packets --- .../moteConnector/ParserStat.py | 54 +++++-------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py index a2d351a9c..c316fdaa7 100644 --- a/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py +++ b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015, CNRS. +# Copyright (c) 2018, CNRS. # All rights reserved. # # Released under the BSD 3-Clause license as published at the link below. @@ -28,11 +28,10 @@ class ParserStat(Parser.Parser): SERTYPE_PKT_RX = 2 SERTYPE_CELL = 3 SERTYPE_ACK = 4 - SERTYPE_PKT_DROPPED = 5 - SERTYPE_DIO = 6 - SERTYPE_DAO = 7 - SERTYPE_NODESTATE = 8 - SERTYPE_6PCMD = 9 + SERTYPE_DIO = 5 + SERTYPE_DAO = 6 + SERTYPE_NODESTATE = 7 + SERTYPE_6PCMD = 8 @@ -40,7 +39,7 @@ def __init__(self): # log log.debug('create ParserStat instance') - + # initialize parent class Parser.Parser.__init__(self,self.HEADER_LENGTH) @@ -221,28 +220,26 @@ def BytesToCells(selfself, bytes): #info to write when a packet is transmitted def LogPktTx(self, addr, asnbytes, input, message): - log.info('{9}|addr={0}|asn={1}|length={2}|frameType={3}|slotOffset={4}|frequency={5}|l2Dest={6}|txpower={7}|numTxAttempts={8}|L3Src={10}|L3Dest={11}|L4Proto={12}|L4SrcPort={13}|L4DestPort={14}'.format( + log.info('{0}|addr={1}|asn={2}|length={3}|frameType={4}|slotOffset={5}|frequency={6}|txpower={7}|umTxAttempts={8}|l2Dest={9}|nL3Src={10}|L3Dest={11}|'.format( + message, self.BytesToAddr(addr), self.BytesToString(asnbytes), input[8], self.ByteToFrameType(input[9]), self.BytesToString(input[10:12]), input[12], - self.BytesToAddr(input[13:21]), - input[21], - input[22], - message, + input[13], + input[14], + self.BytesToAddr(input[15:23]), self.BytesToAddr(input[23:39]), self.BytesToAddr(input[39:55]), - self.ByteToL4protocol(input[55]), - self.BytesToString(input[56:58]), - self.BytesToString(input[58:61]) )); #info to write when a packet is received def LogPktRx(self, addr, asnbytes, input, message): - log.info('{10}|addr={0}|asn={1}|length={2}|frameType={3}|slotOffset={4}|frequency={5}|l2Src={6}|rssi={7}|lqi={8}|crc={9}'.format( + log.info('{0}|addr={1}|asn={2}|length={3}|frameType={4}|slotOffset={5}|frequency={5}|l2Src={6}|rssi={7}|lqi={8}|crc={9}'.format( + message, self.BytesToAddr(addr), self.BytesToString(asnbytes), input[8], @@ -253,24 +250,6 @@ def LogPktRx(self, addr, asnbytes, input, message): input[21], input[22], input[23], - message, - )); - - #info to write when a packet is dropped - def LogPktDropped(self, addr, asnbytes, input): - log.info('{5}|addr={0}|asn={1}|length={2}|frameType={3}|l2Src={4}|L3Src={11}|L3Dest={12}|L4Proto={13}|L4SrcPort={14}|L4DestPort={15}'.format( - self.BytesToAddr(addr), - self.BytesToString(asnbytes), - input[8], - input[9], - input[10], - self.BytesToAddr(input[11:19]), - message, - self.BytesToAddr(input[23:39]), - self.BytesToAddr(input[39:55]), - self.ByteToL4protocol(input[55]), - self.BytesToString(input[56:58]), - self.BytesToString(input[58:61]) )); @@ -282,9 +261,7 @@ def parseInput(self,input): # log if log.isEnabledFor(logging.DEBUG): log.debug('received stat {0}'.format(input)) - - - + #headers addr = input[0:2] asnbytes = input[2:7] @@ -317,9 +294,6 @@ def parseInput(self,input): self.ByteToStatus(input[8]), self.BytesToAddr(input[9:17]) )); - elif (statType == self.SERTYPE_PKT_DROPPED): - self.LogPktDropped(addr, asnbytes, statType, input, "STAT_PK_DROPPED"); - elif (statType == self.SERTYPE_DIO): log.info('STAT_DIO|addr={0}|asn={1}|status={2}|rplinstanceId={3}|rank={4}|DODAGID={5}'.format( From 3e49dc61a24259dd32a52273a6eb85e117f39798 Mon Sep 17 00:00:00 2001 From: Fabrice Theoleyre Date: Wed, 25 Apr 2018 17:34:21 +0200 Subject: [PATCH 4/5] typos in the stat names --- .../openvisualizer/openvisualizer/moteConnector/ParserStat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py index c316fdaa7..829e94785 100644 --- a/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py +++ b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py @@ -220,7 +220,7 @@ def BytesToCells(selfself, bytes): #info to write when a packet is transmitted def LogPktTx(self, addr, asnbytes, input, message): - log.info('{0}|addr={1}|asn={2}|length={3}|frameType={4}|slotOffset={5}|frequency={6}|txpower={7}|umTxAttempts={8}|l2Dest={9}|nL3Src={10}|L3Dest={11}|'.format( + log.info('{0}|addr={1}|asn={2}|length={3}|frameType={4}|slotOffset={5}|frequency={6}|txpower={7}|numTxAttempts={8}|l2Dest={9}|L3Src={10}|L3Dest={11}|'.format( message, self.BytesToAddr(addr), self.BytesToString(asnbytes), From cf4ea7613202ce6cb2da6266d13dc3cf0f10ed78 Mon Sep 17 00:00:00 2001 From: Fabrice Theoleyre Date: Thu, 26 Apr 2018 10:48:43 +0200 Subject: [PATCH 5/5] reordering some fields --- .../moteConnector/ParserStat.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py index 829e94785..0de7693a2 100644 --- a/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py +++ b/software/openvisualizer/openvisualizer/moteConnector/ParserStat.py @@ -220,17 +220,17 @@ def BytesToCells(selfself, bytes): #info to write when a packet is transmitted def LogPktTx(self, addr, asnbytes, input, message): - log.info('{0}|addr={1}|asn={2}|length={3}|frameType={4}|slotOffset={5}|frequency={6}|txpower={7}|numTxAttempts={8}|l2Dest={9}|L3Src={10}|L3Dest={11}|'.format( + log.info('{0}|addr={1}|asn={2}|l2Dest={3}|length={4}|frameType={5}|slotOffset={6}|frequency={7}|txpower={8}|numTxAttempts={9}|L3Src={10}|L3Dest={11}|'.format( message, self.BytesToAddr(addr), self.BytesToString(asnbytes), - input[8], - self.ByteToFrameType(input[9]), - self.BytesToString(input[10:12]), - input[12], - input[13], - input[14], - self.BytesToAddr(input[15:23]), + self.BytesToAddr(input[8:16]), + input[16], + self.ByteToFrameType(input[17]), + self.BytesToString(input[18:20]), + input[20], + input[21], + input[22], self.BytesToAddr(input[23:39]), self.BytesToAddr(input[39:55]), )); @@ -238,15 +238,15 @@ def LogPktTx(self, addr, asnbytes, input, message): #info to write when a packet is received def LogPktRx(self, addr, asnbytes, input, message): - log.info('{0}|addr={1}|asn={2}|length={3}|frameType={4}|slotOffset={5}|frequency={5}|l2Src={6}|rssi={7}|lqi={8}|crc={9}'.format( + log.info('{0}|addr={1}|asn={2}|l2Src={3}|length={4}|frameType={5}|slotOffset={6}|frequency={7}|rssi={8}|lqi={9}|crc={10}|'.format( message, self.BytesToAddr(addr), self.BytesToString(asnbytes), - input[8], - self.ByteToFrameType(input[9]), - self.BytesToString(input[10:12]), - input[12], - self.BytesToAddr(input[13:21]), + self.BytesToAddr(input[8:16]), + input[16], + self.ByteToFrameType(input[17]), + self.BytesToString(input[18:20]), + input[20], input[21], input[22], input[23],