This commit is contained in:
2026-03-21 10:53:02 +01:00
parent 3a6c07513c
commit ccfeb6f2c1
1997 changed files with 361936 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
# vim: set fileencoding=utf-8:
#
# GPIO Zero: a library for controlling the Raspberry Pi's GPIO pins
#
# Copyright (c) 2021-2024 Dave Jones <dave@waveform.org.uk>
#
# SPDX-License-Identifier: BSD-3-Clause
import os
import sys
import argparse
# Remove the try clause when 3.7 support is no longer trivial
try:
from importlib_metadata import version
except ImportError:
from importlib.metadata import version
class CliTool:
"""
Base class for simple command line utilities.
The doc-string of the class forms the basis for the utility's help text.
Instances are constructed with a :attr:`parser` which you can customize.
The :meth:`main` method will be called with the parsed command line
arguments and should return an appropriate exit code.
"""
def __init__(self):
self.parser = argparse.ArgumentParser(description=self.__class__.__doc__)
self.parser.add_argument(
'--version',
action='version',
version=version('gpiozero'))
def get_formatter(self):
return self.parser._get_formatter()
def get_gpiozero_help(self):
fmt = self.get_formatter()
fmt.add_text(
"""
Unable to initialize GPIO Zero. This usually means that you are not
running %(prog)s on a Raspberry Pi. If you still wish to run
%(prog)s, set the GPIOZERO_PIN_FACTORY environment variable to
'mock' and retry, or refer to the Remote GPIO section of the
manual* to configure your environment to remotely access your
Pi.
""")
fmt.add_text(
"* https://gpiozero.readthedocs.io/en/stable/remote_gpio.html")
return fmt.format_help()
def __call__(self, args=None):
if args is None:
args = sys.argv[1:]
try:
return self.main(self.parser.parse_args(args)) or 0
except argparse.ArgumentError as e:
# argparse errors are already nicely formatted, print to stderr and
# exit with code 2
raise e
except Exception as e:
# Output anything else nicely formatted on stderr and exit code 1
if int(os.environ.get('DEBUG', '0')):
raise
self.parser.exit(1, f'{self.parser.prog}: error: {e}\n')
def main(self, args):
raise NotImplementedError

View File

@@ -0,0 +1,82 @@
# vim: set fileencoding=utf-8:
#
# GPIO Zero: a library for controlling the Raspberry Pi's GPIO pins
#
# Copyright (c) 2017-2023 Dave Jones <dave@waveform.org.uk>
# Copyright (c) 2017 Ben Nuttall <ben@bennuttall.com>
#
# SPDX-License-Identifier: BSD-3-Clause
import argparse
import sys
import warnings
import webbrowser
from . import CliTool
from gpiozero import Device
from gpiozero.pins.pi import PiBoardInfo
from gpiozero.pins.style import Style
class PinoutTool(CliTool):
"""
A utility for querying GPIO pin-out information.
"""
def __init__(self):
super().__init__()
self.parser.add_argument(
'-r', '--revision',
dest='revision',
type=lambda s: int(s, base=16),
default=None,
help='Board revision. Default is to autodetect revision of '
'current device')
self.parser.add_argument(
'-c', '--color',
action="store_true",
default=None,
help='Force colored output (by default, the output will include '
'ANSI color codes if run in a color-capable terminal). See also '
'--monochrome')
self.parser.add_argument(
'-m', '--monochrome',
dest='color',
action='store_false',
help='Force monochrome output. See also --color')
self.parser.add_argument(
'-x', '--xyz',
dest='xyz',
action='store_true',
help='Open pinout.xyz in the default web browser')
def main(self, args):
warnings.simplefilter('ignore')
if args.xyz:
webbrowser.open('https://pinout.xyz')
else:
if args.revision is None:
try:
Device.ensure_pin_factory()
board_info = Device.pin_factory.board_info
except ImportError:
sys.stderr.write(self.get_gpiozero_help())
return 1
except IOError:
sys.stderr.write('Unrecognized board')
return 1
else:
board_info = PiBoardInfo.from_revision(args.revision)
style = Style(color=args.color)
sys.stdout.write(f'{board_info:{style} full}')
formatter = self.get_formatter()
formatter.add_text(
"For further information, please refer to "
"https://pinout.xyz/")
sys.stdout.write('\n\n')
sys.stdout.write(formatter.format_help())
def output(self, board):
return
main = PinoutTool()

