It's a type of Planche
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

172 lines
5.6KB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import argparse
  4. import logging
  5. from pylibftdi import BitBangDevice
  6. from pylibftdi._base import FtdiError
  7. from pylibftdi.device import Driver
  8. import six
  9. __author__ = "Nate Bohman"
  10. __credits__ = ["Nate Bohman"]
  11. __license__ = "LGPL"
  12. __maintainer__ = "Nate Bohman"
  13. __email__ = "natrinicle@gmail.com"
  14. __status__ = "Development"
  15. logger = logging.getLogger(__name__) # pylint: disable=invalid-name
  16. FAR_LED = {"ON": 0, "MID": 1, "OFF": 21}
  17. NEAR_LED = {"ON": 0, "MID": 2, "OFF": 42}
  18. def set_led(serial_num=None, far_led=None, near_led=None):
  19. """Set the LEDs on an FTDI BitBanged device.
  20. :param serial_num: (optional) Serial number of the FTDI
  21. device or None to use the first
  22. available device.
  23. :param far_led: (optional) Set the LED furthest from the USB
  24. connector to ON, MID, or OFF.
  25. :param near_led: (optional) Set the LED closest to the USB
  26. connector to ON, MID, or OFF.
  27. :type serial_num: :class:`str` or None
  28. :type far_led: :class:`str`
  29. :type near_led: :class:`str`
  30. """
  31. if serial_num is not None:
  32. assert isinstance(serial_num, (six.string_types))
  33. if far_led is not None:
  34. far_led = FAR_LED.get(far_led.upper())
  35. assert isinstance(far_led, (int))
  36. if near_led is not None:
  37. near_led = NEAR_LED.get(near_led.upper())
  38. assert isinstance(near_led, (int))
  39. try:
  40. with BitBangDevice(serial_num) as bb:
  41. if far_led is None:
  42. # Binary bitwise and the current state against the
  43. # bits that are significant to the far_led.
  44. far_led = bb.read_pins() & 21
  45. if near_led is None:
  46. # Binary bitwise and the current state against the
  47. # bits that are significant to the near_led.
  48. near_led = bb.read_pins() & 42
  49. serial = Driver().list_devices()[bb.device_index][2].decode()
  50. log_msg = "Setting {} far led to {}, near_led to {}".format(
  51. serial,
  52. [key for key in FAR_LED if FAR_LED[key] == far_led][0],
  53. [key for key in NEAR_LED if NEAR_LED[key] == near_led][0],
  54. )
  55. logger.info(log_msg)
  56. bb.port = far_led | near_led
  57. except FtdiError as e:
  58. if "usb_open() failed" in str(e):
  59. err_msg = "".join(
  60. [
  61. "Could not open any FTDI devices. Check permissions and ",
  62. "potentially add the following to udev rules "
  63. '\'SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ',
  64. 'ATTRS{idProduct}=="6001", MODE="0666"\' ',
  65. "or ensure the LED dongle is attached to the system.",
  66. ]
  67. )
  68. raise EnvironmentError((-4, err_msg))
  69. def configure_logging(logger, verbosity):
  70. """Take an int and configures logger levels accordingly where 0 = ERROR and 3 = DEBUG.
  71. :param logger: Logger object to configure.
  72. :param verbosity: Integer coresponding to logging level from 0 being ERROR and 3 being DEBUG.
  73. :type logger: :class:`logging.Logger`
  74. :type verbosity: :class:`int`
  75. """
  76. assert isinstance(logger, (logging.Logger))
  77. assert isinstance(verbosity, (int))
  78. # The messages that display are controlled by the -v or -vv arguments in parse_arguments with
  79. # defaults being error or worse. A single v includes warning messages, a double v includes info
  80. # messages, and a triple v includes debug messages. Triple v also changes the log_format to
  81. # include the module, function name, and line number where logger was called from.
  82. #
  83. # Verbosity
  84. # parser.add_argument("-v", "--verbose", dest="verbose", action="count", default=0,)
  85. log_levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
  86. log_level = log_levels[
  87. min(len(log_levels) - 1, verbosity)
  88. ] # capped to number of levels
  89. if log_level > logging.DEBUG:
  90. log_format = "%(asctime)s %(levelname)s %(message)s"
  91. else:
  92. log_format = (
  93. "%(asctime)s %(levelname)s %(module)s %(funcName)s:%(lineno)s %(message)s"
  94. )
  95. logging.basicConfig(format=log_format)
  96. logger.setLevel(level=log_level)
  97. def parse_args():
  98. """Parse Arguments for set_led."""
  99. parser = argparse.ArgumentParser(
  100. description="Set PureStorage Front Panel LED module states."
  101. )
  102. # Base information (usernames, passwords, etc...)
  103. parser.add_argument(
  104. "-s",
  105. "--serial-num",
  106. dest="serial_num",
  107. action="store",
  108. required=False,
  109. help="Serial Number of LED module if more than one installed.",
  110. )
  111. parser.add_argument(
  112. "-f",
  113. "--far-led",
  114. dest="far_led",
  115. action="store",
  116. required=False,
  117. type=str,
  118. help="State to set the LED furthest from the USB connector (ON, MID, OFF).",
  119. )
  120. parser.add_argument(
  121. "-n",
  122. "--near-led",
  123. dest="near_led",
  124. action="store",
  125. required=False,
  126. type=str,
  127. help="State to set the LED closest to the USB connector (ON, MID, OFF).",
  128. )
  129. # Verbosity
  130. parser.add_argument("-v", "--verbose", dest="verbose", action="count", default=0)
  131. # Positional arguments
  132. args = parser.parse_args()
  133. # Configure logging
  134. configure_logging(logger=logger, verbosity=args.verbose)
  135. return args
  136. def main():
  137. """Main function that is called when script directly called."""
  138. args = parse_args()
  139. set_led(serial_num=args.serial_num, far_led=args.far_led, near_led=args.near_led)
  140. if __name__ == "__main__":
  141. main()