Python library for working with the PD Buddy Sink Serial Console Configuration Interface
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_sink.py 5.2KB

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