From 6fb5f1c5b2c38a1d0447f4882832843c67f6a892 Mon Sep 17 00:00:00 2001 From: Fan Deng Date: Mon, 26 Jun 2017 17:21:33 -0700 Subject: [PATCH 1/4] Add AIY common drivers. This change includes two common drivers: 1) Button - A GPIO-based button driver that automatically debounces the GPIO signal. 2) LED - A GPIO- and PWM-based LED driver that supports a set of simple LED patterns. Tested: Manually tested on a RPi3 + VoiceHat. --- src/aiy/__init__.py | 0 src/aiy/common.py | 223 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 src/aiy/__init__.py create mode 100644 src/aiy/common.py diff --git a/src/aiy/__init__.py b/src/aiy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/aiy/common.py b/src/aiy/common.py new file mode 100644 index 00000000..e5a12142 --- /dev/null +++ b/src/aiy/common.py @@ -0,0 +1,223 @@ +# Copyright 2017 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This library provides common drivers for the AIY projects. + +Drivers in this module requires GPIO.setmode(GPIO.BCM). +""" + +import itertools +import os +import threading +import time + +import RPi.GPIO as GPIO + + +class Button(object): + """Detect edges on the given GPIO channel.""" + + def __init__(self, + channel, + polarity=GPIO.FALLING, + pull_up_down=GPIO.PUD_UP, + debounce_time=0.15): + """A simple GPIO-based button driver. + + This driver supports a simple GPIO-based button. It works by detecting edges + on the given GPIO channel. Debouncing is automatic. + + Args: + channel: the GPIO pin number to use (BCM mode) + polarity: the GPIO polarity to detect; either GPIO.FALLING or GPIO.RISING. + pull_up_down: whether the port should be pulled up or down; defaults to + GPIO.PUD_UP. + debounce_time: the time used in debouncing the button in seconds. + """ + + if polarity not in [GPIO.FALLING, GPIO.RISING]: + raise ValueError('polarity must be one of: GPIO.FALLING or GPIO.RISING') + + self.channel = int(channel) + self.polarity = polarity + self.expected_value = polarity == GPIO.RISING + self.debounce_time = debounce_time + + GPIO.setup(channel, GPIO.IN, pull_up_down=pull_up_down) + + self.callback = None + + def wait_for_press(self): + """Waits for the button to be pressed. + + This method blocks until the button is pressed. + """ + GPIO.add_event_detect(self.channel, self.polarity) + while True: + if GPIO.event_detected(self.channel) and self._debounce(): + GPIO.remove_event_detect(self.channel) + return + else: + time.sleep(0.1) + + def on_press(self, callback): + """Calls the callback whenever the button is pressed. + + Args: + callback: a function to call whenever the button is pressed. It should + take a single channel number. + + Example: + def MyButtonPressHandler(channel): + print "button pressed: channel = %d" % channel + my_button.on_press(MyButtonPressHandler) + """ + GPIO.remove_event_detect(self.channel) + self.callback = callback + GPIO.add_event_detect( + self.channel, self.polarity, callback=self._debounce_and_callback) + + def _debounce_and_callback(self, _): + if self._debounce(): + self.callback() + + def _debounce(self): + """Check that the input holds the expected value for the debounce period, + to avoid false trigger on short pulses.""" + start = time.time() + while time.time() < start + self.debounce_time: + if GPIO.input(self.channel) != self.expected_value: + return False + time.sleep(0.01) + return True + + +class LED: + """Starts a background thread to show patterns with the LED. + + Simple usage: + my_led = LED(channel = 25) + my_led.start() + my_led.set_state(LED_BEACON) + my_led.stop() + """ + + LED_OFF = 0 + LED_ON = 1 + LED_BLINK = 2 + LED_BLINK_3 = 3 + LED_BEACON = 4 + LED_BEACON_DARK = 5 + LED_DECAY = 6 + LED_PULSE_SLOW = 7 + LED_PULSE_QUICK = 8 + + def __init__(self, channel): + self.animator = threading.Thread(target=self._animate) + self.channel = channel + self.iterator = None + self.running = False + self.state = None + self.sleep = 0 + + GPIO.setup(channel, GPIO.OUT) + self.pwm = GPIO.PWM(channel, 100) + + self.lock = threading.Lock() + + def start(self): + """Starts the LED driver.""" + with self.lock: + if not self.running: + self.running = True + self.pwm.start(0) # off by default + self.animator.start() + + def stop(self): + """Stops the LED driver and sets the LED to off.""" + with self.lock: + if self.running: + self.running = False + self.animator.join() + self.pwm.stop() + + def set_state(self, state): + """Sets the LED driver's new state. + + Note the LED driver must be started for this to have any effect. + """ + with self.lock: + self.state = state + + def _animate(self): + while True: + state = None + running = False + with self.lock: + state = self.state + self.state = None + running = self.running + if not running: + return + if state: + if not self._parse_state(state): + print('unsupported state: %d' % state) + if self.iterator: + self.pwm.ChangeDutyCycle(next(self.iterator)) + time.sleep(self.sleep) + else: + # We can also wait for a state change here with a Condition. + time.sleep(1) + + def _parse_state(self, state): + self.iterator = None + self.sleep = 0.0 + if state == self.LED_OFF: + self.pwm.ChangeDutyCycle(0) + return True + if state == self.LED_ON: + self.pwm.ChangeDutyCycle(100) + return True + if state == self.LED_BLINK: + self.iterator = itertools.cycle([0, 100]) + self.sleep = 0.5 + return True + if state == self.LED_BLINK_3: + self.iterator = itertools.cycle([0, 100] * 3 + [0, 0]) + self.sleep = 0.25 + return True + if state == self.LED_BEACON: + self.iterator = itertools.cycle( + itertools.chain([30] * 100, [100] * 8, range(100, 30, -5))) + self.sleep = 0.05 + return True + if state == self.LED_BEACON_DARK: + self.iterator = itertools.cycle( + itertools.chain([0] * 100, range(0, 30, 3), range(30, 0, -3))) + self.sleep = 0.05 + return True + if state == self.LED_DECAY: + self.iterator = itertools.cycle(range(100, 0, -2)) + self.sleep = 0.05 + return True + if state == self.LED_PULSE_SLOW: + self.iterator = itertools.cycle( + itertools.chain(range(0, 100, 2), range(100, 0, -2))) + self.sleep = 0.1 + return True + if state == self.LED_PULSE_QUICK: + self.iterator = itertools.cycle( + itertools.chain(range(0, 100, 5), range(100, 0, -5))) + self.sleep = 0.05 + return True + return False From 73ab0e46b42b187f9334745b57e684601b755c12 Mon Sep 17 00:00:00 2001 From: Fan Deng Date: Mon, 26 Jun 2017 17:50:24 -0700 Subject: [PATCH 2/4] Reformat common.py to pass PEP8 style checks. --- src/aiy/common.py | 309 +++++++++++++++++++++++----------------------- 1 file changed, 157 insertions(+), 152 deletions(-) diff --git a/src/aiy/common.py b/src/aiy/common.py index e5a12142..abb0637e 100644 --- a/src/aiy/common.py +++ b/src/aiy/common.py @@ -25,53 +25,55 @@ class Button(object): - """Detect edges on the given GPIO channel.""" + """Detect edges on the given GPIO channel.""" - def __init__(self, - channel, - polarity=GPIO.FALLING, - pull_up_down=GPIO.PUD_UP, - debounce_time=0.15): - """A simple GPIO-based button driver. + def __init__(self, + channel, + polarity=GPIO.FALLING, + pull_up_down=GPIO.PUD_UP, + debounce_time=0.15): + """A simple GPIO-based button driver. - This driver supports a simple GPIO-based button. It works by detecting edges - on the given GPIO channel. Debouncing is automatic. + This driver supports a simple GPIO-based button. It works by detecting + edges on the given GPIO channel. Debouncing is automatic. Args: channel: the GPIO pin number to use (BCM mode) - polarity: the GPIO polarity to detect; either GPIO.FALLING or GPIO.RISING. + polarity: the GPIO polarity to detect; either GPIO.FALLING or + GPIO.RISING. pull_up_down: whether the port should be pulled up or down; defaults to GPIO.PUD_UP. debounce_time: the time used in debouncing the button in seconds. """ - if polarity not in [GPIO.FALLING, GPIO.RISING]: - raise ValueError('polarity must be one of: GPIO.FALLING or GPIO.RISING') + if polarity not in [GPIO.FALLING, GPIO.RISING]: + raise ValueError( + 'polarity must be one of: GPIO.FALLING or GPIO.RISING') - self.channel = int(channel) - self.polarity = polarity - self.expected_value = polarity == GPIO.RISING - self.debounce_time = debounce_time + self.channel = int(channel) + self.polarity = polarity + self.expected_value = polarity == GPIO.RISING + self.debounce_time = debounce_time - GPIO.setup(channel, GPIO.IN, pull_up_down=pull_up_down) + GPIO.setup(channel, GPIO.IN, pull_up_down=pull_up_down) - self.callback = None + self.callback = None - def wait_for_press(self): - """Waits for the button to be pressed. + def wait_for_press(self): + """Waits for the button to be pressed. This method blocks until the button is pressed. """ - GPIO.add_event_detect(self.channel, self.polarity) - while True: - if GPIO.event_detected(self.channel) and self._debounce(): - GPIO.remove_event_detect(self.channel) - return - else: - time.sleep(0.1) + GPIO.add_event_detect(self.channel, self.polarity) + while True: + if GPIO.event_detected(self.channel) and self._debounce(): + GPIO.remove_event_detect(self.channel) + return + else: + time.sleep(0.1) - def on_press(self, callback): - """Calls the callback whenever the button is pressed. + def on_press(self, callback): + """Calls the callback whenever the button is pressed. Args: callback: a function to call whenever the button is pressed. It should @@ -82,28 +84,31 @@ def MyButtonPressHandler(channel): print "button pressed: channel = %d" % channel my_button.on_press(MyButtonPressHandler) """ - GPIO.remove_event_detect(self.channel) - self.callback = callback - GPIO.add_event_detect( - self.channel, self.polarity, callback=self._debounce_and_callback) - - def _debounce_and_callback(self, _): - if self._debounce(): - self.callback() - - def _debounce(self): - """Check that the input holds the expected value for the debounce period, - to avoid false trigger on short pulses.""" - start = time.time() - while time.time() < start + self.debounce_time: - if GPIO.input(self.channel) != self.expected_value: - return False - time.sleep(0.01) - return True + GPIO.remove_event_detect(self.channel) + self.callback = callback + GPIO.add_event_detect( + self.channel, self.polarity, callback=self._debounce_and_callback) + + def _debounce_and_callback(self, _): + if self._debounce(): + self.callback() + + def _debounce(self): + """Debounces the GPIO signal. + + Check that the input holds the expected value for the debounce + period, to avoid false trigger on short pulses. + """ + start = time.time() + while time.time() < start + self.debounce_time: + if GPIO.input(self.channel) != self.expected_value: + return False + time.sleep(0.01) + return True class LED: - """Starts a background thread to show patterns with the LED. + """Starts a background thread to show patterns with the LED. Simple usage: my_led = LED(channel = 25) @@ -112,112 +117,112 @@ class LED: my_led.stop() """ - LED_OFF = 0 - LED_ON = 1 - LED_BLINK = 2 - LED_BLINK_3 = 3 - LED_BEACON = 4 - LED_BEACON_DARK = 5 - LED_DECAY = 6 - LED_PULSE_SLOW = 7 - LED_PULSE_QUICK = 8 - - def __init__(self, channel): - self.animator = threading.Thread(target=self._animate) - self.channel = channel - self.iterator = None - self.running = False - self.state = None - self.sleep = 0 - - GPIO.setup(channel, GPIO.OUT) - self.pwm = GPIO.PWM(channel, 100) - - self.lock = threading.Lock() - - def start(self): - """Starts the LED driver.""" - with self.lock: - if not self.running: - self.running = True - self.pwm.start(0) # off by default - self.animator.start() - - def stop(self): - """Stops the LED driver and sets the LED to off.""" - with self.lock: - if self.running: + LED_OFF = 0 + LED_ON = 1 + LED_BLINK = 2 + LED_BLINK_3 = 3 + LED_BEACON = 4 + LED_BEACON_DARK = 5 + LED_DECAY = 6 + LED_PULSE_SLOW = 7 + LED_PULSE_QUICK = 8 + + def __init__(self, channel): + self.animator = threading.Thread(target=self._animate) + self.channel = channel + self.iterator = None self.running = False - self.animator.join() - self.pwm.stop() + self.state = None + self.sleep = 0 - def set_state(self, state): - """Sets the LED driver's new state. + GPIO.setup(channel, GPIO.OUT) + self.pwm = GPIO.PWM(channel, 100) + + self.lock = threading.Lock() + + def start(self): + """Starts the LED driver.""" + with self.lock: + if not self.running: + self.running = True + self.pwm.start(0) # off by default + self.animator.start() + + def stop(self): + """Stops the LED driver and sets the LED to off.""" + with self.lock: + if self.running: + self.running = False + self.animator.join() + self.pwm.stop() + + def set_state(self, state): + """Sets the LED driver's new state. Note the LED driver must be started for this to have any effect. """ - with self.lock: - self.state = state - - def _animate(self): - while True: - state = None - running = False - with self.lock: - state = self.state - self.state = None - running = self.running - if not running: - return - if state: - if not self._parse_state(state): - print('unsupported state: %d' % state) - if self.iterator: - self.pwm.ChangeDutyCycle(next(self.iterator)) - time.sleep(self.sleep) - else: - # We can also wait for a state change here with a Condition. - time.sleep(1) - - def _parse_state(self, state): - self.iterator = None - self.sleep = 0.0 - if state == self.LED_OFF: - self.pwm.ChangeDutyCycle(0) - return True - if state == self.LED_ON: - self.pwm.ChangeDutyCycle(100) - return True - if state == self.LED_BLINK: - self.iterator = itertools.cycle([0, 100]) - self.sleep = 0.5 - return True - if state == self.LED_BLINK_3: - self.iterator = itertools.cycle([0, 100] * 3 + [0, 0]) - self.sleep = 0.25 - return True - if state == self.LED_BEACON: - self.iterator = itertools.cycle( - itertools.chain([30] * 100, [100] * 8, range(100, 30, -5))) - self.sleep = 0.05 - return True - if state == self.LED_BEACON_DARK: - self.iterator = itertools.cycle( - itertools.chain([0] * 100, range(0, 30, 3), range(30, 0, -3))) - self.sleep = 0.05 - return True - if state == self.LED_DECAY: - self.iterator = itertools.cycle(range(100, 0, -2)) - self.sleep = 0.05 - return True - if state == self.LED_PULSE_SLOW: - self.iterator = itertools.cycle( - itertools.chain(range(0, 100, 2), range(100, 0, -2))) - self.sleep = 0.1 - return True - if state == self.LED_PULSE_QUICK: - self.iterator = itertools.cycle( - itertools.chain(range(0, 100, 5), range(100, 0, -5))) - self.sleep = 0.05 - return True - return False + with self.lock: + self.state = state + + def _animate(self): + while True: + state = None + running = False + with self.lock: + state = self.state + self.state = None + running = self.running + if not running: + return + if state: + if not self._parse_state(state): + print('unsupported state: %d' % state) + if self.iterator: + self.pwm.ChangeDutyCycle(next(self.iterator)) + time.sleep(self.sleep) + else: + # We can also wait for a state change here with a Condition. + time.sleep(1) + + def _parse_state(self, state): + self.iterator = None + self.sleep = 0.0 + if state == self.LED_OFF: + self.pwm.ChangeDutyCycle(0) + return True + if state == self.LED_ON: + self.pwm.ChangeDutyCycle(100) + return True + if state == self.LED_BLINK: + self.iterator = itertools.cycle([0, 100]) + self.sleep = 0.5 + return True + if state == self.LED_BLINK_3: + self.iterator = itertools.cycle([0, 100] * 3 + [0, 0]) + self.sleep = 0.25 + return True + if state == self.LED_BEACON: + self.iterator = itertools.cycle( + itertools.chain([30] * 100, [100] * 8, range(100, 30, -5))) + self.sleep = 0.05 + return True + if state == self.LED_BEACON_DARK: + self.iterator = itertools.cycle( + itertools.chain([0] * 100, range(0, 30, 3), range(30, 0, -3))) + self.sleep = 0.05 + return True + if state == self.LED_DECAY: + self.iterator = itertools.cycle(range(100, 0, -2)) + self.sleep = 0.05 + return True + if state == self.LED_PULSE_SLOW: + self.iterator = itertools.cycle( + itertools.chain(range(0, 100, 2), range(100, 0, -2))) + self.sleep = 0.1 + return True + if state == self.LED_PULSE_QUICK: + self.iterator = itertools.cycle( + itertools.chain(range(0, 100, 5), range(100, 0, -5))) + self.sleep = 0.05 + return True + return False From e4e7b7de8779eb994cc2a59a1ef34b71f593a35f Mon Sep 17 00:00:00 2001 From: Fan Deng Date: Tue, 27 Jun 2017 09:35:01 -0700 Subject: [PATCH 3/4] Call aiy.common.LED from led.py. The status-led service will now call into aiy.common.LED. Also raise a ValueError when an unexpected state is passed to aiy.common.LED.set_state. Tested: Tried src/main.py and observed expected LED animations. --- src/aiy/common.py | 9 ++-- src/led.py | 124 +++++++++------------------------------------- 2 files changed, 28 insertions(+), 105 deletions(-) diff --git a/src/aiy/common.py b/src/aiy/common.py index abb0637e..c97de241 100644 --- a/src/aiy/common.py +++ b/src/aiy/common.py @@ -11,10 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""This library provides common drivers for the AIY projects. - -Drivers in this module requires GPIO.setmode(GPIO.BCM). -""" +"""This library provides common drivers for the AIY projects.""" import itertools import os @@ -55,6 +52,7 @@ def __init__(self, self.expected_value = polarity == GPIO.RISING self.debounce_time = debounce_time + GPIO.setmode(GPIO.BCM) GPIO.setup(channel, GPIO.IN, pull_up_down=pull_up_down) self.callback = None @@ -135,6 +133,7 @@ def __init__(self, channel): self.state = None self.sleep = 0 + GPIO.setmode(GPIO.BCM) GPIO.setup(channel, GPIO.OUT) self.pwm = GPIO.PWM(channel, 100) @@ -176,7 +175,7 @@ def _animate(self): return if state: if not self._parse_state(state): - print('unsupported state: %d' % state) + raise ValueError('unsupported state: %d' % state) if self.iterator: self.pwm.ChangeDutyCycle(next(self.iterator)) time.sleep(self.sleep) diff --git a/src/led.py b/src/led.py index dca70ab5..d32b994f 100644 --- a/src/led.py +++ b/src/led.py @@ -11,131 +11,54 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +"""Signal states on a LED""" -'''Signal states on a LED''' - -import itertools import logging import os -import threading import time +import aiy.common import RPi.GPIO as GPIO -logger = logging.getLogger('led') +logger = logging.getLogger("led") -CONFIG_DIR = os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config') +CONFIG_DIR = os.getenv("XDG_CONFIG_HOME") or os.path.expanduser("~/.config") CONFIG_FILES = [ - '/etc/status-led.ini', - os.path.join(CONFIG_DIR, 'status-led.ini') + "/etc/status-led.ini", + os.path.join(CONFIG_DIR, "status-led.ini") ] -class LED: - - """Starts a background thread to show patterns with the LED.""" - - def __init__(self, channel): - self.animator = threading.Thread(target=self._animate) - self.channel = channel - self.iterator = None - self.running = False - self.state = None - self.sleep = 0 - - GPIO.setup(channel, GPIO.OUT) - self.pwm = GPIO.PWM(channel, 100) - - def start(self): - self.pwm.start(0) # off by default - self.running = True - self.animator.start() - - def stop(self): - self.running = False - self.animator.join() - self.pwm.stop() - GPIO.output(self.channel, GPIO.LOW) - - def set_state(self, state): - self.state = state - - def _animate(self): - # TODO(ensonic): refactor or add justification - # pylint: disable=too-many-branches - while self.running: - if self.state: - if self.state == 'on': - self.iterator = None - self.sleep = 0.0 - self.pwm.ChangeDutyCycle(100) - elif self.state == 'off': - self.iterator = None - self.sleep = 0.0 - self.pwm.ChangeDutyCycle(0) - elif self.state == 'blink': - self.iterator = itertools.cycle([0, 100]) - self.sleep = 0.5 - elif self.state == 'blink-3': - self.iterator = itertools.cycle([0, 100] * 3 + [0, 0]) - self.sleep = 0.25 - elif self.state == 'beacon': - self.iterator = itertools.cycle( - itertools.chain([30] * 100, [100] * 8, range(100, 30, -5))) - self.sleep = 0.05 - elif self.state == 'beacon-dark': - self.iterator = itertools.cycle( - itertools.chain([0] * 100, range(0, 30, 3), range(30, 0, -3))) - self.sleep = 0.05 - elif self.state == 'decay': - self.iterator = itertools.cycle(range(100, 0, -2)) - self.sleep = 0.05 - elif self.state == 'pulse-slow': - self.iterator = itertools.cycle( - itertools.chain(range(0, 100, 2), range(100, 0, -2))) - self.sleep = 0.1 - elif self.state == 'pulse-quick': - self.iterator = itertools.cycle( - itertools.chain(range(0, 100, 5), range(100, 0, -5))) - self.sleep = 0.05 - else: - logger.warning("unsupported state: %s", self.state) - self.state = None - if self.iterator: - self.pwm.ChangeDutyCycle(next(self.iterator)) - time.sleep(self.sleep) - else: - time.sleep(1) - - def main(): logging.basicConfig( level=logging.INFO, - format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s" - ) + format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s") import configargparse parser = configargparse.ArgParser( - default_config_files=CONFIG_FILES, - description="Status LED daemon") - parser.add_argument('-G', '--gpio-pin', default=25, type=int, - help='GPIO pin for the LED (default: 25)') + default_config_files=CONFIG_FILES, description="Status LED daemon") + parser.add_argument( + "-G", + "--gpio-pin", + default=25, + type=int, + help="GPIO pin for the LED (default: 25)") args = parser.parse_args() led = None state_map = { - "starting": "pulse-quick", - "ready": "beacon-dark", - "listening": "on", - "thinking": "pulse-quick", - "stopping": "pulse-quick", - "power-off": "off", - "error": "blink-3", + "starting": aiy.common.LED.LED_PULSE_QUICK, + "ready": aiy.common.LED.LED_BEACON_DARK, + "listening": aiy.common.LED.LED_ON, + "thinking": aiy.common.LED.LED_PULSE_QUICK, + "stopping": aiy.common.LED.LED_PULSE_QUICK, + "power-off": aiy.common.LED.LED_OFF, + "error": aiy.common.LED.LED_BLINK_3, } try: GPIO.setmode(GPIO.BCM) - led = LED(args.gpio_pin) + led = aiy.common.LED(args.gpio_pin) led.start() while True: try: @@ -156,5 +79,6 @@ def main(): led.stop() GPIO.cleanup() -if __name__ == '__main__': + +if __name__ == "__main__": main() From 7fcc47e1865cbb5c318c69272d839aa9593b9398 Mon Sep 17 00:00:00 2001 From: Fan Deng Date: Thu, 29 Jun 2017 10:12:06 -0700 Subject: [PATCH 4/4] Revert some formatting introduced by pyformat. --- src/led.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/led.py b/src/led.py index d32b994f..1dd1e248 100644 --- a/src/led.py +++ b/src/led.py @@ -20,29 +20,28 @@ import aiy.common import RPi.GPIO as GPIO -logger = logging.getLogger("led") +logger = logging.getLogger('led') -CONFIG_DIR = os.getenv("XDG_CONFIG_HOME") or os.path.expanduser("~/.config") +CONFIG_DIR = os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config') CONFIG_FILES = [ - "/etc/status-led.ini", - os.path.join(CONFIG_DIR, "status-led.ini") + '/etc/status-led.ini', + os.path.join(CONFIG_DIR, 'status-led.ini') ] def main(): logging.basicConfig( level=logging.INFO, - format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s") + format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s" + ) import configargparse parser = configargparse.ArgParser( - default_config_files=CONFIG_FILES, description="Status LED daemon") - parser.add_argument( - "-G", - "--gpio-pin", - default=25, - type=int, - help="GPIO pin for the LED (default: 25)") + default_config_files=CONFIG_FILES, + description="Status LED daemon" + ) + parser.add_argument('-G', '--gpio-pin', default=25, type=int, + help='GPIO pin for the LED (default: 25)') args = parser.parse_args() led = None @@ -80,5 +79,5 @@ def main(): GPIO.cleanup() -if __name__ == "__main__": +if __name__ == '__main__': main()