mirror of
https://github.com/espressif/openthread.git
synced 2026-10-03 22:37:36 +00:00
[thci] add SSH support for OpenThread wpanctl THCI (#3086)
This commit is contained in:
@@ -39,6 +39,7 @@ import logging
|
|||||||
from Queue import Queue
|
from Queue import Queue
|
||||||
|
|
||||||
import serial
|
import serial
|
||||||
|
import paramiko
|
||||||
from IThci import IThci
|
from IThci import IThci
|
||||||
from GRLLibs.UtilityModules.Test import Thread_Device_Role, Device_Data_Requirement, MacType
|
from GRLLibs.UtilityModules.Test import Thread_Device_Role, Device_Data_Requirement, MacType
|
||||||
from GRLLibs.UtilityModules.enums import PlatformDiagnosticPacket_Direction, PlatformDiagnosticPacket_Type
|
from GRLLibs.UtilityModules.enums import PlatformDiagnosticPacket_Direction, PlatformDiagnosticPacket_Type
|
||||||
@@ -69,13 +70,19 @@ class OpenThread_WpanCtl(IThci):
|
|||||||
try:
|
try:
|
||||||
self.UIStatusMsg = ''
|
self.UIStatusMsg = ''
|
||||||
self.mac = kwargs.get('EUI')
|
self.mac = kwargs.get('EUI')
|
||||||
self.port = kwargs.get('SerialPort')
|
|
||||||
self.handle = None
|
self.handle = None
|
||||||
self.AutoDUTEnable = False
|
self.AutoDUTEnable = False
|
||||||
self._is_net = False # whether device is through ser2net
|
self._is_net = False # whether device is through ser2net
|
||||||
self.logStatus = {'stop':'stop', 'running':'running', 'pauseReq':'pauseReq', 'paused':'paused'}
|
self.logStatus = {'stop':'stop', 'running':'running', 'pauseReq':'pauseReq', 'paused':'paused'}
|
||||||
self.joinStatus = {'notstart':'idle', 'ongoing':'discover', 'succeed':'joined', 'failed':'failed'}
|
self.joinStatus = {'notstart':'idle', 'ongoing':'discover', 'succeed':'joined', 'failed':'failed'}
|
||||||
self.logThreadStatus = self.logStatus['stop']
|
self.logThreadStatus = self.logStatus['stop']
|
||||||
|
self.connectType = (kwargs.get('Param5')).strip().lower() if kwargs.get('Param5') is not None else 'usb'
|
||||||
|
if self.connectType == 'ip':
|
||||||
|
self.dutIpv4 = kwargs.get('TelnetIP')
|
||||||
|
self.dutPort = kwargs.get('TelnetPort')
|
||||||
|
self.port = self.dutIpv4 + ':' + self.dutPort
|
||||||
|
else:
|
||||||
|
self.port = kwargs.get('SerialPort')
|
||||||
self.intialize()
|
self.intialize()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
ModuleHelper.WriteIntoDebugLogger('initialize() Error: ' + str(e))
|
ModuleHelper.WriteIntoDebugLogger('initialize() Error: ' + str(e))
|
||||||
@@ -119,9 +126,6 @@ class OpenThread_WpanCtl(IThci):
|
|||||||
if self._is_net:
|
if self._is_net:
|
||||||
return self.handle.recv(size)
|
return self.handle.recv(size)
|
||||||
else:
|
else:
|
||||||
#read_data = self.handle.read(size)
|
|
||||||
#print "read_data : %s" % read_data
|
|
||||||
#return read_data
|
|
||||||
return self.handle.read(size)
|
return self.handle.read(size)
|
||||||
|
|
||||||
def _write(self, data):
|
def _write(self, data):
|
||||||
@@ -192,14 +196,20 @@ class OpenThread_WpanCtl(IThci):
|
|||||||
while self.logThreadStatus != self.logStatus['paused'] and self.logThreadStatus != self.logStatus['stop']:
|
while self.logThreadStatus != self.logStatus['paused'] and self.logThreadStatus != self.logStatus['stop']:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
ssh_stdin = None
|
||||||
|
ssh_stdout = None
|
||||||
|
ssh_stderr = None
|
||||||
try:
|
try:
|
||||||
# command retransmit times
|
# command retransmit times
|
||||||
retry_times = 3
|
retry_times = 3
|
||||||
while retry_times > 0:
|
while retry_times > 0:
|
||||||
retry_times -= 1
|
retry_times -= 1
|
||||||
try:
|
try:
|
||||||
self._sendline(cmd)
|
if self._is_net:
|
||||||
self._expect(cmd)
|
ssh_stdin, ssh_stdout, ssh_stderr = self.handle.exec_command(cmd)
|
||||||
|
else:
|
||||||
|
self._sendline(cmd)
|
||||||
|
self._expect(cmd)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception('%s: failed to send command[%s]: %s', self.port, cmd, str(e))
|
logging.exception('%s: failed to send command[%s]: %s', self.port, cmd, str(e))
|
||||||
if retry_times == 0:
|
if retry_times == 0:
|
||||||
@@ -210,28 +220,53 @@ class OpenThread_WpanCtl(IThci):
|
|||||||
line = None
|
line = None
|
||||||
response = []
|
response = []
|
||||||
retry_times = 10
|
retry_times = 10
|
||||||
while retry_times > 0:
|
stdout_lines = []
|
||||||
line = self._readline()
|
stderr_lines = []
|
||||||
print "read line: %s" % line
|
if self._is_net:
|
||||||
logging.info('%s: the read line is[%s]', self.port, line)
|
stdout_lines = ssh_stdout.readlines()
|
||||||
if line:
|
stderr_lines = ssh_stderr.readlines()
|
||||||
response.append(line)
|
if stderr_lines:
|
||||||
print "response: %s" % response
|
for stderr_line in stderr_lines:
|
||||||
if re.match(WPAN_CARRIER_PROMPT, line):
|
if re.search(r'Not\s+Found|failed\s+with\s+error', stderr_line.strip(), re.M | re.I):
|
||||||
break
|
print "Command failed:" + stderr_line
|
||||||
elif re.search(r'Not\s+Found|failed\s+with\s+error', line, re.M|re.I):
|
return 'Fail'
|
||||||
print "Command failed"
|
print "Got line: " + stderr_line
|
||||||
return 'Fail'
|
logging.info('%s: the read line is[%s]', self.port, stderr_line)
|
||||||
|
response.append(str(stderr_line.strip()))
|
||||||
|
elif stdout_lines:
|
||||||
|
for stdout_line in stdout_lines:
|
||||||
|
logging.info('%s: the read line is[%s]', self.port, stdout_line)
|
||||||
|
if re.search(r'Not\s+Found|failed\s+with\s+error', stdout_line.strip(), re.M | re.I):
|
||||||
|
print "Command failed"
|
||||||
|
return 'Fail'
|
||||||
|
print "Got line: " + stdout_line
|
||||||
|
logging.info('%s: send command[%s] done!', self.port, cmd)
|
||||||
|
response.append(str(stdout_line.strip()))
|
||||||
|
response.append(WPAN_CARRIER_PROMPT)
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
while retry_times > 0:
|
||||||
|
line = self._readline()
|
||||||
|
print "read line: %s" % line
|
||||||
|
logging.info('%s: the read line is[%s]', self.port, line)
|
||||||
|
if line:
|
||||||
|
response.append(line)
|
||||||
|
print "response: %s" % response
|
||||||
|
if re.match(WPAN_CARRIER_PROMPT, line):
|
||||||
|
break
|
||||||
|
elif re.search(r'Not\s+Found|failed\s+with\s+error', line, re.M | re.I):
|
||||||
|
print "Command failed"
|
||||||
|
return 'Fail'
|
||||||
|
else:
|
||||||
|
retry_times -= 1
|
||||||
|
time.sleep(0.1)
|
||||||
else:
|
else:
|
||||||
retry_times -= 1
|
retry_times -= 1
|
||||||
time.sleep(0.1)
|
time.sleep(1)
|
||||||
else:
|
if not re.match(WPAN_CARRIER_PROMPT, line):
|
||||||
retry_times -= 1
|
raise Exception('%s: failed to find end of response' % self.port)
|
||||||
time.sleep(1)
|
logging.info('%s: send command[%s] done!', self.port, cmd)
|
||||||
if not re.match(WPAN_CARRIER_PROMPT, line):
|
return response
|
||||||
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:
|
except Exception, e:
|
||||||
ModuleHelper.WriteIntoDebugLogger('sendCommand() Error: ' + str(e))
|
ModuleHelper.WriteIntoDebugLogger('sendCommand() Error: ' + str(e))
|
||||||
raise
|
raise
|
||||||
@@ -698,8 +733,8 @@ class OpenThread_WpanCtl(IThci):
|
|||||||
return self.__sendCommand(WPANCTL_CMD + 'getprop -v Commissioner:SessionId')[0]
|
return self.__sendCommand(WPANCTL_CMD + 'getprop -v Commissioner:SessionId')[0]
|
||||||
|
|
||||||
def _connect(self):
|
def _connect(self):
|
||||||
print 'My port is %s' % self.port
|
if self.connectType == 'usb':
|
||||||
if self.port.startswith('COM'):
|
print 'My port is %s' % self.port
|
||||||
self.handle = serial.Serial(self.port, 115200, timeout=0.1)
|
self.handle = serial.Serial(self.port, 115200, timeout=0.1)
|
||||||
input_data = self.handle.read(self.handle.inWaiting())
|
input_data = self.handle.read(self.handle.inWaiting())
|
||||||
if not input_data:
|
if not input_data:
|
||||||
@@ -717,11 +752,16 @@ class OpenThread_WpanCtl(IThci):
|
|||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
self._is_net = False
|
self._is_net = False
|
||||||
|
|
||||||
elif ':' in self.port:
|
elif self.connectType == 'ip':
|
||||||
host, port = self.port.split(':')
|
print "My IP: %s Port: %s" % (self.dutIpv4, self.dutPort)
|
||||||
self.handle = socket.create_connection((host, port))
|
try:
|
||||||
self.handle.setblocking(0)
|
self.handle = paramiko.SSHClient()
|
||||||
self._is_net = True
|
self.handle.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
self.handle.connect(self.dutIpv4, port=self.dutPort, username=WPAN_CARRIER_USER, password=WPAN_CARRIER_PASSWD)
|
||||||
|
self.handle.exec_command("stty cols 128")
|
||||||
|
self._is_net = True
|
||||||
|
except Exception as e:
|
||||||
|
ModuleHelper.WriteIntoDebugLogger('connect to ssh Error: ' + str(e))
|
||||||
else:
|
else:
|
||||||
raise Exception('Unknown port schema')
|
raise Exception('Unknown port schema')
|
||||||
self.UIStatusMsg = self.getVersionNumber()
|
self.UIStatusMsg = self.getVersionNumber()
|
||||||
@@ -1306,11 +1346,15 @@ class OpenThread_WpanCtl(IThci):
|
|||||||
"""factory reset"""
|
"""factory reset"""
|
||||||
print '%s call reset' % self.port
|
print '%s call reset' % self.port
|
||||||
try:
|
try:
|
||||||
self._sendline(WPANCTL_CMD + 'leave')
|
if self._is_net:
|
||||||
|
self.__sendCommand(WPANCTL_CMD + 'leave')
|
||||||
|
else:
|
||||||
|
self._sendline(WPANCTL_CMD + 'leave')
|
||||||
|
|
||||||
self.__sendCommand(WPANCTL_CMD + 'dataset erase')
|
self.__sendCommand(WPANCTL_CMD + 'dataset erase')
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
self._read()
|
if not self._is_net:
|
||||||
|
self._read()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
ModuleHelper.WriteIntoDebugLogger('reset() Error: ' + str(e))
|
ModuleHelper.WriteIntoDebugLogger('reset() Error: ' + str(e))
|
||||||
|
|
||||||
|
|||||||
@@ -57,3 +57,27 @@ Alternatively, platform developers may follow the instructions below to add a ne
|
|||||||
9. Drag the "OpenThread_WpanCtl: Wpantund + NCP" reference device to the **Test Bed** section with the desired number.
|
9. Drag the "OpenThread_WpanCtl: Wpantund + NCP" reference device to the **Test Bed** section with the desired number.
|
||||||
|
|
||||||
10. Select one or more test cases to execute.
|
10. Select one or more test cases to execute.
|
||||||
|
|
||||||
|
|
||||||
|
The above is for the serial connection mode between the DUT and the Host PC. The ssh connection mode is
|
||||||
|
also supported for OpenThread WpanCtl, but it can not be auto-discovered and only can be used via ‘Drag and Add’ way
|
||||||
|
in the ‘Configure Test Bed’ Page of Test Harness. The configuration is as following:
|
||||||
|
|
||||||
|
1. Make Raspberry Pi and Host PC in the same LAN.
|
||||||
|
|
||||||
|
2. Login Raspberry Pi, sudo raspi-config, then -> interfacing options -> enable ssh.
|
||||||
|
|
||||||
|
3. Install python paramiko package to `C:\GRL\Pyton2.7`
|
||||||
|
|
||||||
|
4. Copy "OpenThread_WpanCtl.png" to `C:\GRL\Thread1.1\Web\images`.
|
||||||
|
|
||||||
|
5. Copy "deviceInputFields.xml" to `C:\GRL\Thread1.1\Web\data`.
|
||||||
|
|
||||||
|
6. Copy "OpenThread_WpanCtl.py" to `C:\GRL\Thread1.1\Thread_Harness\THCI`.
|
||||||
|
|
||||||
|
7. Launch the Thread Test Harness Software, modify the default configuration if needed, and select **Start**.
|
||||||
|
|
||||||
|
8. Drag the "OpenThread_WpanCtl: Wpantund + NCP (SSH)" reference device to the **Test Bed** section with the desired number.
|
||||||
|
Then fill in the Raspberry Pi IPv4 address and port and click `connect` icon button to get the NCP version.
|
||||||
|
|
||||||
|
9. Select one or more test cases to execute.
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
hint="eg: 115200">115200
|
hint="eg: 115200">115200
|
||||||
</ITEM>
|
</ITEM>
|
||||||
</DEVICE>
|
</DEVICE>
|
||||||
<DEVICE name="OpenThread_WpanCtl" thumbnail="OpenThread.png" description = "OpenThread_WpanCtl: wpantund + NCP" THCI="OpenThread_WpanCtl">
|
<DEVICE name="OpenThread_WpanCtl" thumbnail="OpenThread_WpanCtl.png" description = "OpenThread_WpanCtl: Wpantund + NCP" THCI="OpenThread_WpanCtl">
|
||||||
<ITEM label="Serial Line"
|
<ITEM label="Serial Line"
|
||||||
type="text"
|
type="text"
|
||||||
forParam="SerialPort"
|
forParam="SerialPort"
|
||||||
@@ -90,4 +90,21 @@
|
|||||||
hint="eg: 115200">115200
|
hint="eg: 115200">115200
|
||||||
</ITEM>
|
</ITEM>
|
||||||
</DEVICE>
|
</DEVICE>
|
||||||
|
<DEVICE name="OpenThread_WpanCtl_SSH" thumbnail="OpenThread_WpanCtl.png" description = "OpenThread_WpanCtl: Wpantund + NCP (SSH)" THCI="OpenThread_WpanCtl">
|
||||||
|
<ITEM label="IP addr"
|
||||||
|
type="text"
|
||||||
|
forParam="TelnetIP"
|
||||||
|
validation="ipv4"
|
||||||
|
hint="eg: 192.168.1.111">192.168.1.100
|
||||||
|
</ITEM>
|
||||||
|
<ITEM label="PORT"
|
||||||
|
type="text"
|
||||||
|
forParam="TelnetPort"
|
||||||
|
validation="port"
|
||||||
|
hint="eg: 4901">22
|
||||||
|
</ITEM>
|
||||||
|
<ITEM type="hidden" label = ""
|
||||||
|
forParam="Param5">ip
|
||||||
|
</ITEM>
|
||||||
|
</DEVICE>
|
||||||
</DEVICE_FIELDS>
|
</DEVICE_FIELDS>
|
||||||
|
|||||||
Reference in New Issue
Block a user