View File

@@ -0,0 +1,154 @@
# vim: set fileencoding=utf-8:
#
# GPIO Zero: a library for controlling the Raspberry Pi's GPIO pins
#
# Copyright (c) 2021-2023 Dave Jones <dave@waveform.org.uk>
#
# SPDX-License-Identifier: BSD-3-Clause
import argparse
import sys
import warnings
from . import CliTool
from gpiozero import Device
from gpiozero.pins.pi import PiBoardInfo
class PintestTool(CliTool):
"""
A utility for testing the GPIO pins on a Raspberry Pi, inspired by pigpio's
gpiotest example script, and wiringPi's pintest utility.
"""
def __init__(self):
super().__init__()
self.parser.add_argument(
'-p', '--pins',
dest='pins', default='',
help="The pin(s) to test. Can be specified as a comma-separated "
"list of pins. Pin numbers can be given in any form accepted by "
"gpiozero, e.g. 14, GPIO14, BOARD8. The default is to test all "
"pins")
self.parser.add_argument(
'-s', '--skip',
dest='skip', default='',
help="The pin(s) to skip testing. Can be specified as comma-"
"separated list of pins. Pin numbers can be given in any form "
"accepted by gpiozero, e.g. 14, GPIO14, BOARD8. The default is "
"to skip no pins")
self.parser.add_argument(
'-y', '--yes',
dest='prompt', action='store_false',
help="Proceed without prompting")
self.parser.add_argument(
'-r', '--revision',
dest='revision', type=lambda s: int(s, base=16), default=None,
help="Force board revision. Default is to autodetect revision of "
"current device. You should avoid this option unless you are "
"very sure the detection is incorrect")
def main(self, args):
if args.revision is None:
try:
Device.ensure_pin_factory()
board_info = Device.pin_factory.board_info
except ImportError:
sys.stderr.write(self.get_gpiozero_help())
return 1
except IOError:
sys.stderr.write('Unrecognized board')
return 1
pins = self.get_pins(
board_info,
include=args.pins.split(',') if args.pins else (),
exclude=args.skip.split(',') if args.skip else ())
fmt = self.get_formatter()
fmt.add_text(
f"""
This program checks the board's user-accessible GPIO pins. The
board's model is: {board_info.description}. The following pins are
selected for testing:
""")
fmt.add_text(', '.join(pin.name for pin in pins))
fmt.add_text(
"""
Please ensure that nothing is connected to any of the pins listed
above for the test duration.
""")
print(fmt.format_help())
if args.prompt:
s = input('Proceed with test? [y/N] ').strip().lower()
if s != 'y':
return 2
failed = []
for pin in pins:
try:
print(f'Testing {pin.name}...', end='')
self.test_pin(pin)
except ValueError as e:
print(e)
failed.append(pin)
else:
print('ok')
return 1 if failed else 0
def get_pins(self, board, include, exclude):
if not include:
pins = {
pin
for header in board.headers.values()
for pin in header.pins.values()
if 'gpio' in pin.interfaces
}
else:
pins = {
pin
for name in include
for header, pin in board.find_pin(name)
}
skip = {
pin
for name in exclude
for header, pin in board.find_pin(name)
}
pins -= skip
for pin in pins:
if 'gpio' not in pin.interfaces:
raise ValueError(f'{pin.spec} is not a GPIO pin')
return pins
def test_pin(self, pin_info):
with Device.pin_factory.pin(pin_info.name) as pin:
save_function = pin.function
save_state = pin.state
try:
pin.function = 'output'
pin.state = 0
if pin.state != 0:
raise ValueError(f'Write 0 to {pin_info.function} failed')
pin.state = 1
if pin.state != 1:
raise ValueError(f'Write 1 to {pin_info.function} failed')
pin.function = 'input'
if pin_info.pull != 'up':
pin.pull = 'down'
if pin.state != 0:
raise ValueError(
f'Pull down on {pin_info.function} failed')
if pin_info.pull != 'down':
pin.pull = 'up'
if pin.state != 1:
raise ValueError(
f'Pull up on {pin_info.function} failed')
if pin_info.pull == '':
pin.pull = 'floating'
finally:
pin.function = save_function
if save_function == 'output':
pin.state = save_state
main = PintestTool()