Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 26 additions & 30 deletions ev3dev/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,16 @@ def matches(attribute, pattern):
yield f


class DeviceNotFound(Exception):
pass

# -----------------------------------------------------------------------------
# Define the base class from which all other ev3dev classes are defined.

class Device(object):
"""The ev3dev device base class"""

__slots__ = ['_path', 'connected', '_device_index', 'kwargs']
__slots__ = ['_path', '_device_index', 'kwargs']

DEVICE_ROOT_PATH = '/sys/class'

Expand Down Expand Up @@ -158,7 +161,7 @@ def __init__(self, class_name, name_pattern='*', name_exact=False, **kwargs):
d = ev3dev.Device('tacho-motor', address='outA')
s = ev3dev.Device('lego-sensor', driver_name=['lego-ev3-us', 'lego-nxt-us'])

When connected succesfully, the `connected` attribute is set to True.
If there was no valid connected device, an error is thrown.
"""

classpath = abspath(Device.DEVICE_ROOT_PATH + '/' + class_name)
Expand All @@ -174,23 +177,24 @@ def get_index(file):
if name_exact:
self._path = classpath + '/' + name_pattern
self._device_index = get_index(name_pattern)
self.connected = True
else:
try:
name = next(list_device_names(classpath, name_pattern, **kwargs))
self._path = classpath + '/' + name
self._device_index = get_index(name)
self.connected = True
except StopIteration:
self._path = None
self._device_index = None
self.connected = False
raise DeviceNotFound("%s is not connected." % self) from None

def __str__(self):
if 'address' in self.kwargs:
return "%s(%s)" % (self.__class__.__name__, self.kwargs.get('address'))
else:
return self.__class__.__name__

def __repr__(self):
return self.__str__()

def _attribute_file_open(self, name):
path = os.path.join(self._path, name)
Expand All @@ -209,35 +213,27 @@ def _attribute_file_open(self, name):

def _get_attribute(self, attribute, name):
"""Device attribute getter"""
if self.connected:
if attribute is None:
attribute = self._attribute_file_open( name )
else:
attribute.seek(0)
return attribute, attribute.read().strip().decode()

def _set_attribute(self, attribute, name, value):
"""Device attribute setter"""
try:
if attribute is None:
attribute = self._attribute_file_open( name )
else:
attribute.seek(0)
return attribute, attribute.read().strip().decode()
else:
#log.info("%s: path %s, attribute %s" % (self, self._path, name))
raise Exception("%s is not connected" % self)

def _set_attribute(self, attribute, name, value):
"""Device attribute setter"""
if self.connected:
try:
if attribute is None:
attribute = self._attribute_file_open( name )
else:
attribute.seek(0)

if isinstance(value, str):
value = value.encode()
attribute.write(value)
attribute.flush()
except Exception as ex:
self._raise_friendly_access_error(ex, name)
return attribute
else:
#log.info("%s: path %s, attribute %s" % (self, self._path, name))
raise Exception("%s is not connected" % self)
if isinstance(value, str):
value = value.encode()
attribute.write(value)
attribute.flush()
except Exception as ex:
self._raise_friendly_access_error(ex, name)
return attribute

def _raise_friendly_access_error(self, driver_error, attribute):
if not isinstance(driver_error, OSError):
Expand All @@ -256,7 +252,7 @@ def _raise_friendly_access_error(self, driver_error, attribute):
# We will assume that a file-not-found error is the result of a disconnected device
# rather than a library error. If that isn't the case, at a minimum the underlying
# error info will be printed for debugging.
raise Exception("%s is no longer connected" % self) from driver_error
raise DeviceNotFound("%s is no longer connected" % self) from driver_error
raise driver_error

def get_attr_int(self, attribute, name):
Expand Down
17 changes: 4 additions & 13 deletions tests/api_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,20 @@ def test_device(self):
populate_arena({'medium_motor' : [0, 'outA'], 'infrared_sensor' : [0, 'in1']})

d = ev3.Device('tacho-motor', 'motor*')
self.assertTrue(d.connected)

d = ev3.Device('tacho-motor', 'motor0')
self.assertTrue(d.connected)

d = ev3.Device('tacho-motor', 'motor*', driver_name='lego-ev3-m-motor')
self.assertTrue(d.connected)

d = ev3.Device('tacho-motor', 'motor*', address='outA')
self.assertTrue(d.connected)

d = ev3.Device('tacho-motor', 'motor*', address='outA', driver_name='not-valid')
self.assertTrue(not d.connected)
with self.assertRaises(ev3.DeviceNotFound):
d = ev3.Device('tacho-motor', 'motor*', address='outA', driver_name='not-valid')

d = ev3.Device('lego-sensor', 'sensor*')
self.assertTrue(d.connected)

d = ev3.Device('this-does-not-exist')
self.assertFalse(d.connected)
with self.assertRaises(ev3.DeviceNotFound):
d = ev3.Device('this-does-not-exist')

def test_medium_motor(self):
def dummy(self):
Expand All @@ -53,8 +48,6 @@ def dummy(self):

m = MediumMotor()

self.assertTrue(m.connected);

self.assertEqual(m.device_index, 0)

# Check that reading twice works:
Expand Down Expand Up @@ -86,8 +79,6 @@ def test_infrared_sensor(self):

s = InfraredSensor()

self.assertTrue(s.connected)

self.assertEqual(s.device_index, 0)
self.assertEqual(s.bin_data_format, 's8')
self.assertEqual(s.bin_data('<b'), (16,))
Expand Down
4 changes: 0 additions & 4 deletions utils/move_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
else:
raise Exception("%s is invalid, options are A, B, C, D")

if not motor.connected:
log.error("%s is not connected" % motor)
sys.exit(1)

if args.degrees:
log.info("Motor %s, current position %d, move to position %d, max speed %d" %
(args.motor, motor.position, args.degrees, motor.max_speed))
Expand Down