Skip to content

Commit

Permalink
stop and delete all scripts on object release (note: not tested, jonn…
Browse files Browse the repository at this point in the history
…y make sure to test before releasing!)
  • Loading branch information
sneakers-the-rat committed Nov 21, 2020
1 parent ce0ddf7 commit e821830
Showing 1 changed file with 48 additions and 7 deletions.
55 changes: 48 additions & 7 deletions autopilot/hardware/gpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ def _series_script(self, values, durations = None, unit="ms", repeat=None, finis
if len(durations) == 1:
iter_series = itertools.product(values, durations)
else:
ValueError("length of values and durations must be equal, or length of durations must be 1. got len(values)={}, len(durations)={}".format(len(values), len(durations)))
raise ValueError("length of values and durations must be equal, or length of durations must be 1. got len(values)={}, len(durations)={}".format(len(values), len(durations)))
else:
iter_series = values.__iter__()

Expand All @@ -422,7 +422,7 @@ def _series_script(self, values, durations = None, unit="ms", repeat=None, finis
elif unit == "us":
wait_fn = "mics"
else:
ValueError("Unit for durations must be ms (milliseconds) or us (microseconds)")
raise ValueError("Unit for durations must be ms (milliseconds) or us (microseconds)")

string_pieces = [b" ".join((self.pigs_function, str(self.pin_bcm).encode('utf-8'), str(val).encode('utf-8'), bytes(wait_fn, 'utf-8'), str(dur).encode('utf-8'))) for val, dur in iter_series]
script_str = b" ".join(string_pieces)
Expand All @@ -431,7 +431,7 @@ def _series_script(self, values, durations = None, unit="ms", repeat=None, finis
try:
repeat = int(repeat)
except:
ValueError('Repeat must be coerceable to an integer, got {}'.format(repeat))
raise ValueError('Repeat must be coerceable to an integer, got {}'.format(repeat))

script_str = b" ".join(("LD v0", str(repeat-1), # "LD (load) variable 0 with number of repeats"
"tag 999", # create a tag that can be returned to
Expand Down Expand Up @@ -514,6 +514,7 @@ def series(self, id=None, delete=None, **kwargs):
if script_status == pigpio.PI_SCRIPT_INITING:
check_times = 0
while self.pig.script_status(self.script_handles[id]) == pigpio.PI_SCRIPT_INITING:
# TODO: Expose this as a parameter -- how long to try and init scripts before skipping, mebs some general 'timeout' variable for all blocking ops.
time.sleep(0.005)
check_times += 1
if check_times > 200:
Expand All @@ -533,6 +534,17 @@ def series(self, id=None, delete=None, **kwargs):
return id

def delete_script(self, script_id):
"""
spawn a thread to delete a script with id ``script_id``
This is a 'soft' deletion -- it checks if the script is running, and waits for up to 10 seconds
before actually deleting it.
The script is deleted from the pigpio daemon, from ``script_handles`` and from ``scripts``
Args:
script_id (str): a script ID in :attr:`.Digital_Out.script_handles`
"""
delete_script = threading.Thread(target=self._delete_script, args=(script_id,))
delete_script.start()

Expand All @@ -546,8 +558,32 @@ def _delete_script(self, script_id):

self.pig.delete_script(self.script_handles[script_id])

del self.scripts[self.script_handles[script_id]]
del self.script_handles[script_id]
del self.scripts[script_id]


def delete_all_scripts(self):
"""
Stop and delete all scripts
This is a "hard" deletion -- the script will be immediately stopped if it's running.
"""

for script_handle, script_id in self.script_handles.items():
try:
self.stop_script(script_handle)
except Exception as e:
self.logger.exception(e)

try:
self.pig.delete_script(script_id)
except Exception as e:
self.logger.exception(e)

del self.scripts[self.script_handles[script_id]]
del self.script_handles[script_id]



def stop_script(self, id=None):
"""
Expand Down Expand Up @@ -585,12 +621,16 @@ def stop_script(self, id=None):

def release(self):
"""
Stops last running script, sets to :attr:`~.Digital_Out.off`, and calls :meth:`.GPIO.release`
Stops and deletes all scripts, sets to :attr:`~.Digital_Out.off`, and calls :meth:`.GPIO.release`
"""
try:
self.stop_script()

self.delete_all_scripts()

#self.stop_script()
self.set(self.off)
time.sleep(0.1)

except AttributeError:
# self.pig has already been deleted (release has already been called)
# so self.pig has no attribute 'send' because it is None
Expand Down Expand Up @@ -649,6 +689,7 @@ def __init__(self, pin, event=None, record=True, **kwargs):
self.callbacks = []

# List to store logic transition events
# FIXME: Should be a deque
self.events = []

self.record = record
Expand Down Expand Up @@ -869,7 +910,7 @@ def release(self):
"""
# FIXME: reimplementing parent release method here because of inconsistent use of self.off -- unify API and fix!!
try:
self.stop_script()
self.delete_all_scripts()
self.set(0) # clean values should handle inversion, don't use self.off
time.sleep(0.1)
self.pig.stop()
Expand Down

0 comments on commit e821830

Please sign in to comment.