From d805a4e0bf5ed6250d5dec6a48e951af364a860b Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Mon, 14 Dec 2015 20:26:23 +0100 Subject: Improve robot control script --- robot/main.py | 58 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/robot/main.py b/robot/main.py index b25f748..0b718b7 100755 --- a/robot/main.py +++ b/robot/main.py @@ -21,15 +21,17 @@ PORT = 8000 +from fcntl import fcntl, F_GETFL, F_SETFL +import io import json -import multiprocessing import os import os.path import signal +import subprocess +import time import engineio import eventlet - import ev3dev ev3_names = { @@ -47,18 +49,32 @@ ev3_motors = [ ] connections = set() -process = None - -def _run_exec(program): - import ev3dev - from mindstorms_widgets import mindstorms_widgets - exec(program) +running = False + +# Make a Python interpreter ready for running user program. +def start_interpreter(): + global running + process = subprocess.Popen(['python3', '-u'], bufsize=1, universal_newlines=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + # Set the non-blocking flag for stdout. + flags = fcntl(process.stdout.fileno(), F_GETFL) + fcntl(process.stdout.fileno(), F_SETFL, flags | os.O_NONBLOCK) + process.stdin.write("import ev3dev\n") + process.stdin.write("from mindstorms_widgets import mindstorms_widgets\n") + running = False + return process + +process = start_interpreter() def run(program): - global process - stop() - process = multiprocessing.Process(target=_run_exec, args=[program]) - process.start() + global process, running + if running: + stop() + running = True + process.stdin.write("exec('''" + program + "''')\n") + process.stdin.close() def stop(): global process @@ -67,16 +83,16 @@ def stop(): os.kill(process.pid, signal.SIGKILL) except: pass - process = None - for motor in ev3_motors: if motor.connected: motor.stop(stop_command='brake') + process = start_interpreter() def notifier(): + global process + sensors_path = '/sys/class/lego-sensor' sensors = {} - for sensor in os.listdir(sensors_path): path = os.path.join(sensors_path, sensor) with open(os.path.join(path, 'driver_name'), 'r') as f: @@ -90,8 +106,17 @@ def notifier(): sensors[path] = (friendly_name, multiplier, unit) while True: - eventlet.sleep(0.2) try: + if running: + text = process.stdout.readline() + if text: + message = {'event': 'output', 'text': text} + for sid in connections: + eio.send(sid, json.dumps(message)) + continue + if process.poll() is not None: + process = start_interpreter() + message = {'event': 'update', 'sensors': {}} for path, (name, multiplier, unit) in sorted(sensors.items()): with open(os.path.join(path, 'value0'), 'rb') as f: @@ -105,6 +130,7 @@ def notifier(): eio.send(sid, text) except: pass + eventlet.sleep(0.2) eio = engineio.Server(async_mode='eventlet', cookie=None) app = engineio.Middleware(eio) -- cgit v1.2.1