Skip to content

Commit

Permalink
Merge pull request #153 from openwsn-berkeley/develop_FW-540
Browse files Browse the repository at this point in the history
FW-540. XON/XOFF-based openserial.
  • Loading branch information
changtengfei authored Oct 17, 2018
2 parents 71dfb87 + 4ebddc9 commit 24761e0
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 73 deletions.
20 changes: 12 additions & 8 deletions software/openvisualizer/bin/serialTesterCli/serialTesterCli.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ def _quit_cb(self):
self.moteConnector_handler.quit()
self.moteProbe_handler.close()

#============================ main ============================================

def main():

moteProbe_handler = None
Expand All @@ -138,16 +140,18 @@ def main():
#============================ application logging =============================
import logging
import logging.handlers
logHandler = logging.handlers.RotatingFileHandler('serialTesterCli.log',
maxBytes=2000000,
backupCount=5,
mode='w')
logHandler = logging.handlers.RotatingFileHandler(
'serialTesterCli.log',
maxBytes=2000000,
backupCount=5,
mode='w'
)
logHandler.setFormatter(logging.Formatter("%(asctime)s [%(name)s:%(levelname)s] %(message)s"))
for loggerName in [
'SerialTester',
'moteProbe',
'OpenHdlc',
]:
'SerialTester',
'moteProbe',
'OpenHdlc',
]:
temp = logging.getLogger(loggerName)
temp.setLevel(logging.DEBUG)
temp.addHandler(logHandler)
Expand Down
109 changes: 96 additions & 13 deletions software/openvisualizer/openvisualizer/BspEmulator/BspUart.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ class BspUart(BspModule.BspModule):
Emulates the 'uart' BSP module
'''

INTR_TX = 'uart.tx'
INTR_RX = 'uart.rx'
BAUDRATE = 115200
INTR_TX = 'uart.tx'
INTR_RX = 'uart.rx'
BAUDRATE = 115200

XOFF = 0x13
XON = 0x11
XONXOFF_ESCAPE = 0x12
XONXOFF_MASK = 0x10

def __init__(self,motehandler):

Expand All @@ -39,6 +44,8 @@ def __init__(self,motehandler):
self.uartTxBufferLock = threading.Lock()
self.waitForDoneReading = threading.Lock()
self.waitForDoneReading.acquire()
self.fXonXoffEscaping = False
self.xonXoffEscapedByte = 0

# initialize the parent
BspModule.BspModule.__init__(self,'BspUart')
Expand All @@ -60,7 +67,7 @@ def read(self):
assert len(self.uartRxBuffer)>0
returnVal = [chr(b) for b in self.uartRxBuffer]
self.uartRxBuffer = []

# return that element
return returnVal

Expand Down Expand Up @@ -137,15 +144,54 @@ def cmd_clearTxInterrupts(self):

# update variables
self.txInterruptFlag = False
def cmd_writeByte(self,byteToWrite):

def cmd_writeByte(self, byteToWrite):
'''emulates
void uart_writeByte(uint8_t byteToWrite)'''

# log the activity
if self.log.isEnabledFor(logging.DEBUG):
self.log.debug('cmd_writeByte byteToWrite='+str(self.byteToWrite))

# set tx interrupt flag
self.txInterruptFlag = True

# calculate the time at which the byte will have been sent
doneSendingTime = self.timeline.getCurrentTime()+float(1.0/float(self.BAUDRATE))

# schedule uart TX interrupt in 1/BAUDRATE seconds
self.timeline.scheduleEvent(
doneSendingTime,
self.motehandler.getId(),
self.intr_tx,
self.INTR_TX
)

if byteToWrite==self.XON or byteToWrite==self.XOFF or byteToWrite==self.XONXOFF_ESCAPE:
self.fXonXoffEscaping = True;
self.xonXoffEscapedByte = byteToWrite;
# add to receive buffer
with self.uartRxBufferLock:
self.uartRxBuffer += [self.XONXOFF_ESCAPE]
else:
# add to receive buffer
with self.uartRxBufferLock:
self.uartRxBuffer += [byteToWrite]

# release the semaphore indicating there is something in RX buffer
self.uartRxBufferSem.release()

# wait for the moteProbe to be done reading
self.waitForDoneReading.acquire()

def cmd_setCTS(self, state):
'''emulates
void uart_setCTS(bool state)'''

# log the activity
if self.log.isEnabledFor(logging.DEBUG):
self.log.debug('uart_setCTS state='+str(self.state))

# set tx interrupt flag
self.txInterruptFlag = True

Expand All @@ -162,7 +208,10 @@ def cmd_writeByte(self,byteToWrite):

# add to receive buffer
with self.uartRxBufferLock:
self.uartRxBuffer += [byteToWrite]
if (state==True):
self.uartRxBuffer += [self.XON]
else:
self.uartRxBuffer += [self.XOFF]

# release the semaphore indicating there is something in RX buffer
self.uartRxBufferSem.release()
Expand Down Expand Up @@ -207,8 +256,14 @@ def _writeBuffer(self,buffer):

# add to receive buffer
with self.uartRxBufferLock:
i = 0
while i != len(buffer):
if buffer[i]==self.XON or buffer[i]==self.XOFF or buffer[i]==self.XONXOFF_ESCAPE:
newitem = (self.XONXOFF_ESCAPE, buffer[i]^self.XONXOFF_MASK)
buffer[i:i+1] = newitem
i += 1
self.uartRxBuffer += buffer

# release the semaphore indicating there is something in RX buffer
self.uartRxBufferSem.release()

Expand All @@ -226,7 +281,7 @@ def cmd_readByte(self):
# retrieve the byte last sent
with self.uartTxBufferLock:
return self.uartTxNext

#======================== interrupts ======================================

def intr_tx(self):
Expand All @@ -237,9 +292,37 @@ def intr_tx(self):
# log the activity
if self.log.isEnabledFor(logging.DEBUG):
self.log.debug('intr_tx')

# send interrupt to mote
self.motehandler.mote.uart_isr_tx()

if self.fXonXoffEscaping==True:
self.fXonXoffEscaping = False

# set tx interrupt flag
self.txInterruptFlag = True

# calculate the time at which the byte will have been sent
doneSendingTime = self.timeline.getCurrentTime()+float(1.0/float(self.BAUDRATE))

# schedule uart TX interrupt in 1/BAUDRATE seconds
self.timeline.scheduleEvent(
doneSendingTime,
self.motehandler.getId(),
self.intr_tx,
self.INTR_TX
)

# add to receive buffer
with self.uartRxBufferLock:
self.uartRxBuffer += [self.xonXoffEscapedByte^self.XONXOFF_MASK]

# release the semaphore indicating there is something in RX buffer
self.uartRxBufferSem.release()

# wait for the moteProbe to be done reading
self.waitForDoneReading.acquire()

else:
# send interrupt to mote
self.motehandler.mote.uart_isr_tx()

# do *not* kick the scheduler
return False
Expand Down
7 changes: 1 addition & 6 deletions software/openvisualizer/openvisualizer/RPL/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ def __init__(self):
self.dataLock = threading.Lock()
self.parents = {}
self.parentsLastSeen = {}
self.parentsDelay = {}
self.NODE_TIMEOUT_THRESHOLD = 900

eventBusClient.eventBusClient.__init__(
Expand Down Expand Up @@ -83,11 +82,7 @@ def updateParents(self,sender,signal,data):
self.parents.update({data[0]:data[1]})
self.parentsLastSeen.update({data[0]: time.time()})

with open("dagRecord.txt",'a') as f:
f.write("\ntotal nodes number: {0}\n".format(len(self.parents)))
for addr, timestamp in self.parentsLastSeen.iteritems():
f.write('--addr {0} timestamp {1}\n'.format(''.join(['%02X' % x for x in addr[-2:]]), time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp))))
# self._clearNodeTimeout()
self._clearNodeTimeout()

def _clearNodeTimeout(self):
threshold = time.time() - self.NODE_TIMEOUT_THRESHOLD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def __init__(self,mote):
mote.set_callback(notifId('uart_writeCircularBuffer_FASTSIM'), self.bspUart.cmd_writeCircularBuffer_FASTSIM)
mote.set_callback(notifId('uart_writeBufferByLen_FASTSIM'), self.bspUart.uart_writeBufferByLen_FASTSIM)
mote.set_callback(notifId('uart_readByte'), self.bspUart.cmd_readByte)
mote.set_callback(notifId('uart_setCTS'), self.bspUart.cmd_setCTS)

# logging this module
self.log = logging.getLogger('MoteHandler_'+str(self.id))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ class OpenParser(Parser.Parser):
SERFRAME_MOTE2PC_INFO = ParserIEC.ParserInfoErrorCritical.SEVERITY_INFO
SERFRAME_MOTE2PC_ERROR = ParserIEC.ParserInfoErrorCritical.SEVERITY_ERROR
SERFRAME_MOTE2PC_CRITICAL = ParserIEC.ParserInfoErrorCritical.SEVERITY_CRITICAL
SERFRAME_MOTE2PC_REQUEST = ord('R')
SERFRAME_MOTE2PC_SNIFFED_PACKET = ord('P')
SERFRAME_MOTE2PC_PRINTF = ord('F')

SERFRAME_MOTE2PC_ACKREPLY = ord('A')

SERFRAME_PC2MOTE_SETDAGROOT = ord('R')
SERFRAME_PC2MOTE_DATA = ord('D')
SERFRAME_PC2MOTE_TRIGGERSERIALECHO = ord('S')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ def __init__(self):
'lastUsedAsn_4', # B
'lastUsedAsn_2_3', # H
'lastUsedAsn_0_1', # H

],
)
self._addFieldsParser (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,17 @@ def _runtest(self):
self._resetStats()

# send packets and collect stats
for i in range(numTestPkt):
for pktNum in range(numTestPkt):

# prepare random packet to send
packetToSend = [random.randint(0x00,0xff) for _ in range(testPktLen)]
#packetToSend = [i+1 for i in range(testPktLen)]
#packetToSend = [0x00]*testPktLen

# remember as last sent packet
with self.dataLock:
self.lastSent = packetToSend[:]

# send
self.dispatch(
signal = 'fromMoteConnector@'+self.moteProbeSerialPort,
Expand All @@ -155,15 +157,16 @@ def _runtest(self):
self.stats['numSent'] += 1

# log
self._log('--- packet {0}'.format(pktNum))
self._log('sent: {0}'.format(self.formatList(self.lastSent)))

# wait for answer
self.waitForReply.clear()
if self.waitForReply.wait(timeout):

# log
self._log('received: {0}'.format(self.formatList(self.lastReceived)))

# echo received
with self.dataLock:
if self.lastReceived==self.lastSent:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import ParserException

class moteConnector(eventBusClient.eventBusClient):

DFLT_TIMEOUT = 5 ##< timeout in second for getting an ack

def __init__(self,serialport):

Expand All @@ -34,10 +36,15 @@ def __init__(self,serialport):
self.serialport = serialport

# local variables
self.dataLock = threading.RLock()
self.parser = OpenParser.OpenParser()
self.stateLock = threading.Lock()
self.networkPrefix = None
self._subcribedDataForDagRoot = False
self.busySending = False
self.lastReceived = []
self.timeout = self.DFLT_TIMEOUT
self.waitForReply = threading.Event()

# give this thread a name
self.name = 'moteConnector@{0}'.format(self.serialport)
Expand All @@ -56,9 +63,14 @@ def __init__(self,serialport):
'signal' : 'cmdToMote',
'callback' : self._cmdToMote_handler,
},
{
'sender' : self.WILDCARD,
'signal' : 'fromMoteProbe@'+self.serialport,
'callback' : self._receiveAckFromMoteSerial,
},
]
)

# subscribe to dispatcher
dispatcher.connect(
self._sendToParser,
Expand Down Expand Up @@ -323,6 +335,19 @@ def _bytesToMesh_handler(self,sender,signal,data):
self._sendToMoteProbe(
dataToSend = [OpenParser.OpenParser.SERFRAME_PC2MOTE_DATA]+nextHop+lowpan,
)


def _receiveAckFromMoteSerial(self,sender,signal,data):

# handle ack
if chr(data[0])==chr(OpenParser.OpenParser.SERFRAME_MOTE2PC_ACKREPLY):
# don't handle if I'm not testing
with self.dataLock:
if not self.busySending:
return
with self.dataLock:
# wake up other thread
self.waitForReply.set()

#======================== public ==========================================

Expand All @@ -332,13 +357,25 @@ def quit(self):
#======================== private =========================================

def _sendToMoteProbe(self,dataToSend):
try:
dispatcher.send(
sender = self.name,
signal = 'fromMoteConnector@'+self.serialport,
data = ''.join([chr(c) for c in dataToSend])
)

except socket.error:
log.error(err)
pass

sendDone = False
while sendDone is False:

try:
self.busySending = True
dispatcher.send(
sender = self.name,
signal = 'fromMoteConnector@'+self.serialport,
data = ''.join([chr(c) for c in dataToSend])
)

except socket.error:
log.error(err)
pass
else:
# wait for ack
self.waitForReply.clear()
if self.waitForReply.wait(self.timeout):
sendDone = True

self.busySending = False
Loading

0 comments on commit 24761e0

Please sign in to comment.