Compare commits

...

2 Commits

Author SHA1 Message Date
Andrea Mistrali 68eebf2a83 Merge pull request 'Improvements' (#1) from thread into master
Reviewed-on: #1
2024-06-17 10:07:44 +00:00
Andrea Mistrali e1f3783ed0
Improvements
No more docopt dependency, switched to argparse.
Some extra cleanups
2024-06-17 12:06:04 +02:00
5 changed files with 129 additions and 39 deletions

19
poetry.lock generated
View File

@ -1,16 +1,21 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]] [[package]]
name = "docopt" name = "rpi-gpio"
version = "0.6.2" version = "0.7.1"
description = "Pythonic argument parser, that will make you smile" description = "A module to control Raspberry Pi GPIO channels"
optional = false optional = false
python-versions = "*" python-versions = "*"
files = [ files = [
{file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, {file = "RPi.GPIO-0.7.1-cp27-cp27mu-linux_armv6l.whl", hash = "sha256:b86b66dc02faa5461b443a1e1f0c1d209d64ab5229696f32fb3b0215e0600c8c"},
{file = "RPi.GPIO-0.7.1-cp310-cp310-linux_armv6l.whl", hash = "sha256:57b6c044ef5375a78c8dda27cdfadf329e76aa6943cd6cffbbbd345a9adf9ca5"},
{file = "RPi.GPIO-0.7.1-cp37-cp37m-linux_armv6l.whl", hash = "sha256:77afb817b81331ce3049a4b8f94a85e41b7c404d8e56b61ac0f1eb75c3120868"},
{file = "RPi.GPIO-0.7.1-cp38-cp38-linux_armv6l.whl", hash = "sha256:29226823da8b5ccb9001d795a944f2e00924eeae583490f0bc7317581172c624"},
{file = "RPi.GPIO-0.7.1-cp39-cp39-linux_armv6l.whl", hash = "sha256:15311d3b063b71dee738cd26570effc9985a952454d162937c34e08c0fc99902"},
{file = "RPi.GPIO-0.7.1.tar.gz", hash = "sha256:cd61c4b03c37b62bba4a5acfea9862749c33c618e0295e7e90aa4713fb373b70"},
] ]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.11" python-versions = ">=3.9,<4.0"
content-hash = "020d3e03335e70ca8b1cfd769838e50546a63b9ed4e4034ba584fd3a3ec497fd" content-hash = "5b3b5679f5c6b9e375be39f892efbaabceb43d1d7a346c78386ad876cfa286be"

View File

@ -16,62 +16,61 @@ Options:
-M --max=<max> Maximum value [default: 50] -M --max=<max> Maximum value [default: 50]
-D --delay-val=<delay> Base delay value [default: 0.01] -D --delay-val=<delay> Base delay value [default: 0.01]
-V --verbose Verbose mode [default: True] -V --verbose Verbose mode [default: False]
-h --help Show help. -h --help Show help.
-v --version Show version. -v --version Show version.
""" # NOQA """ # NOQA
import sys import sys
import time import time
import logging import logging
import signal import signal
from docopt import docopt # from docopt import docopt
from pulses.cli_parser import parser
from pulses import VERSION, ledPulse from pulses import VERSION, ledPulse
logging.basicConfig(format="%(asctime)-15s %(levelname)5s %(name)s[%(process)d] %(threadName)s: %(message)s") logging.basicConfig(
format="%(asctime)-15s %(levelname)5s %(name)s[%(process)d] %(threadName)s: %(message)s")
def signal_handler(sig, frame):
print('stopping pulse...', end="", flush=True)
led.stop()
led.join()
print('done.\nBailing out')
sys.exit(0)
def main(): def main():
global led def signal_handler(sig: int, frame):
print('stopping pulse...', end="", flush=True)
led.stop()
led.join()
print('done.\nBailing out')
sys.exit(0)
args = docopt(__doc__, version=f'pulses {VERSION}') args = parser.parse_args()
signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGINT, signal_handler)
log = logging.getLogger() log = logging.getLogger()
log.setLevel('WARNING') log.setLevel('WARNING')
if args.get('--verbose'): if args.verbose:
log.setLevel('DEBUG') log.setLevel('DEBUG')
log.info('setting verbose mode') log.info('setting verbose mode')
led = ledPulse(int(args.get('--gpio'))) led = ledPulse(int(args.gpio))
params = {} params = {}
for method in ['initial', 'loop', 'final']: for method in ['initial', 'loop', 'final']:
methodName = args.get(f"--{method}") methodName = getattr(args, method)
if methodName not in led.valueMethods: if methodName not in led.valueMethods:
print(f"error: no value method '{methodName}' defined") print(f"error: no value method '{methodName}' defined")
sys.exit(1) sys.exit(1)
params[f"{method}Method"] = methodName params[f"{method}Method"] = methodName
methodName = args.get("--delay") methodName = args.delay
if methodName not in led.delayMethods: if methodName not in led.delayMethods:
print(f"error: no delay method '{methodName}' defined") print(f"error: no delay method '{methodName}' defined")
sys.exit(1) sys.exit(1)
params['delayMethod'] = methodName params['delayMethod'] = methodName
params['min'] = int(args.get('--min')) params['min'] = args.min
params['max'] = int(args.get('--max')) params['max'] = args.max
params['delay'] = float(args.get('--delay-val')) params['delay'] = args.delay_val
print("-" * 20) print("-" * 20)
print("pulses CLI test tool") print("pulses CLI test tool")

78
pulses/cli_parser.py Normal file
View File

