|
@@ -2,6 +2,7 @@
|
2
|
2
|
|
3
|
3
|
import argparse
|
4
|
4
|
import sys
|
|
5
|
+import time
|
5
|
6
|
|
6
|
7
|
import pdbuddy
|
7
|
8
|
|
|
@@ -11,109 +12,164 @@ class ExitCode:
|
11
|
12
|
wrong_output = 2
|
12
|
13
|
|
13
|
14
|
|
14
|
|
-def write_verify(sink, cfg):
|
15
|
|
- """Write a SinkConfig to a Sink and verify that it was written"""
|
16
|
|
- sink.set_tmpcfg(cfg)
|
17
|
|
- sink.write()
|
|
15
|
+class SinkTester:
|
|
16
|
+ """Tests a PD Buddy Sink"""
|
18
|
17
|
|
19
|
|
- actual_cfg = sink.get_cfg()
|
20
|
|
- if actual_cfg != cfg:
|
21
|
|
- print('Configuration error; expected config:')
|
22
|
|
- print(cfg)
|
23
|
|
- print('actual config:')
|
24
|
|
- print(actual_cfg)
|
25
|
|
- sys.exit(ExitCode.configuration_error)
|
|
18
|
+ cfg_20v = pdbuddy.SinkConfig(status=pdbuddy.SinkStatus.VALID,
|
|
19
|
+ flags=pdbuddy.SinkFlags.NONE, v=20000, vmin=None, vmax=None,
|
|
20
|
+ i=1000, idim=pdbuddy.SinkDimension.CURRENT)
|
|
21
|
+ cfg_9v = pdbuddy.SinkConfig(status=pdbuddy.SinkStatus.VALID,
|
|
22
|
+ flags=pdbuddy.SinkFlags.NONE, v=9000, vmin=None, vmax=None, i=1000,
|
|
23
|
+ idim=pdbuddy.SinkDimension.CURRENT)
|
26
|
24
|
|
|
25
|
+ flip_poll = 0.125
|
|
26
|
+ flip_delay = 1
|
27
|
27
|
|
28
|
|
-def output_verify(sink):
|
29
|
|
- """Verify that the Sink's output is correct"""
|
30
|
|
- # Get the configured voltage
|
31
|
|
- voltage = sink.get_cfg().v
|
32
|
|
- if voltage is None:
|
33
|
|
- voltage = 0
|
|
28
|
+ @staticmethod
|
|
29
|
+ def _get_tty():
|
|
30
|
+ devices = list(pdbuddy.Sink.get_devices())
|
|
31
|
+ # If the wrong number of devices is present, complain and exit.
|
|
32
|
+ if len(devices) < 1:
|
|
33
|
+ raise ValueError('No PD Buddy Sink devices found')
|
|
34
|
+ elif len(devices) > 1:
|
|
35
|
+ raise ValueError('Multiple PD Buddy Sink devices found')
|
|
36
|
+ # Set tty to the auto-detected Sink
|
|
37
|
+ return devices[0].device
|
|
38
|
+
|
|
39
|
+ def _pre_write(self, cfg):
|
|
40
|
+ """Notify the user that new configuration is being written"""
|
|
41
|
+ print('Writing {v:.1f} V configuration object…'.format(v=cfg.v/1000.))
|
|
42
|
+
|
|
43
|
+ def _cfg_verify(self, sink, cfg):
|
|
44
|
+ """Verify that the given configuration is on the Sink"""
|
|
45
|
+ actual_cfg = sink.get_cfg()
|
|
46
|
+ assert actual_cfg == cfg, ('Configuration error; expected config:\n'
|
|
47
|
+ '{cfg}\n'
|
|
48
|
+ 'actual config:\n'
|
|
49
|
+ '{actual_cfg}'.format(cfg=cfg, actual_cfg=actual_cfg))
|
|
50
|
+
|
|
51
|
+ def _post_write(self, cfg):
|
|
52
|
+ """Notify the user that new configuration has been written"""
|
|
53
|
+ print('Done.')
|
34
|
54
|
|
35
|
|
- answer = input("Is the Sink's output stable at {:.1f} V [Y,n]? ".format(
|
36
|
|
- voltage/1000. * sink.output))
|
37
|
|
- if answer.lower().startswith('n'):
|
38
|
|
- print('Wrong output, exiting.')
|
39
|
|
- sys.exit(ExitCode.wrong_output)
|
|
55
|
+ def _write_verify(self, sink, cfg):
|
|
56
|
+ """Write a SinkConfig to a Sink and verify that it was written"""
|
|
57
|
+ self._pre_write(cfg)
|
40
|
58
|
|
|
59
|
+ sink.set_tmpcfg(cfg)
|
|
60
|
+ sink.write()
|
41
|
61
|
|
42
|
|
-def main():
|
43
|
|
- # Make the argument parser
|
44
|
|
- parser = argparse.ArgumentParser(description='Test a PD Buddy Sink')
|
45
|
|
- parser.add_argument('tty', metavar='tty', type=str, nargs='?',
|
46
|
|
- help="the Sink's tty")
|
47
|
|
- parser.add_argument('-l', '--list-devices', action='store_true',
|
48
|
|
- help='list connected PD Buddy Sinks and exit')
|
|
62
|
+ self._cfg_verify(sink, cfg)
|
49
|
63
|
|
50
|
|
- # Parse arguments
|
51
|
|
- args = parser.parse_args()
|
|
64
|
+ self._post_write(cfg)
|
52
|
65
|
|
53
|
|
- # If asked to, list devices and exit
|
54
|
|
- if args.list_devices:
|
55
|
|
- for sinkinfo in pdbuddy.Sink.get_devices():
|
56
|
|
- print(sinkinfo.device, '-', sinkinfo.manufacturer,
|
57
|
|
- sinkinfo.product, sinkinfo.serial_number)
|
58
|
|
- sys.exit(0)
|
|
66
|
+ def _test_output(self, sink, voltage):
|
|
67
|
+ """Test if the Sink's output is correct"""
|
|
68
|
+ answer = input("Is the Sink's output stable at {:.1f} V [Y,n]? ".format(
|
|
69
|
+ voltage/1000. * sink.output))
|
|
70
|
+ return not answer.lower().startswith('n')
|
59
|
71
|
|
60
|
|
- # If there's no device file specified, try to auto-detect
|
61
|
|
- if not args.tty:
|
62
|
|
- devices = list(pdbuddy.Sink.get_devices())
|
63
|
|
- # If the wrong number of devices is present, complain and exit.
|
64
|
|
- if len(devices) < 1:
|
65
|
|
- print('No PD Buddy Sink devices found')
|
66
|
|
- sys.exit(1)
|
67
|
|
- elif len(devices) > 1:
|
68
|
|
- print('Multiple PD Buddy Sink devices found')
|
69
|
|
- sys.exit(1)
|
70
|
|
- # Set args.tty to the auto-detected Sink
|
71
|
|
- args.tty = devices[0].device
|
|
72
|
+ def _output_verify(self, sink):
|
|
73
|
+ """Verify that the Sink's output is correct"""
|
|
74
|
+ # Get the configured voltage
|
|
75
|
+ voltage = sink.get_cfg().v
|
|
76
|
+ if voltage is None:
|
|
77
|
+ voltage = 0
|
72
|
78
|
|
73
|
|
- # Define configurations for testing
|
74
|
|
- cfg_20v = pdbuddy.SinkConfig(status=pdbuddy.SinkStatus.VALID,
|
75
|
|
- flags=pdbuddy.SinkFlags.NONE, v=20000, vmin=None, vmax=None,
|
76
|
|
- i=1000, idim=pdbuddy.SinkDimension.CURRENT)
|
77
|
|
- cfg_9v = pdbuddy.SinkConfig(status=pdbuddy.SinkStatus.VALID,
|
78
|
|
- flags=pdbuddy.SinkFlags.NONE, v=9000, vmin=None, vmax=None, i=1000,
|
79
|
|
- idim=pdbuddy.SinkDimension.CURRENT)
|
|
79
|
+ assert self._test_output(sink, voltage), 'Wrong output voltage'
|
80
|
80
|
|
81
|
|
- # Run the testing procedure
|
82
|
|
- with pdbuddy.Sink(args.tty) as sink:
|
|
81
|
+ def _test_phase1(self, sink):
|
83
|
82
|
# Make sure output is disabled to start
|
84
|
83
|
sink.output = False
|
85
|
84
|
|
86
|
85
|
# Set initial configuration
|
87
|
|
- print('Writing 20 V configuration object…')
|
88
|
|
- write_verify(sink, cfg_20v)
|
89
|
|
- print('Done.')
|
|
86
|
+ self._write_verify(sink, self.cfg_20v)
|
90
|
87
|
|
91
|
88
|
# Turn on the output and ensure that it's correct
|
92
|
89
|
sink.output = True
|
93
|
|
- output_verify(sink)
|
|
90
|
+ self._output_verify(sink)
|
94
|
91
|
|
95
|
92
|
# Turn off the output and ensure that it's off
|
96
|
93
|
sink.output = False
|
97
|
|
- output_verify(sink)
|
|
94
|
+ self._output_verify(sink)
|
98
|
95
|
|
99
|
96
|
# Turn on the output again and ensure that it's back at 20 V
|
100
|
97
|
sink.output = True
|
101
|
|
- output_verify(sink)
|
|
98
|
+ self._output_verify(sink)
|
102
|
99
|
|
103
|
100
|
# Set second configuration
|
104
|
|
- print('Writing 9 V configuration object…')
|
105
|
|
- write_verify(sink, cfg_9v)
|
106
|
|
- print('Done.')
|
|
101
|
+ self._write_verify(sink, self.cfg_9v)
|
107
|
102
|
|
108
|
103
|
# Ensure that the output is 9 V now
|
109
|
|
- output_verify(sink)
|
|
104
|
+ self._output_verify(sink)
|
|
105
|
+
|
|
106
|
+ def _alert_flip(self):
|
|
107
|
+ print('Remove, flip, and re-insert the USB connector.')
|
|
108
|
+
|
|
109
|
+ def _flip(self):
|
|
110
|
+ self._alert_flip()
|
|
111
|
+
|
|
112
|
+ # Wait for the Sink to be disconnected
|
|
113
|
+ while len(list(pdbuddy.Sink.get_devices())):
|
|
114
|
+ time.sleep(self.flip_poll)
|
|
115
|
+
|
|
116
|
+ # Wait for the Sink to be connected
|
|
117
|
+ while not len(list(pdbuddy.Sink.get_devices())):
|
|
118
|
+ time.sleep(self.flip_poll)
|
|
119
|
+
|
|
120
|
+ time.sleep(self.flip_delay)
|
|
121
|
+
|
|
122
|
+ def _test_phase2(self, sink):
|
|
123
|
+ # Ensure that the Sink is configured for 9 V
|
|
124
|
+ self._cfg_verify(sink, self.cfg_9v)
|
|
125
|
+
|
|
126
|
+ # Ensure that the output is off
|
|
127
|
+ self._output_verify(sink)
|
|
128
|
+
|
|
129
|
+ # Turn on the output and ensure that it's correct (9 V)
|
|
130
|
+ sink.output = True
|
|
131
|
+ self._output_verify(sink)
|
110
|
132
|
|
111
|
133
|
# Erase the sink's configuration
|
112
|
134
|
sink.erase()
|
113
|
135
|
|
114
|
136
|
# Ensure there's no output despite it being enabled
|
115
|
137
|
sink.output = True
|
116
|
|
- output_verify(sink)
|
|
138
|
+ self._output_verify(sink)
|
|
139
|
+
|
|
140
|
+ def test(self):
|
|
141
|
+ """Test a PD Buddy Sink"""
|
|
142
|
+ with pdbuddy.Sink(self._get_tty()) as sink:
|
|
143
|
+ self._test_phase1(sink)
|
|
144
|
+
|
|
145
|
+ self._flip()
|
|
146
|
+
|
|
147
|
+ with pdbuddy.Sink(self._get_tty()) as sink:
|
|
148
|
+ self._test_phase2(sink)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+def main():
|
|
152
|
+ # Make the argument parser
|
|
153
|
+ parser = argparse.ArgumentParser(description='Test a PD Buddy Sink')
|
|
154
|
+ parser.add_argument('-l', '--list-devices', action='store_true',
|
|
155
|
+ help='list connected PD Buddy Sinks and exit')
|
|
156
|
+
|
|
157
|
+ # Parse arguments
|
|
158
|
+ args = parser.parse_args()
|
|
159
|
+
|
|
160
|
+ # If asked to, list devices and exit
|
|
161
|
+ if args.list_devices:
|
|
162
|
+ for sinkinfo in pdbuddy.Sink.get_devices():
|
|
163
|
+ print(sinkinfo.device, '-', sinkinfo.manufacturer,
|
|
164
|
+ sinkinfo.product, sinkinfo.serial_number)
|
|
165
|
+ sys.exit(0)
|
|
166
|
+
|
|
167
|
+ tester = SinkTester()
|
|
168
|
+ try:
|
|
169
|
+ tester.test()
|
|
170
|
+ except (AssertionError, ValueError) as e:
|
|
171
|
+ print(e)
|
|
172
|
+ sys.exit(1)
|
117
|
173
|
|
118
|
174
|
# Congratulations, all tests passed!
|
119
|
175
|
print('Test successful!')
|