1
1
#!/usr/bin/env python
2
2
# SPDX-License-Identifier: MIT
3
-
4
- from absl import app , flags
5
-
6
3
from os .path import basename , expanduser
7
- from typing import List
4
+ from typing import List , Optional
5
+
6
+ import serial .tools .list_ports
7
+ from absl import app , flags , logging
8
8
9
9
from .config import ToolConfig
10
10
from .device import Device
15
15
flags .DEFINE_string ('device' , None , 'Busy Tag\' s serial port.' )
16
16
flags .DEFINE_integer ('baudrate' , 115200 , 'Connection baudrate.' )
17
17
18
+
18
19
def format_size (size : int ) -> str :
19
20
if size < 1_000 :
20
21
return f'{ size } B'
21
22
if size < 500_000 :
22
- return f'{ size / 1_000 :.2f} kB'
23
- return f'{ size / 1_000_000 :.2f} MB'
24
-
25
-
26
- def main (argv : List [str ]) -> None :
23
+ return f'{ size / 1_000 :.2f} kB'
24
+ return f'{ size / 1_000_000 :.2f} MB'
25
+
26
+
27
+ def list_devices (baudrate : int ) -> List [str ]:
28
+ devices = []
29
+ ports = serial .tools .list_ports .comports ()
30
+ logging .debug (f'Probing { len (ports )} serial devices...' )
31
+
32
+ for port in ports :
33
+ try :
34
+ logging .debug (f'Trying to connect to { port .device } ' )
35
+ with serial .Serial (port .device , baudrate = baudrate , timeout = 1.0 ) as conn :
36
+ logging .debug (f'Connected to { port .device } ' )
37
+ conn .write (b'AT+GDN\r \n ' )
38
+ while True :
39
+ response = conn .readline ()
40
+ logging .debug (f'Read from device: { response } ' )
41
+ if response .startswith (b'+evn' ):
42
+ continue
43
+ if response .startswith (b'+DN:busytag-' ):
44
+ devices .append (port .device )
45
+ break
46
+ except Exception :
47
+ pass
48
+
49
+ return devices
50
+
51
+
52
+ def main (argv : List [str ]) -> Optional [int ]:
27
53
config = ToolConfig (FLAGS .config_file )
28
54
if FLAGS .device is not None :
29
55
config .device = FLAGS .device
30
- if config .device is None :
31
- raise Exception ('Device must be specified' )
56
+ config .write_to_file ()
32
57
33
- bt :Device = None
58
+ bt : Optional [ Device ] = None
34
59
35
60
# Remove argv[0]
36
- argv .pop (0 )
61
+ exec_name = argv .pop (0 )
37
62
command = 'help'
38
63
if len (argv ) > 0 :
39
64
command = argv .pop (0 )
40
- bt = Device (config .device , baudrate = FLAGS .baudrate )
41
65
66
+ # Don't bother connecting for commands that don't need a device connection.
67
+ if command not in ('list_devices' , 'help' ):
68
+ if config .device is None :
69
+ print ('A device must be specified using the `--device` flag or be set in the config file!' )
70
+ print (f'You can run `{ exec_name } list_devices` to find the available devices.' )
71
+ return 1
72
+ bt = Device (config .device , baudrate = FLAGS .baudrate )
42
73
43
74
match command :
44
75
case 'info' :
@@ -49,6 +80,15 @@ def main(argv: List[str]) -> None:
49
80
print (f'Storage capacity: { format_size (bt .capacity )} ' )
50
81
print (f'Free storage: { format_size (bt .get_free_storage ())} ' )
51
82
83
+ case 'list_devices' :
84
+ devices = list_devices (FLAGS .baudrate )
85
+ if len (devices ) == 0 :
86
+ print ('No devices found' )
87
+ else :
88
+ print ('Available devices:' )
89
+ for device in devices :
90
+ print (f' { device } ' )
91
+
52
92
case 'list_pictures' :
53
93
print ('Pictures in device:' )
54
94
for picture in bt .list_pictures ():
@@ -91,6 +131,15 @@ def main(argv: List[str]) -> None:
91
131
led_config = LedConfig (LedPin .ALL , argv .pop (0 ).upper ())
92
132
bt .set_led_solid_color (led_config )
93
133
134
+ case 'apply_led_preset' :
135
+ assert len (argv ) >= 1
136
+ preset_name = argv .pop (0 )
137
+
138
+ # Clear all LEDs first
139
+ bt .set_led_solid_color (LedConfig (LedPin .ALL , '000000' ))
140
+ for e in config .led_presets .get (preset_name ):
141
+ bt .set_led_solid_color (e )
142
+
94
143
case 'get_brightness' :
95
144
print (f'Brightness: { bt .get_display_brightness ()} ' )
96
145
@@ -101,8 +150,10 @@ def main(argv: List[str]) -> None:
101
150
bt .set_display_brightness (brightness )
102
151
103
152
case 'help' :
153
+ print (f'\n \t USAGE: { exec_name } [flags] <command> [<args>]\n ' )
104
154
print ('Available commands:' )
105
155
print (' help: Prints this message' )
156
+ print (' list_devices: Lists available devices' )
106
157
print (' info: Displays device information' )
107
158
print (' list_pictures: Lists pictures in device' )
108
159
print (' list_files: Lists files in device' )
@@ -112,16 +163,20 @@ def main(argv: List[str]) -> None:
112
163
print (' get <filename>: Copies <filename> from the device to the working directory' )
113
164
print (' rm <filename>: Deletes <filename>' )
114
165
print (' set_led_solid_color <6 hex RGB colour>: Sets the LEDs colour' )
166
+ print (' apply_led_preset <preset name>: Sets the LEDs colour according to a preset' )
115
167
print (' get_brightness: Gets current display brightness' )
116
168
print (' set_brightness <brightness>: Sets current display brightness (int between 1 and 100, inclusive' )
169
+ print (f'\n For flag documentation, run { exec_name } --help' )
117
170
118
171
case _:
119
172
print (f'Unknown command `{ command } `. Please use the `help` to list available commands' )
173
+ return 1
174
+ return 0
120
175
121
- config .write_to_file ()
122
176
123
177
def run_main ():
124
178
app .run (main )
125
179
180
+
126
181
if __name__ == '__main__' :
127
- run_main ()
182
+ run_main ()
0 commit comments