@ -0,0 +1,78 @@
"""
Usage:
pulses [--gpio <gpio>] [--initial <initialMethod>] [--loop <loopMethod>]
[--final <finalMethod>] [--delay <delayMethod>]
[--min <min>] [--max <max>] [--delay-val <delay>]
[--verbose]
Options:
-g --gpio=<gpio> GPIO to use [default: 12]
-i --initial=<method> Initial method [default: linear]
-l --loop=<method> Loop method [default: sin]
-f --final=<method> Final method [default: linear]
-d --delay=<method> Delay method [default: constant]
-m --min=<min> Minimum value [default: 2]
-M --max=<max> Maximum value [default: 50]
-D --delay-val=<delay> Base delay value [default: 0.01]
-V --verbose Verbose mode [default: True]
-h --help Show help.
-v --version Show version.
""" # NOQA
import argparse
from pulses import VERSION
epilogue = """
"""
class Formatter(argparse.RawDescriptionHelpFormatter,
argparse.ArgumentDefaultsHelpFormatter):
"""
We want to show the default values and show the description
and epilogue not reformatted, so we create our own formatter class
"""
pass
parser = argparse.ArgumentParser(prog="pulses",
description="Pulse your LED(s)",
epilog=epilogue,
formatter_class=Formatter)
parser.add_argument('-g', '--gpio', type=int, default=12,
metavar="<gpio>",
help="GPIO to use")
parser.add_argument('-i', '--initial', type=str, default='linear',
metavar="<initial method>",
help="Initial method")
parser.add_argument('-l', '--loop', type=str, default='sin',
metavar="<loop method>",
help="Loop method")
parser.add_argument('-f', '--final', type=str, default='linear',
metavar="<final method>",
help="Final method")
parser.add_argument('-d', '--delay', type=str, default='constant',
metavar="<delay method>",
help="Delay method")
parser.add_argument('-m', '--min', type=int, default=2,
metavar="<min>",
help="Minimum value")
parser.add_argument('-M', '--max', type=int, default=50,
metavar="<max>",
help="Max value")
parser.add_argument('-D', '--delay-val', type=float, default=0.01,
metavar="<delay value>",
help="Base delay value")
parser.add_argument('-V', '--verbose', action='store_true', default=False,
help="Verbose mode")
parser.add_argument('--version', action='version',
version=f'%(prog)s {VERSION}')

View File

@ -4,16 +4,17 @@ import time
import threading import threading
from queue import Queue from queue import Queue
from typing import Callable
from .methods import * # NOQA from .methods import * # NOQA
class ledPulse(threading.Thread): class ledPulse(threading.Thread):
delayMethods = ['constant', 'sin', 'cos'] delayMethods: list = ['constant', 'sin', 'cos']
valueMethods = ['on', 'off', 'linear', 'vshape', 'sin', 'cos'] valueMethods: list = ['on', 'off', 'linear', 'vshape', 'sin', 'cos']
methods = {'delay': {}, 'value': {}} methods: dict = {'delay': {}, 'value': {}}
defaultSet = { defaultSet: dict = {
'min': 2, 'min': 2,
'max': 50, 'max': 50,
'delay': 0.01, 'delay': 0.01,
@ -22,8 +23,15 @@ class ledPulse(threading.Thread):
'loopMethod': 'linear', 'loopMethod': 'linear',
'finalMethod': None 'finalMethod': None
} }
initialMethod: str
loopMethod: str
finalMethod: str
delayMethod: str
min: int
max: int
delay: float
def __init__(self, gpio, name="led0"): def __init__(self, gpio: int, name: str = "led0") -> None:
super().__init__(name=name, super().__init__(name=name,
daemon=True) daemon=True)
@ -69,7 +77,7 @@ class ledPulse(threading.Thread):
self.model = sys.platform self.model = sys.platform
try: try:
with open('/sys/firmware/devicetree/base/model', 'r') as m: with open('/sys/firmware/devicetree/base/model', 'r') as m:
model = m.read().strip() model = m.read()[:-1]
if model.lower().startswith('raspberry pi'): if model.lower().startswith('raspberry pi'):
self.supported = True self.supported = True
self.model = model self.model = model
@ -97,7 +105,7 @@ class ledPulse(threading.Thread):
return (self.supported, sys.platform) return (self.supported, sys.platform)
def set(self, **kwargs): def set(self, **kwargs: dict):
for key, value in kwargs.items(): for key, value in kwargs.items():
if key in self.defaultSet.keys(): if key in self.defaultSet.keys():
@ -198,13 +206,13 @@ class ledPulse(threading.Thread):
# in the loop we are and is added as a method to self, so # in the loop we are and is added as a method to self, so
# it has access to all the properties of self: max, min, delay # it has access to all the properties of self: max, min, delay
### ###
def register_value_method(self, name, fn): def register_value_method(self, name: str, fn: Callable):
self.register_method('value', name, fn) self.register_method('value', name, fn)
def register_delay_method(self, name, fn): def register_delay_method(self, name: str, fn: Callable):
self.register_method('delay', name, fn) self.register_method('delay', name, fn)
def register_method(self, kind, name, fn): def register_method(self, kind: str, name: str, fn: Callable):
if kind not in ['delay', 'value']: if kind not in ['delay', 'value']:
self.log.warning(f"unknown kind {kind}") self.log.warning(f"unknown kind {kind}")
return return

View File

@ -7,7 +7,7 @@ readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.9,<4.0" python = ">=3.9,<4.0"
docopt = "^0.6.2" rpi-gpio = {version = "^0.7.1", platform = "linux"}
[tool.poetry.scripts] [tool.poetry.scripts]
pulses = "pulses.cli:main" pulses = "pulses.cli:main"