THCI support ser2net devices (#885)

* THCI support ser2net

* use readline for commissioner log
This commit is contained in:
Buke Po
2016-10-25 22:30:31 -07:00
committed by Jonathan Hui
parent f600840499
commit d4e112dc3f
+135 -23
View File
@@ -32,9 +32,12 @@
>> Class : ARM
'''
import re
import sys
import time
import serial
import socket
import logging
from IThci import IThci
from pexpect_serial import SerialSpawn
from GRLLibs.UtilityModules.Test import Thread_Device_Role, Device_Data_Requirement, MacType
@@ -43,6 +46,8 @@ from GRLLibs.UtilityModules.ModuleHelper import ModuleHelper, ThreadRunner
from GRLLibs.ThreadPacket.PlatformPackets import PlatformDiagnosticPacket, PlatformPackets
from Queue import Queue
linesepx = re.compile(r'\r\n|\n')
"""regex: used to split lines"""
class ARM(IThci):
firmware = 'Sep 9 2016 14:57:36'# keep the consistency with ARM firmware style
@@ -62,6 +67,7 @@ class ARM(IThci):
try:
self.mac = kwargs.get('EUI')
self.port = kwargs.get('SerialPort')
self.handle = None
self.UIStatusMsg = self.firmware
self.networkName = ModuleHelper.Default_NwkName
self.networkKey = ModuleHelper.Default_NwkKey
@@ -84,10 +90,92 @@ class ARM(IThci):
def __del__(self):
"""close the serial port connection"""
try:
self.serial.close()
self.closeConnection()
except Exception, e:
ModuleHelper.WriteIntoDebugLogger("delete() Error: " + str(e))
def _expect(self, expected, times=100):
"""Find the `expected` line within `times` trials.
Args:
expected str: the expected string
times int: number of trials
"""
print('[%s] Expecting [%s]' % (self.port, expected))
for i in range(0, times):
line = self._readline()
print('[%s] Got line [%s]' % (self.port, line))
if line == expected:
print('[%s] Expected [%s]' % (self.port, expected))
return
if not line:
time.sleep(1)
raise Exception('failed to find expected string[%s]' % expected)
def _read(self, size=512):
logging.info('%s: reading', self.port)
if self._is_net:
return self.handle.recv(size)
else:
return self.handle.read(size)
def _write(self, data):
logging.info('%s: writing', self.port)
if self._is_net:
self.handle.sendall(data)
else:
self.handle.write(data)
def _readline(self):
"""Read exactly one line from the device
Returns:
None on no data
"""
logging.info('%s: reading line', self.port)
if len(self.lines) > 1:
return self.lines.pop(0)
tail = ''
if len(self.lines):
tail = self.lines.pop()
try:
tail += self._read()
except socket.error:
logging.exception('%s: No new data', self.port)
time.sleep(0.1)
self.lines += linesepx.split(tail)
if len(self.lines) > 1:
return self.lines.pop(0)
def _sendline(self, line):
"""Send exactly one line to the device
Args:
line str: data send to device
"""
logging.info('%s: sending line', self.port)
# clear buffer
self.lines = []
try:
self._read()
except socket.error:
logging.debug('%s: Nothing cleared', self.port)
print('sending [%s]' % line)
self._write(line + '\r\n')
# wait for write to complete
time.sleep(0.1)
def __sendCommand(self, cmd):
"""send specific command to reference unit over serial port
@@ -99,6 +187,7 @@ class ARM(IThci):
Value: successfully retrieve the desired value from reference unit
Error: some errors occur, indicates by the followed specific error number
"""
logging.info('%s: sendCommand[%s]', self.port, cmd)
if self.logThreadStatus == self.logStatus['running']:
self.logThreadStatus = self.logStatus['pauseReq']
while self.logThreadStatus != self.logStatus['paused'] and self.logThreadStatus != self.logStatus['stop']:
@@ -110,28 +199,35 @@ class ARM(IThci):
while retryTimes:
retryTimes -= 1
try:
self.serial.sendline(cmd)
self.serial.expect(cmd + self.serial.linesep)
self._sendline(cmd)
self._expect(cmd)
except Exception as e:
print 'Failed to send command: %s' % str(e)
logging.exception('%s: failed to send command[%s]: %s', self.port, cmd, str(e))
if not retryTimes:
raise
else:
break
line = None
response = []
while True:
line = self.serial.readline().strip('\0\r\n\t')
max_lines = 50
while max_lines:
max_lines -= 1
line = self._readline()
logging.info('%s: the read line is[%s]', self.port, line)
if line:
response.append(line)
if line == 'Done':
break
if self.logThreadStatus == self.logStatus['paused']:
self.logThreadStatus = self.logStatus['running']
else:
time.sleep(0.1)
if line != 'Done':
raise Exception('%s: failed to find end of response' % self.port)
logging.info('%s: send command[%s] done!', self.port, cmd)
return response
except Exception, e:
ModuleHelper.WriteIntoDebugLogger("sendCommand() Error: " + str(e))
raise
def __getIp6Address(self, addressType):
"""get specific type of IPv6 address configured on thread device
@@ -474,7 +570,7 @@ class ARM(IThci):
continue
try:
line = self.serial.readline()
line = self._readline()
if line:
print line
logs.put(line)
@@ -559,21 +655,34 @@ class ARM(IThci):
"""close current serial port connection"""
print '%s call closeConnection' % self.port
try:
self.serial.close()
if self.handle:
self.handle.close()
self.handle = None
except Exception, e:
ModuleHelper.WriteIntoDebugLogger("closeConnection() Error: " + str(e))
def _connect(self):
print('My port is %s' % self.port)
if self.port.startswith('COM'):
self.handle = serial.Serial(self.port, 115200, timeout=0, xonxoff=True)
self._is_net = False
elif ':' in self.port:
host, port = self.port.split(':')
self.handle = socket.create_connection((host, port))
self.handle.setblocking(0)
self._is_net = True
else:
raise Exception('Unknown port schema')
def intialize(self):
"""initialize the serial port with baudrate, timeout parameters"""
print '%s call intialize' % self.port
try:
# init serial port
serialDevice = serial.Serial(self.port, 115200, timeout=1)
self.serial = SerialSpawn(serialDevice)
self._connect()
time.sleep(3)
if self.serial != None:
self.deviceConnected = True
self.deviceConnected = True
except Exception, e:
ModuleHelper.WriteIntoDebugLogger("intialize() Error: " + str(e))
self.deviceConnected = False
@@ -994,11 +1103,14 @@ class ARM(IThci):
"""power down the Thread device"""
print '%s call powerDown' % self.port
self.isPowerDown = True
self.serial.sendline('reset')
self.reset()
def powerUp(self):
"""power up the Thread device"""
print '%s call powerUp' % self.port
if not self.handle:
self._connect()
self.isPowerDown = False
if not self.__isOpenThreadRunning():
@@ -1041,8 +1153,8 @@ class ARM(IThci):
try:
cmd = 'ping %s %s' % (destination, str(length))
print cmd
self.serial.sendline(cmd)
self.serial.expect(cmd + self.serial.linesep)
self._sendline(cmd)
self._expect(cmd)
# wait echo reply
time.sleep(1)
except Exception, e:
@@ -1061,8 +1173,8 @@ class ARM(IThci):
try:
cmd = 'ping %s %s' % (destination, str(length))
print cmd
self.serial.sendline(cmd)
self.serial.expect(cmd + self.serial.linesep)
self._sendline(cmd)
self._expect(cmd)
# wait echo reply
time.sleep(1)
except Exception, e:
@@ -1113,8 +1225,8 @@ class ARM(IThci):
"""factory reset"""
print '%s call reset' % self.port
try:
self.serial.sendline('reset')
time.sleep(3)
self._sendline('reset')
self._read()
except Exception, e:
ModuleHelper.WriteIntoDebugLogger("reset() Error: " + str(e))