Compare commits
No commits in common. "tobru-musicbox" and "master" have entirely different histories.
tobru-musi
...
master
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -1,3 +1,9 @@
|
|||
__pycache__
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
.venv/
|
||||
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
.eggs/
|
||||
|
|
471
.pylintrc
Normal file
471
.pylintrc
Normal file
|
@ -0,0 +1,471 @@
|
|||
[MASTER]
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
ignore=.git,
|
||||
.venv,
|
||||
|
||||
# Add files or directories matching the regex patterns to the blacklist. The
|
||||
# regex matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Use multiple processes to speed up Pylint.
|
||||
jobs=1
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# Specify a configuration file.
|
||||
#rcfile=
|
||||
|
||||
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
||||
# user-friendly hints instead of false-positive error messages
|
||||
suggestion-mode=yes
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
|
||||
confidence=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once).You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=bad-whitespace,
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
enable=c-extension-no-member
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details
|
||||
#msg-template=
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, json
|
||||
# and msvs (visual studio).You can also give a reporter class, eg
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=no
|
||||
|
||||
# Activate the evaluation score.
|
||||
score=yes
|
||||
|
||||
|
||||
[REFACTORING]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
# Complete name of functions that never returns. When checking for
|
||||
# inconsistent-return-statements if a never returning function is called then
|
||||
# it will be considered as an explicit return statement and no message will be
|
||||
# printed.
|
||||
never-returning-functions=optparse.Values,sys.exit
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Limits count of emitted suggestions for spelling mistakes
|
||||
max-spelling-suggestions=4
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it working
|
||||
# install python-enchant package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to indicated private dictionary in
|
||||
# --spelling-private-dict-file option instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,
|
||||
XXX,
|
||||
TODO
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# This flag controls whether pylint should warn about no-member and similar
|
||||
# checks whenever an opaque object is returned when inferring. The inference
|
||||
# can return multiple potential results while evaluating a Python object, but
|
||||
# some branches might not be evaluated, which results in partial inference. In
|
||||
# that case, it might be useful to still emit no-member and other checks for
|
||||
# the rest of the inferred objects.
|
||||
ignore-on-opaque-inference=yes
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis. It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# Show a hint with possible names when a member name was not found. The aspect
|
||||
# of finding the hint is based on edit distance.
|
||||
missing-member-hint=yes
|
||||
|
||||
# The minimum edit distance a name should have in order to be considered a
|
||||
# similar match for a missing member name.
|
||||
missing-member-hint-distance=1
|
||||
|
||||
# The total number of similar names that should be taken in consideration when
|
||||
# showing a hint for a missing member.
|
||||
missing-member-max-choices=1
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# Tells whether unused global variables should be treated as a violation.
|
||||
allow-global-unused-variables=yes
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,
|
||||
_cb
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expectedly
|
||||
# not used).
|
||||
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore
|
||||
ignored-argument-names=_.*|^ignored_|^unused_
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,past.builtins,future.builtins,io,builtins
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=100
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# List of optional constructs for which whitespace checking is disabled. `dict-
|
||||
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
|
||||
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
|
||||
# `empty-line` allows space-only lines.
|
||||
no-space-check=trailing-comma,
|
||||
dict-separator
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
single-line-class-stmt=no
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Naming style matching correct argument names
|
||||
argument-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct argument names. Overrides argument-
|
||||
# naming-style
|
||||
#argument-rgx=
|
||||
|
||||
# Naming style matching correct attribute names
|
||||
attr-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct attribute names. Overrides attr-naming-
|
||||
# style
|
||||
#attr-rgx=
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=foo,
|
||||
bar,
|
||||
baz,
|
||||
toto,
|
||||
tutu,
|
||||
tata
|
||||
|
||||
# Naming style matching correct class attribute names
|
||||
class-attribute-naming-style=any
|
||||
|
||||
# Regular expression matching correct class attribute names. Overrides class-
|
||||
# attribute-naming-style
|
||||
#class-attribute-rgx=
|
||||
|
||||
# Naming style matching correct class names
|
||||
class-naming-style=PascalCase
|
||||
|
||||
# Regular expression matching correct class names. Overrides class-naming-style
|
||||
#class-rgx=
|
||||
|
||||
# Naming style matching correct constant names
|
||||
const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct constant names. Overrides const-naming-
|
||||
# style
|
||||
#const-rgx=
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
# Naming style matching correct function names
|
||||
function-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct function names. Overrides function-
|
||||
# naming-style
|
||||
#function-rgx=
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=i,
|
||||
j,
|
||||
k,
|
||||
f,
|
||||
ex,
|
||||
_
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name
|
||||
include-naming-hint=no
|
||||
|
||||
# Naming style matching correct inline iteration names
|
||||
inlinevar-naming-style=any
|
||||
|
||||
# Regular expression matching correct inline iteration names. Overrides
|
||||
# inlinevar-naming-style
|
||||
#inlinevar-rgx=
|
||||
|
||||
# Naming style matching correct method names
|
||||
method-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct method names. Overrides method-naming-
|
||||
# style
|
||||
#method-rgx=
|
||||
|
||||
# Naming style matching correct module names
|
||||
module-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct module names. Overrides module-naming-
|
||||
# style
|
||||
#module-rgx=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Naming style matching correct variable names
|
||||
variable-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct variable names. Overrides variable-
|
||||
# naming-style
|
||||
#variable-rgx=
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method
|
||||
max-args=5
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Maximum number of boolean expressions in a if statement
|
||||
max-bool-expr=5
|
||||
|
||||
# Maximum number of branch for function / method body
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of locals for function / method body
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of return / yield for function / method body
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of statements in function / method body
|
||||
max-statements=50
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=mcs
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Allow wildcard imports from modules that define __all__.
|
||||
allow-wildcard-with-all=yes
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=regsub,
|
||||
TERMIOS,
|
||||
Bastion,
|
||||
rexec
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception"
|
||||
overgeneral-exceptions=Exception
|
19
.travis.yml
Normal file
19
.travis.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
language: python
|
||||
|
||||
python:
|
||||
- 3.7
|
||||
|
||||
install:
|
||||
# Workaround for pi-rc522 dependency issue.
|
||||
- pip install spidev RPi.GPIO
|
||||
|
||||
# Install package develop
|
||||
- pip install -e .[develop]
|
||||
|
||||
script:
|
||||
# Code style checks.
|
||||
- pycodestyle mopidy_pummeluff
|
||||
- pylint mopidy_pummeluff
|
||||
|
||||
# Build check.
|
||||
- python setup.py build
|
19
LICENSE
Normal file
19
LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2019 confirm IT solutions
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
155
README.rst
Normal file
155
README.rst
Normal file
|
@ -0,0 +1,155 @@
|
|||
Mopidy Pummeluff
|
||||
================
|
||||
|
||||
Pummeluff is a `Mopidy <http://www.mopidy.com/>`_ extension which allows you to control Mopidy via RFID tags. It is as simple as that:
|
||||
|
||||
- Register an action to an RFID tag
|
||||
- Touch that tag on the RFID reader and the action will be executed
|
||||
|
||||
Thus, the Mopidy Pummeluff extension adds the following features to Mopidy:
|
||||
|
||||
- A radically simple web UI which can be used to manage the RFID tags
|
||||
- A daemon which continuously reads RFID tags in the background and executes the assigned actions
|
||||
|
||||
There are several actions included, such as replacing the tracklist with a desired URI, setting the volume to a specific level or controlling the playback state.
|
||||
|
||||
Hardware
|
||||
========
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
To get the whole thing working, you need at least the following hardware:
|
||||
|
||||
- A Raspberry Pi 3 Model B
|
||||
- An ``RC522`` RFID module (`RC522 on AliExpress <https://www.aliexpress.com/wholesale?SearchText=rc522>`_ for approx. *USD 1*)
|
||||
- RFID tags (``ISO 14443A`` & ``Mifare`` should work, `14443A tags on AliExpress <https://www.aliexpress.com/wholesale?SearchText=14443A+lot>`_ for approx. *0.4 USD* per tag)
|
||||
- Female dupont jumper wires (`female dupont jumper cables on AliExpress <https://www.aliexpress.com/wholesale?SearchText=dupont>`_ for approx. *1 USD*)
|
||||
|
||||
Optionally you can also add two buttons to the RPi, which can be used for power & playback control:
|
||||
|
||||
- Two momentary push buttons (`momentary push buttons on AliExpress <https://www.aliexpress.com/wholesale?SearchText=momentary+push+button>`_ for approx. *USD 1-2*)
|
||||
|
||||
Pummeluff also supports a status LED, which lights up when Pummeluff (i.e. Mopidy) is running. You can go with a separate LED, just make sure it can handle 3.3V or add a resistor. There are also push buttons with integrated LED's available, for example `these 5V momentary push buttons on AliExpress <https://www.aliexpress.com/item/16mm-Metal-brass-Push-Button-Switch-flat-round-illumination-ring-Latching-1NO-1NC-Car-press-button/32676526568.html>`_.
|
||||
|
||||
.. note::
|
||||
|
||||
The project will probably run on other RPi models, but I've only tested it on the ``3B``. The RPi ``3B+`` should also work fine, as the GPIO pins are identical. I don't know about RPi ``1`` or ``2``, but you can give it a shot.
|
||||
|
||||
Connecting the RC522 module
|
||||
---------------------------
|
||||
|
||||
Please connect the ``RC522`` RFID module to the RPi as follows:
|
||||
|
||||
- ``RC522 pin 1 [SDA ]`` ––– ``RPi pin 24 [SPI0 CE0 ]``
|
||||
- ``RC522 pin 2 [SCK ]`` ––– ``RPi pin 23 [SPI0 SCLK]``
|
||||
- ``RC522 pin 3 [MOSI]`` ––– ``RPi pin 19 [SPI0 MOSI]``
|
||||
- ``RC522 pin 4 [MISO]`` ––– ``RPi pin 21 [SPI0 MISO]``
|
||||
- ``RC522 pin 5 [IRQ ]`` ––– ``RPi pin 18 [ GPIO 24 ]``
|
||||
- ``RC522 pin 6 [GND ]`` ––– ``RPi pin 20 [ GND ]``
|
||||
- ``RC522 pin 7 [RST ]`` ––– ``RPi pin 22 [ GPIO 25 ]``
|
||||
- ``RC522 pin 8 [3.3V]`` ––– ``RPi pin 17 [3.3V PWR ]``
|
||||
|
||||
Please have a look at the `Raspberry Pi SPI pinout <https://pinout.xyz/pinout/spi>`_ if you want to have a graphical view of the RPi GPIO pins.
|
||||
|
||||
.. note::
|
||||
|
||||
This connections are only valid for the RPi model ``3B`` and ``3B+``. If you want to use another RPI model, make sure you're using the correct pins.
|
||||
|
||||
Connecting the buttons (optional)
|
||||
---------------------------------
|
||||
|
||||
You can connect two buttons to the RPi:
|
||||
|
||||
- ``RPi pin 5`` - Power button: Shutdown the Raspberry Pi into halt state & wake it up again from halt state
|
||||
- ``RPi pin 29`` - Playback button: Pause and resume the playback
|
||||
- ``RPi pin 31`` - Stop button: Stops the playback
|
||||
- ``RPi pin 33`` - Previous button: Changes to the previous track in the playlist
|
||||
- ``RPi pin 35`` - Next button: Changes to the next track in the playlist
|
||||
|
||||
The buttons must shortcut their corresponding pins against ``GND`` (e.g. pin ``6``) when pressed. This means you want to connect one pin of the button (i.e. ``C``) to RPI's ``GND``, and the other one (i.e. ``NO``) to RPi's pin ``5``, ``29``, ``31``, ``33`` or ``35``.
|
||||
|
||||
Connecting the status LED (optional)
|
||||
------------------------------------
|
||||
|
||||
If you want to have a status LED which is turned on when the RPi is running, you can connect an LED to a ``GND`` pin (e.g. pin ``6``) & to pin ``8``.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Prepare Raspberry Pi
|
||||
--------------------
|
||||
|
||||
Before you can install and use Mopidy Pummeluff, you need to configure your Raspberry Pi properly.
|
||||
|
||||
We want to enable the ``SPI`` interface and give the ``mopidy`` user access to it. This is required for the communication to the RFID module. Enter this command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo raspi-config
|
||||
|
||||
In the configuraton utility, **Enable the SPI** under ``5 Interfacing Options – P4 SPI``.
|
||||
|
||||
After that, add your ``mopidy`` user to the ``spi`` and ``gpio`` group:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo usermod -a -G spi,gpio mopidy
|
||||
|
||||
If you're planning to use a button or RFID tag to shutdown the system, you also need to create a sudo rule, so that the ``mopidy`` user can shutdown the system without a password prompt:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
echo "mopidy ALL = NOPASSWD: /sbin/shutdown" > /etc/sudoers.d/mopidy
|
||||
|
||||
Install via pip
|
||||
---------------
|
||||
|
||||
The recommended way to install Mopidy Pummeluff by using ``pip`` and thus by executing the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo pip install mopidy-pummeluff
|
||||
|
||||
.. hint::
|
||||
|
||||
If you get an error that ``spidev`` could not be found, run ``pip install spidev`` first. This is an issue related to the ``pi-rc522`` Pypi package.
|
||||
|
||||
Install from source
|
||||
-------------------
|
||||
|
||||
Alternatively, you can also install Mopidy Pummeluff from source, by running this command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo su -
|
||||
cd /usr/src
|
||||
git clone https://github.com/confirm/mopidy-pummeluff.git
|
||||
cd mopidy-pummeluff
|
||||
python setup.py install
|
||||
|
||||
.. hint::
|
||||
|
||||
If you get an error that ``spidev`` could not be found, run ``pip install spidev`` first. This is an issue related to the ``pi-rc522`` Pypi package.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Activate and configure the `Mopidy HTTP <https://docs.mopidy.com/en/latest/ext/http/>`_ extension and make sure you can connect to the Web UI. The minimal config looks like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
[http]
|
||||
enabled = true
|
||||
hostname = 0.0.0.0
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Open the Mopidy Web UI (i.e. ``http://{MOPIDY_IP}:6680/``).
|
||||
You should see a ``pummeluff`` web client which can be used to regsiter new RFID tags.
|
||||
|
||||
Contribution
|
||||
============
|
||||
|
||||
Please follow `these development guidelines <https://development-guidelines.confirm.ch/>`_ when contributing to this project.
|
|
@ -4,7 +4,6 @@ Mopidy Pummeluff Python module.
|
|||
|
||||
import os
|
||||
|
||||
import pkg_resources
|
||||
import mopidy
|
||||
|
||||
from .frontend import PummeluffFrontend
|
||||
|
@ -12,8 +11,6 @@ from .web import LatestHandler, RegistryHandler, RegisterHandler, UnregisterHand
|
|||
ActionClassesHandler
|
||||
|
||||
|
||||
__version__ = pkg_resources.get_distribution('Mopidy-Pummeluff').version
|
||||
|
||||
def app_factory(config, core): # pylint: disable=unused-argument
|
||||
'''
|
||||
App factory for the web apps.
|
||||
|
@ -40,7 +37,6 @@ class Extension(mopidy.ext.Extension):
|
|||
|
||||
dist_name = 'Mopidy-Pummeluff'
|
||||
ext_name = 'pummeluff'
|
||||
version = __version__
|
||||
|
||||
def get_default_config(self): # pylint: disable=no-self-use
|
||||
'''
|
|
@ -9,12 +9,13 @@ __all__ = (
|
|||
'NextTrack',
|
||||
'Shutdown',
|
||||
'Tracklist',
|
||||
'ToggleShuffle',
|
||||
'Volume',
|
||||
)
|
||||
|
||||
from .playback import PlayPause, Stop, PreviousTrack, NextTrack
|
||||
from .shutdown import Shutdown
|
||||
from .tracklist import Tracklist
|
||||
from .tracklist import Tracklist, ToggleShuffle
|
||||
from .volume import Volume
|
||||
|
||||
ACTIONS = {}
|
|
@ -4,6 +4,7 @@ Python module for Mopidy Pummeluff tracklist tag.
|
|||
|
||||
__all__ = (
|
||||
'Tracklist',
|
||||
'ToggleShuffle',
|
||||
)
|
||||
|
||||
from logging import getLogger
|
||||
|
@ -39,3 +40,23 @@ class Tracklist(Action):
|
|||
core.tracklist.clear()
|
||||
core.tracklist.add(uris=uris)
|
||||
core.playback.play()
|
||||
|
||||
|
||||
class ToggleShuffle(Action):
|
||||
'''
|
||||
Toggles random mode
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def execute(cls, core):
|
||||
'''
|
||||
Toggle random mode.
|
||||
|
||||
:param mopidy.core.Core core: The mopidy core instance
|
||||
'''
|
||||
|
||||
shuffle = core.tracklist.get_random().get()
|
||||
shuffle = not shuffle
|
||||
core.tracklist.set_random(shuffle)
|
||||
|
||||
LOGGER.info('Toggling shuffle mode [%s]', shuffle)
|
|
@ -24,10 +24,10 @@ class GPIOHandler(Thread):
|
|||
LED when it's started and then reacting to button presses.
|
||||
'''
|
||||
button_pins = {
|
||||
#5: Shutdown,
|
||||
#29: PlayPause,
|
||||
#31: Stop,
|
||||
#33: PreviousTrack,
|
||||
5: Shutdown,
|
||||
29: PlayPause,
|
||||
31: Stop,
|
||||
33: PreviousTrack,
|
||||
35: NextTrack,
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,6 @@ class GPIOHandler(Thread):
|
|||
LOGGER.debug('Setup pin %s as LED pin', self.led_pin)
|
||||
GPIO.setup(self.led_pin, GPIO.OUT)
|
||||
GPIO.output(self.led_pin, GPIO.HIGH)
|
||||
play_sound('success.wav')
|
||||
|
||||
self.stop_event.wait()
|
||||
GPIO.cleanup() # pylint: disable=no-member
|
|
@ -48,8 +48,7 @@ class TagReader(Thread):
|
|||
super().__init__()
|
||||
self.core = core
|
||||
self.stop_event = stop_event
|
||||
#self.rfid = RFID()
|
||||
self.rfid = RFID(pin_irq=15)
|
||||
self.rfid = RFID()
|
||||
|
||||
def run(self):
|
||||
'''
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Mopidy >= 2.2.2
|
||||
pi-rc522 == 2.2.1
|
2
requirements_dev.txt
Normal file
2
requirements_dev.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
pycodestyle==2.5.0
|
||||
pylint==2.4.4
|
49
setup.py
Executable file
49
setup.py
Executable file
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env python
|
||||
'''
|
||||
Setup script for Mopidy-Pummeluff module.
|
||||
'''
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
with open('requirements.txt') as f:
|
||||
requirements = f.read().strip().split('\n')
|
||||
|
||||
with open('requirements_dev.txt') as f:
|
||||
requirements_dev = f.read().strip().split('\n')
|
||||
|
||||
setup(
|
||||
name='Mopidy-Pummeluff',
|
||||
use_scm_version=True,
|
||||
url='https://github.com/confirm/mopidy-pummeluff',
|
||||
license='MIT',
|
||||
author='confirm IT solutions',
|
||||
author_email='mopidy-pummeluff@confirm.ch',
|
||||
description='Pummeluff is a Mopidy extension which allows you to control Mopidy via RFID tags',
|
||||
long_description=open('README.rst').read(),
|
||||
packages=find_packages(exclude=[
|
||||
'tests',
|
||||
'tests.*',
|
||||
]),
|
||||
zip_safe=False,
|
||||
include_package_data=True,
|
||||
setup_requires=[
|
||||
'setuptools_scm',
|
||||
],
|
||||
install_requires=['setuptools'] + requirements,
|
||||
extras_require={
|
||||
'develop': requirements_dev,
|
||||
},
|
||||
entry_points={
|
||||
'mopidy.ext': [
|
||||
'pummeluff = mopidy_pummeluff:Extension',
|
||||
],
|
||||
},
|
||||
classifiers=[
|
||||
'Environment :: No Input/Output (Daemon)',
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Topic :: Multimedia :: Sound/Audio :: Players',
|
||||
],
|
||||
)
|
Loading…
Reference in a new issue