- added support for TCP connection through Ev3Server

git-svn-id: http://moon:8086/svn/software/trunk/projects/opencv@340 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2016-10-23 16:52:12 +00:00
parent 5ab9ce1447
commit ab063f1d74
2 changed files with 180 additions and 140 deletions
+179 -139
View File
@@ -2,47 +2,50 @@
Prerequisites: Prerequisites:
Make sure your sdp includes an SP (serial port): Make sure your sdp includes an SP (serial port):
% sdptool browse local % sdptool browse local
... ...
Service Name: Serial Port Service Name: Serial Port
Service Description: COM Port Service Description: COM Port
If not: If not:
% sdptool add SP % sdptool add SP
Then: Then:
% hcitool scan % hcitool scan
... ...
XX:XX:XX:XX:XX:XX EV3 XX:XX:XX:XX:XX:XX EV3
% sudo rfcomm bind /dev/rfcomm0 XX:XX:XX:XX:XX:XX % sudo rfcomm bind /dev/rfcomm0 XX:XX:XX:XX:XX:XX
Now /dev/rfcomm0 can be opened and closed like a normal serial port. Now /dev/rfcomm0 can be opened and closed like a normal serial port.
The opposite action is: The opposite action is:
% sudo rfcomm release /dev/rfcomm0 % sudo rfcomm release /dev/rfcomm0
EXAMPLE USAGE: EXAMPLE USAGE:
from ev3 import * from ev3 import *
with ev3.EV3() as brick: with ev3.EV3() as brick:
# Create DirectCommand objects and add commands to them. # Create DirectCommand objects and add commands to them.
cmd = direct_command.DirectCommand() cmd = direct_command.DirectCommand()
cmd.add_ui_draw_update() cmd.add_ui_draw_update()
cmd.send(brick) cmd.send(brick)
# Call single DirectCommand functions without creating DirectCommand # Call single DirectCommand functions without creating DirectCommand
# objects each time. # objects each time.
brick.output_stop(direct_command.OutputPort.PORT_C, brick.output_stop(direct_command.OutputPort.PORT_C,
direct_command.StopType.BRAKE) direct_command.StopType.BRAKE)
# Call single system_command functions. # Call single system_command functions.
brick.write_mailbox('foo', (0,1,2,3,4,5,6,7,8,9,0)) brick.write_mailbox('foo', (0,1,2,3,4,5,6,7,8,9,0))
""" """
import sys
import serial import serial
import socket
import array
import message import message
import system_command import system_command
@@ -50,139 +53,176 @@ import direct_command
class KnownPaths(object): class KnownPaths(object):
"""These are the default directories on the brick. All paths are """These are the default directories on the brick. All paths are
relative to 'lms2012/sys' by default. relative to 'lms2012/sys' by default.
""" """
DEFAULT_PATH = "." # lms2012/sys DEFAULT_PATH = "." # lms2012/sys
PROJECTS_PATH = "../prjs" # lms2012/prjs PROJECTS_PATH = "../prjs" # lms2012/prjs
APPS_PATH = "../apps" # lms2012/apps APPS_PATH = "../apps" # lms2012/apps
TOOLS_PATH = "../tools" # lms2012/tools TOOLS_PATH = "../tools" # lms2012/tools
SOURCE_PATH = "../source" # lms2012/source SOURCE_PATH = "../source" # lms2012/source
class EV3Error(Exception): class EV3Error(Exception):
"""Subclass for reporting errrors.""" """Subclass for reporting errrors."""
pass pass
class Port(object):
RFCOMM_BAUDRATE = 115200
def __init__(self, port_str):
self._port_str = port_str
self.sock = None
self.mode = 'Unknown'
if (self.sock is None):
try:
addr = self._port_str.split(':')
_ = socket.inet_aton(addr[0])
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.sock.connect((addr[0], int(addr[1])))
self.mode = "TCP"
except Exception as e:
self.sock = serial.Serial(port=self._port_str,
baudrate=self.RFCOMM_BAUDRATE,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=None,
xonxoff=False,
rtscts=False,
writeTimeout=None,
dsrdtr=False,
interCharTimeout=None)
self.mode = 'Serial'
def read(self, size, timeout=1.0):
if self.mode == 'Serial':
return self.sock.read(size)
elif self.mode == 'TCP':
return self.sock.recv(size)
def write(self, data):
if self.mode == 'Serial':
return self.sock.write(data)
elif self.mode == 'TCP':
byte = array.array('B', data).tostring()
return self.sock.send(byte)
def __del__(self):
if (self.sock is not None):
self.sock.close()
self.sock = None
class EV3(object): class EV3(object):
"""""" """"""
DEFAULT_RFCOMM_PORT = '/dev/rfcomm0' DEFAULT_RFCOMM_PORT = '/dev/rfcomm0'
RFCOMM_BAUDRATE = 115200
def __init__(self, port_str=DEFAULT_RFCOMM_PORT):
"""Creates a new object but doesn't open the port."""
self._port_str = port_str
self._port = None
def __init__(self, port_str=DEFAULT_RFCOMM_PORT): def open(self):
"""Creates a new object but doesn't open the port.""" """Opens the object's serial port."""
self._port_str = port_str if (self._port is None):
self._port = None self._port = Port(self._port_str)
def close(self):
"""Closes the object's serial port."""
if (self._port is not None):
del self._port
self._port = None
def open(self): def send_message(self, msg, message_counter=0x1234):
"""Opens the object's serial port.""" """Allows for sending raw messages to the EV3. The msg parameter should
if (self._port is None): be an array of byte values. The msg parameter should not include the
self._port = serial.Serial(port=self._port_str, length/message_counter header. Raises an EV3Error if the specified
baudrate=self.RFCOMM_BAUDRATE, message is a type that expects a reply.
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=None,
xonxoff=False,
rtscts=False,
writeTimeout=None,
dsrdtr=False,
interCharTimeout=None)
def close(self): """
"""Closes the object's serial port.""" try:
if (self._port is not None): message.send_message_no_reply(self._port, msg, message_counter)
self._port.close() except message.MessageError as ex:
self._port = None raise EV3Error(ex.message)
def send_message(self, msg, message_counter=0x1234): def send_message_for_reply(self, msg, message_counter=0x1234):
"""Allows for sending raw messages to the EV3. The msg parameter should """Allows for sending raw messages to the EV3. The msg parameter should
be an array of byte values. The msg parameter should not include the be an array of byte values. The msg parameter should not include the
length/message_counter header. Raises an EV3Error if the specified length/message_counter header. Raises an EV3Error if the specified
message is a type that expects a reply. message is a type that doesn't expect a reply.
""" """
try: try:
message.send_message_no_reply(self._port, msg, message_counter) return message.send_message_for_reply(self._port,
except message.MessageError as ex: msg,
raise EV3Error(ex.message) message_counter)
except message.MessageError as ex:
raise EV3Error(ex.message)
def send_message_for_reply(self, msg, message_counter=0x1234): def __dir__(self):
"""Allows for sending raw messages to the EV3. The msg parameter should """Add in functions from the system_command module as well as methods
be an array of byte values. The msg parameter should not include the from the DirectCommand class because they can be called directly on an
length/message_counter header. Raises an EV3Error if the specified EV3 object.
message is a type that doesn't expect a reply.
""" """
try: result = dir(type(self))
return message.send_message_for_reply(self._port, result += list(self.__dict__)
msg, result += [s for s in list(system_command.__dict__)
message_counter) if not s.startswith('_')]
except message.MessageError as ex: result += [s[4:] for s in list(direct_command.DirectCommand.__dict__)
raise EV3Error(ex.message) if s.startswith('add_')]
return sorted(set(result))
def __dir__(self): def __getattr__(self, name):
"""Add in functions from the system_command module as well as methods """A little bit of magic is used in order to make it easier to work with
from the DirectCommand class because they can be called directly on an EV3 objects.
EV3 object.
""" """
result = dir(type(self)) if (hasattr(system_command, name)):
result += list(self.__dict__) # This allows functions from the system_command module to be called
result += [s for s in list(system_command.__dict__) # from an EV3 object i.e. ev3.list_files(KnownPaths.PROJECTS_PATH).
if not s.startswith('_')] def execute_sc(*args):
result += [s[4:] for s in list(direct_command.DirectCommand.__dict__) """This is just a wrapper around an individual function from the
if s.startswith('add_')] system_command module. See the system_command module for more
return sorted(set(result)) information.
"""
getattr(system_command, name)(self, *args)
return execute_sc
# This allows single functions from the DirectCommand class to be called
# from an EV3 object i.e. ev3.ui_draw_update().
dc_name = ('add_' + name)
if (hasattr(direct_command.DirectCommand, dc_name)):
def execute_dc(*args):
"""This is just a wrapper around an individual DirectCommand
method. See the DirectCommand class for more information.
"""
dc = direct_command.DirectCommand()
getattr(dc, dc_name)(*args)
return dc.send(self)
return execute_dc
return Object.__getattr__(self, name)
def __getattr__(self, name): def __enter__(self):
"""A little bit of magic is used in order to make it easier to work with self.open()
EV3 objects. return self
"""
if (hasattr(system_command, name)):
# This allows functions from the system_command module to be called
# from an EV3 object i.e. ev3.list_files(KnownPaths.PROJECTS_PATH).
def execute_sc(*args):
"""This is just a wrapper around an individual function from the
system_command module. See the system_command module for more
information.
"""
getattr(system_command, name)(self, *args)
return execute_sc
# This allows single functions from the DirectCommand class to be called
# from an EV3 object i.e. ev3.ui_draw_update().
dc_name = ('add_' + name)
if (hasattr(direct_command.DirectCommand, dc_name)):
def execute_dc(*args):
"""This is just a wrapper around an individual DirectCommand
method. See the DirectCommand class for more information.
"""
dc = direct_command.DirectCommand()
getattr(dc, dc_name)(*args)
return dc.send(self)
return execute_dc
return Object.__getattr__(self, name)
def __enter__(self): def __exit__(self, type, value, traceback):
self.open() self.close()
return self
def __exit__(self, type, value, traceback):
self.close()
+1 -1
View File
@@ -159,7 +159,7 @@ def append_str(byte_list, str_value):
def _read_bytes(port, num_bytes): def _read_bytes(port, num_bytes):
return [ord(i) for i in port.read(num_bytes)] return port.read(num_bytes)
def _write_bytes(port, byte_seq): def _write_bytes(port, byte_seq):