-
Notifications
You must be signed in to change notification settings - Fork 51
/
demo_effect_repl.py
190 lines (159 loc) · 5.17 KB
/
demo_effect_repl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import argparse
import logging
import time
from typing import Optional
import serial
from python_tools.effect_definitions import (
base_color_effects,
special_effects,
tail_codes,
)
from python_tools.pixmob_conversion_funcs import bits_to_arduino_string
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s"
)
LOG = logging.getLogger(__name__)
def print_help():
print(
"Command syntax:",
" BASE_EFFECT [TAIL_CODE]",
" SPECIAL_EFFECT [TAIL_CODE]",
"Base effects:",
" ".join(base_color_effects.keys()),
"",
"Special effects:",
" ".join(special_effects.keys()),
"",
"Tail codes:",
" ".join(tail_codes.keys()),
"",
"Example:",
" %s" % next(iter(base_color_effects.keys())),
" %s %s"
% (next(iter(base_color_effects.keys())), next(iter(tail_codes.keys()))),
sep="\n",
)
def send_effect(
serial_port: serial.Serial, effect_code: str, tail_code: Optional[str] = None
):
effect_bits = []
effect_code = effect_code.upper().strip()
if effect_code in base_color_effects:
effect_bits = base_color_effects[effect_code]
elif effect_code in special_effects:
effect_bits = special_effects[effect_code]
else:
LOG.warning(
"Invalid base effect %s. See base_color_effects and "
"special_effects in effect_definitions.py for options.",
effect_code,
)
return
# NOTE: Not sure if special effects also take tail code input
if tail_code is not None:
tail_code = tail_code.upper().strip()
if tail_code in tail_codes:
effect_bits += tail_codes[tail_code]
else:
LOG.warning(
"Invalid tail code %s. See tail_codes "
"in effect_definitions.py for options.",
tail_code,
)
arduino_string_ver = bits_to_arduino_string(effect_bits)
tx_data = bytes(arduino_string_ver, "utf-8")
LOG.debug("Transmitting %s...", tx_data[:32])
serial_port.write(tx_data)
# Small delay after each command
time.sleep(0.1)
def repl_commands(serial_port: serial.Serial):
print('Type "help" for a list of known commands, "exit" or "q" to quit.')
while True:
try:
cmd = input("Command> ")
except KeyboardInterrupt:
break
# Split by space to add tail command after base command.
cmd = cmd.upper().split(" ")
if cmd[0] == "EXIT" or cmd[0] == "Q":
break
if cmd[0] == "HELP":
print_help()
continue
effect_code = cmd[0]
tail_code = cmd[1] if len(cmd) > 1 else None
send_effect(serial_port, effect_code, tail_code=tail_code)
def main():
parser = argparse.ArgumentParser(
description=(
"Simple command-line loop to send effects "
"to the Pixmob bracelet by typing in the effect names."
)
)
parser.add_argument(
"-p",
"--port",
default="/dev/ttyUSB0",
type=str,
help="Serial port (COMx, /dev/ttyUSB0 or /dev/ttyACM0) to connect.",
)
parser.add_argument(
"-b",
"--baud-rate",
default=115200,
type=int,
help="Serial baud rate (default: 115200)",
)
parser.add_argument(
"-w",
"--wait-on-connect",
action="store_true",
default=False,
help=(
"Set to True if using a lower power microcontroller "
"(like an Arduino Nano instead of ESP board) "
"and you have issues."
),
)
parser.add_argument(
"-c",
"--continue-cli",
action="store_true",
default=False,
help=(
"Set to True if you are passing the effect in the "
"command line, and want to still drop into the REPL."
),
)
parser.add_argument("effect", type=str, nargs="?")
parser.add_argument("tail_code", type=str, nargs="?")
args = parser.parse_args()
try:
LOG.info("Connecting to %s at baud rate %d...", args.port, args.baud_rate)
arduino = serial.Serial(port=args.port, baudrate=args.baud_rate, timeout=0.1)
LOG.info("Connected!")
except Exception:
LOG.exception("Failed while trying to connect. Full traceback:")
print(
"If you haven't, specify the serial port to connect to using "
"the '-p' argument."
)
print("Run the script with '-h' for more information.")
exit(1)
try:
if args.wait_on_connect:
time.sleep(2.5)
# If user has provided effect in arguments, send it directly
if args.effect is not None:
send_effect(arduino, args.effect, tail_code=args.tail_code)
# If the program should not go to the repl after done, exit.
if not args.continue_cli:
return
repl_commands(arduino)
except Exception:
LOG.exception("Uncaught exception occurred in the input loop. Full traceback:")
finally:
arduino.close()
if __name__ == "__main__":
main()