Blame view

gpio_trigger.py 5.59 KB
Frederik Lindenaar authored
1
2
3
#! /usr/bin/env python

#
Frederik Lindenaar authored
4
# gpio_trigger.py - execute a command when a GPIO input pin changes
Frederik Lindenaar authored
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#
# Version 1.0, latest version, documentation and bugtracker available at:
#		https://gitlab.lindenaar.net/scripts/raspberrypi
#
# Copyright (c) 2019 Frederik Lindenaar
#
# This script is free software: you can redistribute and/or modify it under the
# terms of version 3 of the GNU General Public License as published by the Free
# Software Foundation, or (at your option) any later version of the license.
#
# This script is distributed in the hope that it will be useful but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, visit <http://www.gnu.org/licenses/> to download it.
#

from os import fork, system
from argparse import ArgumentParser
from RPi import GPIO
Frederik Lindenaar authored
27
28
29
30
31
32
parser = ArgumentParser(
    description='Run command when a Raspberry Pi pin changes to high or low.',
    epilog='(*) use \'--\' to stop argument parsing, arguments can contain the '
           'following variables: %PIN%=pin number, %STATE%=value (HIGH or LOW)')
parser.add_argument('-D', '--daemon',  action='store_true',
                    help='run in background (as daemon)')
Frederik Lindenaar authored
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
pgroup = parser.add_mutually_exclusive_group(required=False)
pgroup.add_argument('-P', '--pcb', action='store_const', dest='mode',
                    const=GPIO.BOARD, default=GPIO.BOARD,
                    help='GPIO header/board (PCB) pin numbers (default)')
pgroup.add_argument('-S', '--bcm', help='GPIO BCM mode (Broadcom SOC pins)',
                    action='store_const', dest='mode', const=GPIO.BCM)
parser.add_argument('-p', '--pin', type=int, required=False, default=40,
                    help='GPIO pin number to use (default: 40)')
pgroup = parser.add_mutually_exclusive_group(required=False)
pgroup.add_argument('-u', '--pull-up', action='store_const', dest='pull',
                    default=GPIO.PUD_UP, const=GPIO.PUD_UP,
                    help='internally pull pin up (default)')
pgroup.add_argument('-d', '--pull-down', action='store_const', dest='pull',
                    const=GPIO.PUD_DOWN, help='internally pull pin down')
pgroup.add_argument('-n', '--no-pull', action='store_const', const=GPIO.PUD_OFF,
                    dest='pull', help='don\'t pull pin up or down internally')
pgroup = parser.add_mutually_exclusive_group(required=False)
pgroup.add_argument('-f', '--edge-falling', action='store_const',
                    const=GPIO.FALLING, dest='edge', default=GPIO.FALLING,
                    help='respond to pin going down (default)')
pgroup.add_argument('-r', '--edge-rising', action='store_const', dest='edge',
                    const=GPIO.RISING, help='respond to pin going up')
pgroup.add_argument('-a', '--edge-any', action='store_const', const=GPIO.BOTH,
                    dest='edge', help='respond to any pin change')
parser.add_argument('-b', '--debounce',  type=int, default=200,
                    help='debounce period (in milliseconds, default=200)')
Frederik Lindenaar authored
59
60
61
parser.add_argument('-H', '--hold',  type=int, default=-1,
                    help='optional hold time, pin must be held stable for the '
                    'specified time in milliseconds to trigger cmd')
Frederik Lindenaar authored
62
63
parser.add_argument('-t', '--timeout',  type=int, default=-1,
                    help='optional timeout (in milliseconds) to wait')
Frederik Lindenaar authored
64
65
parser.add_argument('-i', '--ignore-result', action='store_true', default=False,
                    help='ignore command result code (default: exit if <> 0)')
Frederik Lindenaar authored
66
67
68
69
70
71
pgroup = parser.add_mutually_exclusive_group(required=False)
pgroup.add_argument('-c', '--continuous', default=False, action='store_true',
                    help='continously monitor GPIO pin and run cmd upon change')
pgroup.add_argument('-o', '--once', action='store_false', dest='continuous',
                    help='monitor pin and run cmd once, then exit (default)')
parser.add_argument('cmd', help='command to execute when pin goes low')
Frederik Lindenaar authored
72
parser.add_argument('arg', nargs='*', help='argument(s) for the command (*)')
Frederik Lindenaar authored
73
74
75
76
77
78
79
80
81
82

args = parser.parse_args()                              # parse command line
GPIO.setmode(args.mode)                                 # set GPIO number mode
GPIO.setup(args.pin, GPIO.IN, pull_up_down=args.pull)   # setup pin as input

if args.daemon and fork() != 0:                         # Fork for daemon mode
    exit(0)                                             # exit parent process

ret = 0
while args.ignore_result or ret == 0:
Frederik Lindenaar authored
83
    # wait for GPIO pin to be changed in the right direction
Frederik Lindenaar authored
84
85
    if GPIO.wait_for_edge(args.pin, args.edge, bouncetime=args.debounce,
                                                        timeout=args.timeout):
Frederik Lindenaar authored
86
87
88
89
90
91
92
93
94
95
        state = GPIO.input(args.pin)
        # pin changed, if required check if it is stays the same long enough
        if (args.hold < 0) or (
            GPIO.wait_for_edge(args.pin, GPIO.BOTH, bouncetime=args.debounce,
                                    timeout=args.hold - args.debounce) is None):
            ret = system(' '.join([ args.cmd ] + [
                [ 'LOW', 'HIGH' ][state] if arg == '%STATE%' else
                str(args.pin) if arg == '%PIN%' else arg for arg in args.arg]))
            if not args.continuous:                     # exit if running once
                break
Frederik Lindenaar authored
96
    else:                                               # exit if timeout
Frederik Lindenaar authored
97
        ret = -1
Frederik Lindenaar authored
98
99
100
101
102
        break

GPIO.cleanup(args.pin)                                  # cleanup GPIO

exit(ret)                                               # and return the result