|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
-
- import argparse
- import logging
-
- from pylibftdi import BitBangDevice
- from pylibftdi._base import FtdiError
- from pylibftdi.device import Driver
- import six
-
- __author__ = "Nate Bohman"
- __credits__ = ["Nate Bohman"]
- __license__ = "LGPL"
- __maintainer__ = "Nate Bohman"
- __email__ = "natrinicle@gmail.com"
- __status__ = "Development"
-
- logger = logging.getLogger(__name__) # pylint: disable=invalid-name
-
-
- FAR_LED = {"ON": 0, "MID": 1, "OFF": 21}
- NEAR_LED = {"ON": 0, "MID": 2, "OFF": 42}
-
-
- def set_led(serial_num=None, far_led=None, near_led=None):
- """Set the LEDs on an FTDI BitBanged device.
-
- :param serial_num: (optional) Serial number of the FTDI
- device or None to use the first
- available device.
- :param far_led: (optional) Set the LED furthest from the USB
- connector to ON, MID, or OFF.
- :param near_led: (optional) Set the LED closest to the USB
- connector to ON, MID, or OFF.
- :type serial_num: :class:`str` or None
- :type far_led: :class:`str`
- :type near_led: :class:`str`
- """
- if serial_num is not None:
- assert isinstance(serial_num, (six.string_types))
- if far_led is not None:
- far_led = FAR_LED.get(far_led.upper())
- assert isinstance(far_led, (int))
- if near_led is not None:
- near_led = NEAR_LED.get(near_led.upper())
- assert isinstance(near_led, (int))
-
- try:
- with BitBangDevice(serial_num) as bb:
- if far_led is None:
- # Binary bitwise and the current state against the
- # bits that are significant to the far_led.
- far_led = bb.read_pins() & 21
- if near_led is None:
- # Binary bitwise and the current state against the
- # bits that are significant to the near_led.
- near_led = bb.read_pins() & 42
-
- serial = Driver().list_devices()[bb.device_index][2].decode()
-
- log_msg = "Setting {} far led to {}, near_led to {}".format(
- serial,
- [key for key in FAR_LED if FAR_LED[key] == far_led][0],
- [key for key in NEAR_LED if NEAR_LED[key] == near_led][0],
- )
- logger.info(log_msg)
- bb.port = far_led | near_led
- except FtdiError as e:
- if "usb_open() failed" in str(e):
- err_msg = "".join(
- [
- "Could not open any FTDI devices. Check permissions and ",
- "potentially add the following to udev rules "
- '\'SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ',
- 'ATTRS{idProduct}=="6001", MODE="0666"\' ',
- "or ensure the LED dongle is attached to the system.",
- ]
- )
- raise EnvironmentError((-4, err_msg))
-
-
- def configure_logging(logger, verbosity):
- """Take an int and configures logger levels accordingly where 0 = ERROR and 3 = DEBUG.
-
- :param logger: Logger object to configure.
- :param verbosity: Integer coresponding to logging level from 0 being ERROR and 3 being DEBUG.
- :type logger: :class:`logging.Logger`
- :type verbosity: :class:`int`
- """
- assert isinstance(logger, (logging.Logger))
- assert isinstance(verbosity, (int))
-
- # The messages that display are controlled by the -v or -vv arguments in parse_arguments with
- # defaults being error or worse. A single v includes warning messages, a double v includes info
- # messages, and a triple v includes debug messages. Triple v also changes the log_format to
- # include the module, function name, and line number where logger was called from.
- #
- # Verbosity
- # parser.add_argument("-v", "--verbose", dest="verbose", action="count", default=0,)
-
- log_levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
- log_level = log_levels[
- min(len(log_levels) - 1, verbosity)
- ] # capped to number of levels
- if log_level > logging.DEBUG:
- log_format = "%(asctime)s %(levelname)s %(message)s"
- else:
- log_format = (
- "%(asctime)s %(levelname)s %(module)s %(funcName)s:%(lineno)s %(message)s"
- )
-
- logging.basicConfig(format=log_format)
- logger.setLevel(level=log_level)
-
-
- def parse_args():
- """Parse Arguments for set_led."""
- parser = argparse.ArgumentParser(
- description="Set PureStorage Front Panel LED module states."
- )
-
- # Base information (usernames, passwords, etc...)
- parser.add_argument(
- "-s",
- "--serial-num",
- dest="serial_num",
- action="store",
- required=False,
- help="Serial Number of LED module if more than one installed.",
- )
- parser.add_argument(
- "-f",
- "--far-led",
- dest="far_led",
- action="store",
- required=False,
- type=str,
- help="State to set the LED furthest from the USB connector (ON, MID, OFF).",
- )
- parser.add_argument(
- "-n",
- "--near-led",
- dest="near_led",
- action="store",
- required=False,
- type=str,
- help="State to set the LED closest to the USB connector (ON, MID, OFF).",
- )
-
- # Verbosity
- parser.add_argument("-v", "--verbose", dest="verbose", action="count", default=0)
-
- # Positional arguments
-
- args = parser.parse_args()
-
- # Configure logging
- configure_logging(logger=logger, verbosity=args.verbose)
-
- return args
-
-
- def main():
- """Main function that is called when script directly called."""
- args = parse_args()
- set_led(serial_num=args.serial_num, far_led=args.far_led, near_led=args.near_led)
-
-
- if __name__ == "__main__":
- main()
|