Skip to content

Commit 9a0a02b

Browse files
committed
Make Device constructor more generic
The previous version of Device.__init__ took three positional arguments: class name ('tacho-motor'), device name pattern ('motor*' or just '*'), and port name ('outA'). The new version takes two positional arguments (class name and device name) and an arbitrary set of keyword arguments. The keyword arguments are used for matching against device attributes. A match is considered a match when the provided value is a substring of attribute value. If a list is provided as keyword argument, then a match against any single entry of the list is enough. Compare the previous call: d = Device('tacho-motor', 'outA', 'motor*') with the new calls # Get a motor on output port A: d = Device('tacho-motor', 'motor*', port_name='outA') # Get large motor on output port A: m = Device('tacho-motor', 'motor*', port_name='outA', driver_name='lego-ev3-l-motor') # Get an ultrasonic sensor (don't care if EV3 one or NXT one): m = Device('lego-sensor', driver_name=['lego-ev3-us', 'lego-nxt-us']) This would allow for easy implementation of such classes as LargeMotor or MediumMotor. This also makes Device constructor interface compatible with boostc version of python bindings.
1 parent c67d1c4 commit 9a0a02b

File tree

2 files changed

+68
-49
lines changed

2 files changed

+68
-49
lines changed

ev3dev/ev3dev.py

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,48 @@ class Device(object):
3939

4040
DEVICE_ROOT_PATH = '/sys/class'
4141

