-
-
Save ThiefMaster/6e0ed390707f57cb0c6a to your computer and use it in GitHub Desktop.
Demo script for my "rotary board" - https://github.com/ThiefMaster/rotaryboard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!py -3 | |
import atexit | |
import re | |
import signal | |
import subprocess | |
import sys | |
from serial import Serial | |
from win32com.client import Dispatch | |
class Demo(object): | |
# the internal order of LEDs is not extremely intuitive so we | |
# use a different order to make this script a bit nicer | |
_LED_ORDER = '012387654' | |
def __init__(self, port): | |
self._active = True | |
self._port = port | |
self._shell = Dispatch('WScript.Shell') | |
self._serial = None | |
self._mode = 0 | |
self._submode = 0 | |
self._modesteps = 0 | |
self._ticks = 0 | |
atexit.register(self._close) | |
self._open() | |
signal.signal(signal.SIGINT, lambda num, frame: self._stop()) | |
def run(self): | |
_MSG_RE = re.compile(r'([A-Z]+)(?:\.([0-9]))?(?:=(-?[0-9]+))?') | |
ready = False | |
# reset the board | |
self._send('RST') | |
while self._active: | |
line = self._recv() | |
if ready: | |
match = _MSG_RE.match(line) | |
if match is not None: | |
cmd, n, val = match.groups() | |
n = int(n) if n is not None else None | |
val = int(val) if val is not None else None | |
self._process(cmd, n, val) | |
self._tick() | |
elif line == 'READY': | |
ready = True | |
self._ready() | |
def _ready(self): | |
# once the board is ready, we turn off all LEDs | |
for n in range(9): | |
self._led(n, '0') | |
def _tick(self): | |
self._ticks += 1 | |
# mode 0: fancy blinking unless a specific LED is selected | |
if self._mode == 0: | |
if self._submode == 0: | |
self._led(0, '0RGY'[(self._ticks // 3) % 4]) | |
else: | |
self._led(0, 0) | |
# mode 1: notification blinkers | |
elif self._mode == 1 and self._modesteps == 0: | |
if self._submode == 0: | |
self._led(7, 0) | |
self._led(8, self._ticks % 2 == 0) | |
elif self._submode == 1: | |
self._led(7, self._ticks % 2 == 0) | |
self._led(8, self._ticks % 2 == 1) | |
# mode 2/3: powerpoint control. indicate direction using the multicolor LED | |
elif self._mode in (2, 3): | |
if self._submode == 5: | |
self._led(0, 0) | |
else: | |
self._led(0, 'RG'[self._mode - 2]) | |
self._submode += 1 | |
def _process(self, cmd, n, val): | |
# button pressed | |
if cmd == 'RBTN' and val: | |
self._submode = 0 | |
if self._mode != n: | |
self._modesteps = 0 | |
else: | |
self._modesteps += 1 | |
self._mode = n | |
self._dark() | |
if self._mode == 1: | |
if self._modesteps > 0: | |
self._led(self._modesteps + 3, 1) | |
if self._modesteps >= 3: | |
self._led(0, 'G') | |
self._interactive() | |
self._process('RBTN', 0, 1) # back to mode 0 | |
elif self._mode in (2, 3): | |
self._sendkeys(['{LEFT}', '{RIGHT}'][n - 2]) | |
# rotart button turned | |
elif cmd == 'RVAL' and n == 0: | |
if self._mode == 0: | |
self._submode += 1 if val > 0 else -1 | |
self._submode %= 9 | |
self._dark() | |
if self._submode != 0: | |
self._led(self._submode, '1') | |
elif self._mode == 1: | |
self._submode += 1 if val > 0 else -1 | |
self._submode %= 2 | |
def _dark(self): | |
for n in range(9): | |
self._led(n, '0') | |
def _sendkeys(self, keys): | |
self._shell.SendKeys(keys) | |
def _interactive(self): | |
self._close() | |
subprocess.call(['f:/putty/putty.exe', '-load', 'rot']) | |
self._open() | |
self._dark() | |
def _stop(self): | |
self._dark() | |
self._active = False | |
def _close(self): | |
if self._serial is not None: | |
self._serial.close() | |
def _open(self): | |
self._close() | |
self._serial = Serial(self._port, 19200, timeout=0.1) | |
def _send(self, cmd, n=None, val=None): | |
if n is not None and val is not None: | |
line = '{}.{}={}\n'.format(cmd, n, int(val) if isinstance(val, bool) else val) | |
elif n is not None: | |
line = '{}.{}\n'.format(cmd, n) | |
else: | |
line = '{}\n'.format(cmd) | |
self._serial.write(bytes(line, 'ascii')) | |
def _led(self, n, color): | |
self._send('RLED', self._LED_ORDER[n], color) | |
def _recv(self): | |
return self._serial.readline().decode('ascii').lstrip('\0').strip() | |
if __name__ == '__main__': | |
Demo(sys.argv[1] if len(sys.argv) > 1 else 'COM3').run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment