2019-11-01 10:34:57 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""buttond.py: Watch a Rasberry Pi GPIO button. Exec Hog4 comment macros."""
|
|
|
|
|
|
|
|
__author__ = "Kevin Matz"
|
|
|
|
__copyright__ = "Copyright 2019, Company 235, LLC"
|
|
|
|
__credits__ = ["Kevin Matz"]
|
|
|
|
|
|
|
|
__license__ = "MIT"
|
2022-05-12 23:32:09 -04:00
|
|
|
__version__ = "1.1"
|
2019-11-01 10:34:57 -04:00
|
|
|
__maintainer__ = "Kevin Matz"
|
|
|
|
__email__ = "kevin@company235.com"
|
|
|
|
|
|
|
|
__status__ = "Prototype"
|
|
|
|
|
2022-05-12 23:27:25 -04:00
|
|
|
import argparse
|
2019-11-01 10:34:57 -04:00
|
|
|
import configparser
|
2022-05-12 19:53:40 -04:00
|
|
|
import logging
|
2019-11-01 10:34:57 -04:00
|
|
|
from signal import pause
|
2022-05-12 23:31:38 -04:00
|
|
|
from baconscript import comment, HogNet, LISTENER, load_servers
|
2022-05-12 18:46:33 -04:00
|
|
|
from gpiozero import Button, GPIODeviceError
|
2019-11-01 10:34:57 -04:00
|
|
|
|
|
|
|
# use mock pins when not working on Pi hardware
|
|
|
|
# from gpiozero.pins.mock import MockFactory
|
|
|
|
# from gpiozero import Device
|
|
|
|
# Device.pin_factory = MockFactory()
|
|
|
|
|
2022-05-12 19:53:40 -04:00
|
|
|
log = logging.getLogger(__name__)
|
2019-11-03 20:41:50 -05:00
|
|
|
|
2022-05-12 23:25:14 -04:00
|
|
|
|
|
|
|
def main():
|
|
|
|
"""Entry point for direct execution."""
|
2022-05-12 23:27:25 -04:00
|
|
|
## parse the command line
|
|
|
|
args = get_command_arguments()
|
|
|
|
## configure logging
|
|
|
|
log_levels = {
|
|
|
|
0: logging.CRITICAL,
|
|
|
|
1: logging.ERROR,
|
|
|
|
2: logging.WARN,
|
|
|
|
3: logging.INFO,
|
|
|
|
4: logging.DEBUG,
|
|
|
|
}
|
|
|
|
if args.verbosity is None:
|
|
|
|
args.verbosity = 0 if args.quiet else 3
|
|
|
|
logging.basicConfig(level=log_levels.get(args.verbosity, logging.DEBUG))
|
|
|
|
## output header
|
|
|
|
print(f"Version: {__version__}\t{__copyright__}")
|
2022-05-12 23:30:24 -04:00
|
|
|
## load config files
|
2022-05-12 23:31:38 -04:00
|
|
|
LISTENER.osc = HogNet(load_servers(args.servers))
|
2022-05-12 23:30:24 -04:00
|
|
|
load_config(args.buttons)
|
2022-05-12 23:25:14 -04:00
|
|
|
## run the event loop
|
|
|
|
try:
|
|
|
|
pause()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
2022-05-12 23:27:25 -04:00
|
|
|
def get_command_arguments():
|
|
|
|
"""Parse the command line arguments."""
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description='Exec Hog4 comment macros on RasPi GPIO activity.',
|
|
|
|
epilog=__copyright__)
|
2022-05-12 23:30:24 -04:00
|
|
|
parser.add_argument('-b', '--buttons', default="buttons.cfg",
|
|
|
|
help="button configuration file")
|
2022-05-12 23:31:38 -04:00
|
|
|
parser.add_argument('-s', '--servers', default="server.cfg",
|
|
|
|
help="OSC servers configuration file")
|
2022-05-12 23:27:25 -04:00
|
|
|
parser.add_argument('-q', '--quiet', action='store_true',
|
|
|
|
help="sets the default log level to 0, otherwise 3.")
|
|
|
|
parser.add_argument("-v", dest="verbosity",
|
|
|
|
action="count", default=None,
|
|
|
|
help="verbosity (between 1-4 with more printing more "
|
|
|
|
" verbose logging). "
|
|
|
|
"CRITICAL=0, ERROR=1, WARN=2, INFO=3, DEBUG=4")
|
|
|
|
parser.add_argument('--version', action='version',
|
|
|
|
version=f'%(prog)s {__version__}')
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
|
|
|
2022-05-12 23:30:24 -04:00
|
|
|
def load_config(file):
|
|
|
|
"""Load a configuration file."""
|
|
|
|
config = configparser.ConfigParser(allow_no_value=True)
|
|
|
|
log.debug("Loading config from %s", file)
|
|
|
|
config.read(file)
|
|
|
|
# set up each buttons
|
|
|
|
for button in config.get('button', 'names').split(','):
|
|
|
|
try:
|
|
|
|
# move to config section
|
|
|
|
cfg = config[button]
|
|
|
|
# read from settings
|
|
|
|
pin = cfg.get('pin', None)
|
|
|
|
closed = cfg.get('close', None)
|
|
|
|
opened = cfg.get('open', None)
|
|
|
|
# set up button on pin
|
|
|
|
log.debug('init %s on GPIO %s', button, pin)
|
|
|
|
_buttons[button] = Button(pin)
|
|
|
|
# connect button callbacks to anonymous functions
|
|
|
|
log.info('connecting %s "closed" to macro %s', button, closed)
|
|
|
|
_buttons[button].when_pressed = lambda macro=closed: activate(macro)
|
|
|
|
log.info('connecting %s "opened" to macro %s', button, opened)
|
|
|
|
_buttons[button].when_released = lambda macro=opened: activate(macro)
|
|
|
|
except (KeyError, GPIODeviceError) as error:
|
|
|
|
log.error('Error configuring button %s: %s', button, error)
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
2022-05-12 23:23:46 -04:00
|
|
|
def activate(macro):
|
|
|
|
"""Sanitize user configured macros."""
|
2019-11-17 10:58:21 -05:00
|
|
|
if macro is None:
|
2019-11-03 20:42:23 -05:00
|
|
|
return
|
2019-11-17 10:58:21 -05:00
|
|
|
macro = macro.strip('\"').upper()
|
2022-05-12 18:46:53 -04:00
|
|
|
if macro == "":
|
2019-11-03 20:42:23 -05:00
|
|
|
return
|
2019-11-17 11:10:48 -05:00
|
|
|
# pass macro to baconscript
|
2022-05-12 23:30:57 -04:00
|
|
|
log.debug("doing macro %s", macro)
|
2019-11-17 10:58:21 -05:00
|
|
|
comment(macro)
|
2019-11-03 20:41:50 -05:00
|
|
|
|
|
|
|
|
2019-11-01 10:34:57 -04:00
|
|
|
# empty button directory
|
|
|
|
_buttons = {}
|
|
|
|
|
2019-11-17 11:10:48 -05:00
|
|
|
|
|
|
|
# when run directly, sleep until button signal or KeyboardInterrupt
|
2019-11-01 10:34:57 -04:00
|
|
|
if __name__ == '__main__':
|
2022-05-12 23:25:14 -04:00
|
|
|
main()
|
2019-11-17 11:11:37 -05:00
|
|
|
else:
|
|
|
|
# indicate prefered method of sleeping when laoded as a module
|
2022-05-12 19:53:40 -04:00
|
|
|
log.debug('call signal.pause() instead of time.sleep()')
|