42-
def __init__(self, class_name, port='auto', name='*' ):
42+
def __init__(self, class_name, name='*', **kwargs ):
4343
"""Spin through the Linux sysfs class for the device type and find
44-
the first unconnected device"""
44+
a device that matches the provided name and attributes (if any).
4545
46-
self._classpath = os.path.abspath( Device.DEVICE_ROOT_PATH + '/' + class_name )
46+
Parameters:
47+
class_name: class name of the device, a subdirectory of /sys/class.
48+
For example, 'tacho-motor'.
49+
name: pattern that device name should match.
50+
For example, 'sensor*' or 'motor*'. Default value: '*'.
51+
keyword arguments: used for matching the corresponding device
52+
attributes. For example, port_name='outA', or
53+
driver_name=['lego-ev3-us', 'lego-nxt-us']. When argument value
54+
is a list, then a match against any entry of the list is
55+
enough.
56+
57+
Example:
58+
d = ev3dev.Device('tacho-motor', port_name='outA')
59+
s = ev3dev.Device('lego-sensor', driver_name=['lego-ev3-us', 'lego-nxt-us'])
60+
61+
When connected succesfully, the `connected` attribute is set to True.
62+
"""
63+
64+
classpath = os.path.abspath( Device.DEVICE_ROOT_PATH + '/' + class_name )
4765
self.filehandle_cache = {}
66+
self.connected = False
4867

49-
for file in os.listdir( self._classpath ):
50-
if 'auto' == port:
51-
if fnmatch.fnmatch(file, name):
52-
print('Got a name match ' + file + ' <-> ' + name)
53-
self._path = os.path.abspath( self._classpath + '/' + file )
54-
break
55-
else:
56-
port_name_file = os.path.abspath( self._classpath + '/' + file + '/port_name')
57-
f = open( port_name_file, 'r' )
58-
port_name = f.read().strip()
59-
f.close()
60-
61-
if fnmatch.fnmatch(port_name, port):
62-
print('Got a port match ' + port_name + ' <-> ' + port)
63-
self._path = os.path.abspath( self._classpath + '/' + file )
64-
break
68+
for file in os.listdir( classpath ):
69+
if fnmatch.fnmatch(file, name):
70+
self._path = os.path.abspath( classpath + '/' + file )
71+
72+
# See if requested attributes match:
73+
if all([self.__matches(k, kwargs[k]) for k in kwargs]):
74+
self.connected = True
75+
return
76+
77+
def __matches(self, attribute, pattern):
78+
"""Test if attribute value matches pattern (that is, if pattern is a
79+
substring of attribute value). If pattern is a list, then a match with
80+
any one entry is enough.
81+
"""
82+
value = self._get_attribute(attribute)
83+
return any([value.find(pat) >= 0 for pat in list(pattern)])
6584

6685
def __exit__(self, exc_type, exc_value, traceback):
6786
print("Well, this is embarassing....")
@@ -158,8 +177,8 @@ class Motor(Device):
158177
SYSTEM_CLASS_NAME = 'tacho-motor'
159178
SYSTEM_DEVICE_NAME_CONVENTION = 'motor*'
160179

161-
def __init__(self, port='auto', name='*' ):
162-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
180+
def __init__(self, port='', name='*', **kwargs ):
181+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
163182

164183
#~autogen
165184
#~autogen python_generic-get-set classes.motor>currentClass
@@ -632,8 +651,8 @@ class DcMotor(Device):
632651
SYSTEM_CLASS_NAME = 'dc-motor'
633652
SYSTEM_DEVICE_NAME_CONVENTION = 'motor*'
634653

635-
def __init__(self, port='auto', name='*' ):
636-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
654+
def __init__(self, port='', name='*', **kwargs ):
655+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
637656

638657
#~autogen
639658
#~autogen python_generic-get-set classes.dcMotor>currentClass
@@ -861,8 +880,8 @@ class ServoMotor(Device):
861880
SYSTEM_CLASS_NAME = 'servo-motor'
862881
SYSTEM_DEVICE_NAME_CONVENTION = 'motor*'
863882

864-
def __init__(self, port='auto', name='*' ):
865-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
883+
def __init__(self, port='', name='*', **kwargs ):
884+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
866885

867886
#~autogen
868887
#~autogen python_generic-get-set classes.servoMotor>currentClass
@@ -1064,8 +1083,8 @@ class Sensor(Device):
10641083
SYSTEM_CLASS_NAME = 'lego-sensor'
10651084
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
10661085

1067-
def __init__(self, port='auto', name='*' ):
1068-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1086+
def __init__(self, port='', name='*', **kwargs ):
1087+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
10691088

10701089
#~autogen
10711090
#~autogen python_generic-get-set classes.sensor>currentClass
@@ -1188,8 +1207,8 @@ class I2cSensor(Device):
11881207
SYSTEM_CLASS_NAME = 'lego-sensor'
11891208
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
11901209

1191-
def __init__(self, port='auto', name='*' ):
1192-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1210+
def __init__(self, port='', name='*', **kwargs ):
1211+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
11931212

11941213
#~autogen
11951214
#~autogen python_generic-get-set classes.i2cSensor>currentClass
@@ -1234,8 +1253,8 @@ class ColorSensor(Device):
12341253
SYSTEM_CLASS_NAME = 'lego-sensor'
12351254
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
12361255

1237-
def __init__(self, port='auto', name='*' ):
1238-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1256+
def __init__(self, port='', name='*', **kwargs ):
1257+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
12391258

12401259
#~autogen
12411260
#~autogen python_generic-property-value classes.colorSensor>currentClass
@@ -1262,8 +1281,8 @@ class UltrasonicSensor(Device):
12621281
SYSTEM_CLASS_NAME = 'lego-sensor'
12631282
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
12641283

1265-
def __init__(self, port='auto', name='*' ):
1266-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1284+
def __init__(self, port='', name='*', **kwargs ):
1285+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
12671286

12681287
#~autogen
12691288
#~autogen python_generic-property-value classes.ultrasonicSensor>currentClass
@@ -1290,8 +1309,8 @@ class GyroSensor(Device):
12901309
SYSTEM_CLASS_NAME = 'lego-sensor'
12911310
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
12921311

1293-
def __init__(self, port='auto', name='*' ):
1294-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1312+
def __init__(self, port='', name='*', **kwargs ):
1313+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
12951314

12961315
#~autogen
12971316
#~autogen python_generic-property-value classes.gyroSensor>currentClass
@@ -1318,8 +1337,8 @@ class InfraredSensor(Device):
13181337
SYSTEM_CLASS_NAME = 'lego-sensor'
13191338
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
13201339

1321-
def __init__(self, port='auto', name='*' ):
1322-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1340+
def __init__(self, port='', name='*', **kwargs ):
1341+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
13231342

13241343
#~autogen
13251344
#~autogen python_generic-property-value classes.infraredSensor>currentClass
@@ -1348,8 +1367,8 @@ class SoundSensor(Device):
13481367
SYSTEM_CLASS_NAME = 'lego-nxt-sound'
13491368
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
13501369

1351-
def __init__(self, port='auto', name='*' ):
1352-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1370+
def __init__(self, port='', name='*', **kwargs ):
1371+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
13531372

13541373
#~autogen
13551374
#~autogen python_generic-property-value classes.soundSensor>currentClass
@@ -1373,8 +1392,8 @@ class LightSensor(Device):
13731392
SYSTEM_CLASS_NAME = 'lego-nxt-light'
13741393
SYSTEM_DEVICE_NAME_CONVENTION = 'sensor*'
13751394

1376-
def __init__(self, port='auto', name='*' ):
1377-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1395+
def __init__(self, port='', name='*', **kwargs ):
1396+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
13781397

13791398
#~autogen
13801399
#~autogen python_generic-property-value classes.lightSensor>currentClass
@@ -1400,8 +1419,8 @@ class Led(Device):
14001419
SYSTEM_CLASS_NAME = 'leds'
14011420
SYSTEM_DEVICE_NAME_CONVENTION = ''
14021421

1403-
def __init__(self, port='auto', name='*' ):
1404-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1422+
def __init__(self, port='', name='*', **kwargs ):
1423+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
14051424

14061425
#~autogen
14071426
#~autogen python_generic-get-set classes.led>currentClass
@@ -1505,8 +1524,8 @@ class PowerSupply(Device):
15051524
SYSTEM_CLASS_NAME = 'power_supply'
15061525
SYSTEM_DEVICE_NAME_CONVENTION = ''
15071526

1508-
def __init__(self, port='auto', name='*' ):
1509-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1527+
def __init__(self, port='', name='*', **kwargs ):
1528+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
15101529

15111530
#~autogen
15121531
#~autogen python_generic-get-set classes.powerSupply>currentClass
@@ -1600,8 +1619,8 @@ class LegoPort(Device):
16001619
SYSTEM_CLASS_NAME = 'lego_port'
16011620
SYSTEM_DEVICE_NAME_CONVENTION = ''
16021621

1603-
def __init__(self, port='auto', name='*' ):
1604-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
1622+
def __init__(self, port='', name='*', **kwargs ):
1623+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )
16051624

16061625
#~autogen
16071626
#~autogen python_generic-get-set classes.legoPort>currentClass

templates/python_generic-class.liquid

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ class {{ class_name }}(Device):
99
SYSTEM_CLASS_NAME = '{{ currentClass.systemClassName }}'
1010
SYSTEM_DEVICE_NAME_CONVENTION = '{{ device_name_convention }}'
1111

12-
def __init__(self, port='auto', name='*' ):
13-
Device.__init__( self, self.SYSTEM_CLASS_NAME, port, name )
12+
def __init__(self, port='', name='*', **kwargs ):
13+
Device.__init__( self, self.SYSTEM_CLASS_NAME, name, port_name=port, **kwargs )

0 commit comments

Comments
 (0)