Source code for philander.sysfactory

"""A system convergence layer for smbus, smbus2, periphery or simulative implementation.

The factory class provides implementations for hardware resources like
serial bus or GPIO pins. This unifies the APIs provided by packages
like smbus, smbus2, periphery or gpiozero etc.
"""
__author__ = "Oliver Maye"
__version__ = "0.1"
__all__ = ["SysProvider", "SysFactory" ]

from philander.penum import Enum, unique, auto, idiotypic
#import warnings

from philander.systypes import ErrorCode

[docs] @unique @idiotypic class SysProvider(Enum): """Menmonic designator for a lower-level lib, package or system\ environment to rely the implementation on. """ NONE = auto() """No low-level API available. """ AUTO = auto() """Auto-detect best matching lib/package. """ SIM = auto() """Built-in hardware simulation. """ GPIOZERO = auto() """GPIO zero implementation for raspberry pi (https://gpiozero.readthedocs.io/en/latest/). """ MICROPYTHON = auto() """MicroPython environment (https://docs.micropython.org). """ PERIPHERY = auto() """Python periphery lib (https://pypi.org/project/python-periphery/). """ RPIGPIO = auto() """RaspberryPi GPIO lib (https://pypi.org/project/RPi.GPIO/). """ SMBUS2 = auto() """System Management Bus v2 (SMBUS2) implementation (https://pypi.org/project/smbus2/). """
[docs] class SysFactory(): """As a factory, provide implementations for specific hardware resources. """ @staticmethod def _autoDetectProvider( providers, fallback=SysProvider.NONE): ret = fallback # List of supported libs. # Each entry is a tuple of SysProvider Mnemonics, module name, class name, # such as in (SysProvider.PERIPHERY, "periphery", "I2C") for ent in providers: try: module = __import__( ent[1] ) if hasattr(module, ent[2]): ret = ent[0] break else: # log something pass except ImportError: pass return ret @staticmethod def _createInstance( provider, implementations ): if provider in implementations: moduleName, className = implementations.get( provider ) module = __import__(moduleName, None, None, [className]) cls = getattr( module, className ) ret = cls() else: #raise NotImplementedError('Driver module ' + str(provider) + ' is not supported.') # warnings.warn( # "Cannot find GPIO factory lib. Using SIM. Consider installing RPi.GPIO, gpiozero or periphery!" # ) ret = None return ret
[docs] @staticmethod def getSerialBus( provider=SysProvider.AUTO ): """Generates a serial bus implementation according to the requested provider. :param SysProvider provider: The low-level lib to rely on, or AUTO\ for automatic detection. :return: A serial bus implementation object, or None in case of an error. :rtype: SerialBus """ provs = [(SysProvider.SMBUS2, "smbus2", "SMBus"), (SysProvider.PERIPHERY, "periphery", "I2C"), (SysProvider.MICROPYTHON, "machine", "I2C"), ] impls = { SysProvider.MICROPYTHON: ("philander.serialbus_micropython", "_SerialBus_Micropython"), SysProvider.PERIPHERY: ("philander.serialbus_periphery", "_SerialBus_Periphery"), SysProvider.SIM: ("philander.serialbus_sim", "_SerialBus_Sim"), SysProvider.SMBUS2: ("philander.serialbus_smbus2", "_SerialBus_SMBus2"), } if provider == SysProvider.AUTO: provider = SysFactory._autoDetectProvider( provs, SysProvider.SIM ) ret = SysFactory._createInstance( provider, impls ) return ret
[docs] @staticmethod def getGPIO( provider=SysProvider.AUTO ): """Generates a GPIO implementation according to the requested provider. :param SysProvider provider: The low-level lib to rely on, or AUTO\ for automatic detection. :return: A GPIO implementation object, or None in case of an error. :rtype: GPIO """ provs = [(SysProvider.RPIGPIO, "RPi.GPIO", "GPIO"), (SysProvider.GPIOZERO, "gpiozero", "DigitalOutputDevice"), (SysProvider.PERIPHERY, "periphery", "GPIO"), (SysProvider.MICROPYTHON, "machine", "Pin"), ] impls = { SysProvider.GPIOZERO: ("philander.gpio_zero", "_GPIO_Zero"), SysProvider.MICROPYTHON: ("philander.gpio_micropython", "_GPIO_Micropython"), SysProvider.PERIPHERY: ("philander.gpio_periphery", "_GPIO_Periphery"), SysProvider.RPIGPIO: ("philander.gpio_rpi", "_GPIO_RPi"), SysProvider.SIM: ("philander.gpio_sim", "_GPIO_Sim"), } if provider == SysProvider.AUTO: provider = SysFactory._autoDetectProvider( provs, SysProvider.SIM ) ret = SysFactory._createInstance( provider, impls ) return ret