1818import textwrap
1919from pathlib import Path
2020from tempfile import NamedTemporaryFile
21- from typing import Any , Dict , Optional
21+ from typing import Any , Dict , List , Optional
2222
2323import serial
2424
3131BAUDRATE = 19200 # NOTE: This needs to match the baudrate in the test sketch
3232
3333
34- def parse_test_output (test_output : str , results : Dict [str , Any ]) -> None :
34+ def parse_test_output (test_output : List [ str ] , results : Dict [str , Any ]) -> bool :
3535 """Parse the test output from the Arduino."""
3636 current_test = 1
37+ pass_fail = True
3738
38- lines = test_output .splitlines ()
39- lines_iter = iter (lines )
39+ lines_iter = iter (test_output )
4040 for line in lines_iter :
4141 line = line .strip ()
4242 if not line :
@@ -52,14 +52,37 @@ def parse_test_output(test_output: str, results: Dict[str, Any]) -> None:
5252 assert test_num == current_test , f"Missing test { current_test } "
5353 current_test += 1
5454
55- # TODO
5655 if test_num == 1 :
57- pass
58- elif test_num > 1 and test_num < 6 :
59-
60- pass
61- elif test_num >= 6 :
62- pass
56+ result_line = next (lines_iter )
57+ results ['stuck_pins' ] = result_line .split ()[- 1 ] == 'OK!'
58+ elif test_num in range (2 , 6 ):
59+ name_prefix = "" if test_num < 4 else "analog-"
60+ name_suffix = "sink" if test_num % 2 else "source"
61+ header_line = next (lines_iter )
62+ _volts_line = next (lines_iter )
63+ result_line = next (lines_iter )
64+
65+ header_fields = header_line .split ()
66+ result_fields = result_line .split ()
67+ for pin , result_val in zip (header_fields , result_fields ):
68+ results [f'{ name_prefix } { pin } _{ name_suffix } ' ] = (result_val == '-OK-' )
69+ elif test_num in range (6 , 9 ):
70+ adc_level = {6 : 'mid' , 7 : 'high' , 8 : 'low' }[test_num ]
71+ adc_bounds = {6 : (2.2 , 2.7 ), 7 : (3.0 , 3.6 ), 8 : (1.2 , 2.0 )}[test_num ]
72+ header_line = next (lines_iter )
73+ volts_line = next (lines_iter )
74+
75+ header_fields = header_line .split ()
76+ result_fields = volts_line .split ()
77+ for pin , result_val in zip (header_fields , result_fields ):
78+ pin_num = pin .split ('-' )[- 1 ]
79+ pin_result = adc_bounds [0 ] <= float (result_val ) <= adc_bounds [1 ]
80+ results [f'adc_{ adc_level } _{ pin_num } ' ] = pin_result
81+ if not pin_result :
82+ pass_fail = False
83+
84+ assert current_test == 9 , f"Test { current_test } not found"
85+ return pass_fail
6386
6487
6588def test_arduino (
@@ -97,21 +120,22 @@ def test_arduino(
97120 serial_port = serial .Serial (
98121 port = arduino .port ,
99122 baudrate = BAUDRATE ,
100- timeout = 30 ,
123+ timeout = 2 ,
101124 )
102125
103126 try :
104- test_output = serial_port .read_until (b'TEST COMPLETE\n ' ).decode ('utf-8' )
105- test_summary = serial_port .readline ().decode ('utf-8' ).strip ()
127+ * lines_bytes , test_summary_bytes = serial_port .readlines ()
128+ lines = [line .decode ('utf-8' ).strip () for line in lines_bytes ]
129+ test_summary = test_summary_bytes .decode ('utf-8' ).strip ()
106130 except serial .SerialTimeoutException :
107131 logger .error ("Timed out waiting for test output" )
108132 raise AssertionError ("Timed out waiting for test output" )
109133 finally :
110134 serial_port .close ()
111135
112- parse_test_output (test_output , results )
136+ assert parse_test_output (lines , results ), "Failed analog tests"
113137 # Test summary only contains content when there are failures
114- assert test_summary == "" , f"Test failed: { test_summary } "
138+ assert test_summary == "" , test_summary
115139
116140 # Flash arduino with stock firmware
117141 flash_arduino (avrdude , arduino .port , stock_fw_hex )
@@ -127,7 +151,16 @@ def test_arduino(
127151def main (args : argparse .Namespace ) -> None :
128152 """Main function for the arduino test."""
129153 new_log = True
130- fieldnames = ['asset' , 'serial' , 'passed' ]
154+ fieldnames = ['asset' , 'serial' , 'passed' , 'stuck_pins' ]
155+ fieldnames += [f'PIN-{ n } _source' for n in range (3 , 13 )]
156+ fieldnames += [f'PIN-{ n } _sink' for n in range (3 , 13 )]
157+ fieldnames += [f'analog-PIN-{ n } _source' for n in range (1 , 6 )]
158+ fieldnames += [f'analog-PIN-{ n } _sink' for n in range (1 , 6 )]
159+ fieldnames += [
160+ f'adc_{ lvl } _{ n } '
161+ for lvl in ('mid' , 'high' , 'low' )
162+ for n in range (0 , 6 )
163+ ]
131164
132165 try :
133166 avrdude = get_avrdude_path ()
0 commit comments