Skip to content

Commit a36879b

Browse files
authored
Replace autogenerated properties for trigger, delay_on/off with custom ones (#243)
This introduces a workaround for ev3dev/ev3dev#225 and fixes #234. First, when trigger is set to 'timer', the setter blocks until 'delay_on' and 'delay_off' files have been created and got the correct attributes. The maximum wait time is 1 second. Second, since 'delay_on' and 'delay_off' attributes are created and destroyed depending on value of 'trigger', their cache entries may become outdated. This commit makes an attempt to reopen the files in this case.
1 parent 61b5439 commit a36879b

File tree

2 files changed

+87
-8
lines changed

2 files changed

+87
-8
lines changed

ev3dev/core.py

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,8 @@ def triggers(self):
21462146
self._triggers, value = self.get_attr_set(self._triggers, 'trigger')
21472147
return value
21482148

2149+
# ~autogen
2150+
21492151
@property
21502152
def trigger(self):
21512153
"""
@@ -2171,19 +2173,70 @@ def trigger(self):
21712173
def trigger(self, value):
21722174
self._trigger = self.set_attr_string(self._trigger, 'trigger', value)
21732175

2176+
# Workaround for ev3dev/ev3dev#225.
2177+
# When trigger is set to 'timer', we need to wait for 'delay_on' and
2178+
# 'delay_off' attributes to appear with correct permissions.
2179+
if value == 'timer':
2180+
for attr in ('delay_on', 'delay_off'):
2181+
path = self._path + '/' + attr
2182+
2183+
# Make sure the file has been created:
2184+
for _ in range(5):
2185+
if os.path.exists(path):
2186+
break
2187+
time.sleep(0.2)
2188+
else:
2189+
raise Exception('"{}" attribute has not been created'.format(attr))
2190+
2191+
# Make sure the file has correct permissions:
2192+
for _ in range(5):
2193+
mode = stat.S_IMODE(os.stat(path)[stat.ST_MODE])
2194+
if mode & stat.S_IRGRP and mode & stat.S_IWGRP:
2195+
break
2196+
time.sleep(0.2)
2197+
else:
2198+
raise Exception('"{}" attribute has wrong permissions'.format(attr))
2199+
2200+
21742201
@property
21752202
def delay_on(self):
21762203
"""
21772204
The `timer` trigger will periodically change the LED brightness between
21782205
0 and the current brightness setting. The `on` time can
21792206
be specified via `delay_on` attribute in milliseconds.
21802207
"""
2181-
self._delay_on, value = self.get_attr_int(self._delay_on, 'delay_on')
2182-
return value
2208+
2209+
# Workaround for ev3dev/ev3dev#225.
2210+
# 'delay_on' and 'delay_off' attributes are created when trigger is set
2211+
# to 'timer', and destroyed when it is set to anything else.
2212+
# This means the file cache may become outdated, and we may have to
2213+
# reopen the file.
2214+
for retry in (True, False):
2215+
try:
2216+
self._delay_on, value = self.get_attr_int(self._delay_on, 'delay_on')
2217+
return value
2218+
except OSError:
2219+
if retry:
2220+
self._delay_on = None
2221+
else:
2222+
raise
21832223

21842224
@delay_on.setter
21852225
def delay_on(self, value):
2186-
self._delay_on = self.set_attr_int(self._delay_on, 'delay_on', value)
2226+
# Workaround for ev3dev/ev3dev#225.
2227+
# 'delay_on' and 'delay_off' attributes are created when trigger is set
2228+
# to 'timer', and destroyed when it is set to anything else.
2229+
# This means the file cache may become outdated, and we may have to
2230+
# reopen the file.
2231+
for retry in (True, False):
2232+
try:
2233+
self._delay_on = self.set_attr_int(self._delay_on, 'delay_on', value)
2234+
return
2235+
except OSError:
2236+
if retry:
2237+
self._delay_on = None
2238+
else:
2239+
raise
21872240

21882241
@property
21892242
def delay_off(self):
@@ -2192,15 +2245,39 @@ def delay_off(self):
21922245
0 and the current brightness setting. The `off` time can
21932246
be specified via `delay_off` attribute in milliseconds.
21942247
"""
2195-
self._delay_off, value = self.get_attr_int(self._delay_off, 'delay_off')
2196-
return value
2248+
2249+
# Workaround for ev3dev/ev3dev#225.
2250+
# 'delay_on' and 'delay_off' attributes are created when trigger is set
2251+
# to 'timer', and destroyed when it is set to anything else.
2252+
# This means the file cache may become outdated, and we may have to
2253+
# reopen the file.
2254+
for retry in (True, False):
2255+
try:
2256+
self._delay_off, value = self.get_attr_int(self._delay_off, 'delay_off')
2257+
return value
2258+
except OSError:
2259+
if retry:
2260+
self._delay_off = None
2261+
else:
2262+
raise
21972263

21982264
@delay_off.setter
21992265
def delay_off(self, value):
2200-
self._delay_off = self.set_attr_int(self._delay_off, 'delay_off', value)
2201-
2266+
# Workaround for ev3dev/ev3dev#225.
2267+
# 'delay_on' and 'delay_off' attributes are created when trigger is set
2268+
# to 'timer', and destroyed when it is set to anything else.
2269+
# This means the file cache may become outdated, and we may have to
2270+
# reopen the file.
2271+
for retry in (True, False):
2272+
try:
2273+
self._delay_off = self.set_attr_int(self._delay_off, 'delay_off', value)
2274+
return
2275+
except OSError:
2276+
if retry:
2277+
self._delay_off = None
2278+
else:
2279+
raise
22022280

2203-
# ~autogen
22042281

22052282
@property
22062283
def brightness_pct(self):

templates/generic-get-set.liquid

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{% assign class_name = currentClass.friendlyName | downcase | underscore_spaces %}{%
22
for prop in currentClass.systemProperties %}{%
33
assign prop_name = prop.name | downcase | underscore_spaces %}{%
4+
if class_name != 'led' or prop_name != 'trigger' and prop_name != 'delay_on' and prop_name != 'delay_off' %}{%
45
assign getter = prop.type %}{%
56
assign setter = prop.type %}{%
67
if prop.type == 'string array' %}{%
@@ -32,5 +33,6 @@ for prop in currentClass.systemProperties %}{%
3233
self._{{ prop_name }} = self.set_attr_{{ setter }}(self._{{ prop_name }}, '{{prop.systemName}}', value){%
3334
endif%}{% unless forloop.last %}
3435
{% endunless %}{%
36+
endif %}{%
3537
endfor %}
3638

0 commit comments

Comments
 (0)