REFACTOR: Rename card to tag

This commit is contained in:
Dominique Barton 2019-03-26 21:22:15 +01:00
parent 5cb14f7f3e
commit 78ab0a32ef
9 changed files with 153 additions and 153 deletions

View file

@ -15,7 +15,7 @@ from logging import getLogger
import pykka
from mopidy import core as mopidy_core
from .threads import GPIOHandler, CardReader
from .threads import GPIOHandler, TagReader
LOGGER = getLogger(__name__)
@ -24,7 +24,7 @@ LOGGER = getLogger(__name__)
class PummeluffFrontend(pykka.ThreadingActor, mopidy_core.CoreListener):
'''
Pummeluff frontend which basically reacts to GPIO button pushes and touches
of RFID cards.
of RFID tags.
'''
def __init__(self, config, core): # pylint: disable=unused-argument
@ -32,18 +32,18 @@ class PummeluffFrontend(pykka.ThreadingActor, mopidy_core.CoreListener):
self.core = core
self.stop_event = Event()
self.gpio_handler = GPIOHandler(core=core, stop_event=self.stop_event)
self.card_reader = CardReader(core=core, stop_event=self.stop_event)
self.tag_reader = TagReader(core=core, stop_event=self.stop_event)
def on_start(self):
'''
Start GPIO handler & card reader threads.
Start GPIO handler & tag reader threads.
'''
self.gpio_handler.start()
self.card_reader.start()
self.tag_reader.start()
def on_stop(self):
'''
Set threading stop event to tell GPIO handler & card reader threads to
Set threading stop event to tell GPIO handler & tag reader threads to
stop their operations.
'''
self.stop_event.set()

View file

@ -20,11 +20,11 @@ LOGGER = getLogger(__name__)
class RegistryDict(dict):
'''
Simple card registry based on Python's internal :py:class:`dict` class,
Simple tag registry based on Python's internal :py:class:`dict` class,
which reads and writes the registry from/to disk.
'''
registry_path = '/var/lib/mopidy/pummeluff/cards.json'
registry_path = '/var/lib/mopidy/pummeluff/tags.json'
def __init__(self):
super(RegistryDict, self).__init__(self)

View file

@ -1,17 +1,17 @@
# -*- coding: utf-8 -*-
'''
Python module for Mopidy Pummeluff cards.
Python module for Mopidy Pummeluff tags.
'''
from __future__ import absolute_import, unicode_literals, print_function
__all__ = (
'Card',
'TracklistCard',
'VolumeCard',
'PlayPauseCard',
'StopCard',
'ShutdownCard',
'Tag',
'TracklistTag',
'VolumeTag',
'PlayPauseTag',
'StopTag',
'ShutdownTag',
)
from logging import getLogger
@ -23,34 +23,34 @@ from . import actions
LOGGER = getLogger(__name__)
class InvalidCardType(Exception):
class InvalidTagType(Exception):
'''
Exception which is thrown when an invalid card type is defined.
Exception which is thrown when an invalid tag type is defined.
'''
pass
class Card(object):
class Tag(object):
'''
Base RFID card class, which will implement the factory pattern in Python's
Base RFID tag class, which will implement the factory pattern in Python's
own :py:meth:`__new__` method.
'''
def __new__(cls, uid):
'''
Implement factory pattern and return correct card instance.
Implement factory pattern and return correct tag instance.
'''
card = REGISTRY.get(uid, {})
new_cls = cls.get_class(card.get('type', ''))
tag = REGISTRY.get(uid, {})
new_cls = cls.get_class(tag.get('type', ''))
if cls is Card and cls is not new_cls:
if cls is Tag and cls is not new_cls:
instance = new_cls(uid=uid)
else:
instance = super(Card, cls).__new__(cls, uid=uid)
instance = super(Tag, cls).__new__(cls, uid=uid)
instance.registered = bool(card)
instance.alias = card.get('alias')
instance.parameter = card.get('parameter')
instance.registered = bool(tag)
instance.alias = tag.get('alias')
instance.parameter = tag.get('parameter')
return instance
@ -64,7 +64,7 @@ class Card(object):
def __call__(self, core):
'''
Action method which is called when the card is detected on the RFID
Action method which is called when the tag is detected on the RFID
reader.
:param mopidy.core.Core core: The mopidy core instance
@ -75,62 +75,62 @@ class Card(object):
getattr(actions, self.action)(*args)
@staticmethod
def get_class(card_type):
def get_class(tag_type):
'''
Return class for specific card type.
Return class for specific tag type.
:param str card_type: The card type
:param str tag_type: The tag type
:return: The card class
:return: The tag class
:rtype: type
'''
try:
name = card_type.title() + 'Card'
name = tag_type.title() + 'Tag'
cls = globals()[name]
assert issubclass(cls, Card)
assert issubclass(cls, Tag)
except (KeyError, AssertionError):
raise InvalidCardType('Card class for type "{}" does\'t exist.'.format(card_type))
raise InvalidTagType('Tag class for type "{}" does\'t exist.'.format(tag_type))
return cls
@classmethod
def get_type(cls, card_class=None):
def get_type(cls, tag_class=None):
'''
Return the type for a specific card class.
Return the type for a specific tag class.
:param type card_class: The card class
:param type tag_class: The tag class
:return: The card type
:return: The tag type
:rtype: str
'''
return (card_class or cls).__name__[0:-4].lower()
return (tag_class or cls).__name__[0:-3].lower()
@classmethod
def all(cls):
'''
Return all registered cards in a list.
Return all registered tags in a list.
:return: Registered cards
:rtype: list[Card]
:return: Registered tags
:rtype: list[Tag]
'''
return {uid: Card(uid=uid) for uid in REGISTRY}
return {uid: Tag(uid=uid) for uid in REGISTRY}
@classmethod
def register(cls, uid, alias=None, parameter=None, card_type=None):
def register(cls, uid, alias=None, parameter=None, tag_type=None):
'''
Register card in the registry.
Register tag in the registry.
:param str uid: The card's UID
:param str alias: The card's alias
:param str uid: The tag's UID
:param str alias: The tag's alias
:param str parameter: The optional parameter
:param str card_type: The card type
:param str tag_type: The tag type
:return: The registered card
:rtype: Card
:return: The registered tag
:rtype: Tag
'''
if card_type is None:
card_type = cls.get_type(cls)
if tag_type is None:
tag_type = cls.get_type(cls)
uid = uid.strip()
if not uid:
@ -138,36 +138,36 @@ class Card(object):
LOGGER.error(error)
raise ValueError(error)
LOGGER.info('Registering %s card %s with parameter "%s"', card_type, uid, parameter)
LOGGER.info('Registering %s tag %s with parameter "%s"', tag_type, uid, parameter)
real_cls = cls.get_class(card_type)
real_cls = cls.get_class(tag_type)
if real_cls == Card:
error = 'Registering cards without explicit types are not allowed. ' \
'Set card_type argument on Card.register() ' \
'or use register() method of explicit card classes.'
raise InvalidCardType(error)
if real_cls == Tag:
error = 'Registering tags without explicit types are not allowed. ' \
'Set tag_type argument on Tag.register() ' \
'or use register() method of explicit tag classes.'
raise InvalidTagType(error)
if hasattr(real_cls, 'validate_parameter'):
real_cls.validate_parameter(parameter)
REGISTRY[uid] = {
'type': card_type,
'type': tag_type,
'alias': alias.strip(),
'parameter': parameter.strip()
}
return Card.all().get(uid)
return Tag.all().get(uid)
@property
def dict(self):
'''
Return the dict version of this card.
Return the dict version of this tag.
:return: The dict version of this card
:return: The dict version of this tag
:rtype: dict
'''
card_dict = {
tag_dict = {
'uid': self.uid,
'alias': self.alias,
'type': self.get_type(),
@ -175,9 +175,9 @@ class Card(object):
}
if hasattr(self, 'scanned'):
card_dict['scanned'] = self.scanned
tag_dict['scanned'] = self.scanned
return card_dict
return tag_dict
@property
def action(self):
@ -195,17 +195,17 @@ class Card(object):
raise NotImplementedError(error % cls)
class TracklistCard(Card):
class TracklistTag(Tag):
'''
Replaces the current tracklist with the URI retreived from the card's
Replaces the current tracklist with the URI retreived from the tag's
parameter.
'''
action = 'replace_tracklist'
class VolumeCard(Card):
class VolumeTag(Tag):
'''
Sets the volume to the percentage value retreived from the card's parameter.
Sets the volume to the percentage value retreived from the tag's parameter.
'''
action = 'set_volume'
@ -225,21 +225,21 @@ class VolumeCard(Card):
raise ValueError('Volume parameter has to be a number between 0 and 100')
class PlayPauseCard(Card):
class PlayPauseTag(Tag):
'''
Pauses or resumes the playback, based on the current state.
'''
action = 'play_pause'
class StopCard(Card):
class StopTag(Tag):
'''
Stops the playback.
'''
action = 'stop'
class ShutdownCard(Card):
class ShutdownTag(Tag):
'''
Shutting down the system.
'''

View file

@ -6,4 +6,4 @@ Threads of Mopidy Pummeluff.
from __future__ import absolute_import, unicode_literals, print_function
from .gpio_handler import *
from .card_reader import *
from .tag_reader import *

View file

@ -6,7 +6,7 @@ Python module for the dedicated Mopidy Pummeluff threads.
from __future__ import absolute_import, unicode_literals, print_function
__all__ = (
'CardReader',
'TagReader',
)
from threading import Thread
@ -16,7 +16,7 @@ from logging import getLogger
import RPi.GPIO as GPIO
from pirc522 import RFID
from mopidy_pummeluff.cards import Card
from mopidy_pummeluff.tags import Tag
from mopidy_pummeluff.sound import play_sound
LOGGER = getLogger(__name__)
@ -28,12 +28,12 @@ class ReadError(Exception):
'''
class CardReader(Thread):
class TagReader(Thread):
'''
Thread which reads RFID cards from the RFID reader.
Thread which reads RFID tags from the RFID reader.
Because the RFID reader algorithm is reacting to an IRQ (interrupt), it is
blocking as long as no card is touched, even when Mopidy is exiting. Thus,
blocking as long as no tag is touched, even when Mopidy is exiting. Thus,
we're running the thread as daemon thread, which means it's exiting at the
same moment as the main thread (aka Mopidy core) is exiting.
'''
@ -47,7 +47,7 @@ class CardReader(Thread):
:param mopidy.core.Core core: The mopidy core instance
:param threading.Event stop_event: The stop event
'''
super(CardReader, self).__init__()
super(TagReader, self).__init__()
self.core = core
self.stop_event = stop_event
self.rfid = RFID()
@ -68,7 +68,7 @@ class CardReader(Thread):
uid = self.read_uid()
if now - prev_time > 1 or uid != prev_uid:
LOGGER.info('Card %s read', uid)
LOGGER.info('Tag %s read', uid)
self.handle_uid(uid)
prev_time = now
@ -81,7 +81,7 @@ class CardReader(Thread):
def read_uid(self):
'''
Return the UID from the card.
Return the UID from the tag.
:return: The hex UID
:rtype: string
@ -101,20 +101,20 @@ class CardReader(Thread):
def handle_uid(self, uid):
'''
Handle the scanned card / retreived UID.
Handle the scanned tag / retreived UID.
:param str uid: The UID
'''
card = Card(uid)
tag = Tag(uid)
if card.registered:
LOGGER.info('Triggering action of registered card')
if tag.registered:
LOGGER.info('Triggering action of registered tag')
play_sound('success.wav')
card(self.core)
tag(self.core)
else:
LOGGER.info('Card is not registered, thus doing nothing')
LOGGER.info('Tag is not registered, thus doing nothing')
play_sound('fail.wav')
card.scanned = time()
CardReader.latest = card
tag.scanned = time()
TagReader.latest = tag

View file

@ -16,15 +16,15 @@ from logging import getLogger
from tornado.web import RequestHandler
from . import cards
from .frontend import CardReader
from . import tags
from .threads import TagReader
LOGGER = getLogger(__name__)
class LatestHandler(RequestHandler): # pylint: disable=abstract-method
'''
Request handler which returns the latest scanned card.
Request handler which returns the latest scanned tag.
'''
def initialize(self, core): # pylint: disable=arguments-differ
@ -39,23 +39,23 @@ class LatestHandler(RequestHandler): # pylint: disable=abstract-method
'''
Handle GET request.
'''
card = CardReader.latest
tag = TagReader.latest
LOGGER.debug('Returning latest card %s', card)
LOGGER.debug('Returning latest tag %s', tag)
if card is None:
if tag is None:
data = {
'success': False,
'message': 'No card scanned yet'
'message': 'No tag scanned yet'
}
else:
data = {
'success': True,
'message': 'Scanned card found',
'message': 'Scanned tag found',
}
data.update(card.dict)
data.update(tag.dict)
self.set_header('Content-type', 'application/json')
self.write(dumps(data))
@ -63,7 +63,7 @@ class LatestHandler(RequestHandler): # pylint: disable=abstract-method
class RegistryHandler(RequestHandler): # pylint: disable=abstract-method
'''
Request handler which returns all registered cards.
Request handler which returns all registered tags.
'''
def initialize(self, core): # pylint: disable=arguments-differ
@ -78,15 +78,15 @@ class RegistryHandler(RequestHandler): # pylint: disable=abstract-method
'''
Handle GET request.
'''
cards_list = []
tags_list = []
for card in cards.Card.all().values():
cards_list.append(card.dict)
for tag in tags.Tag.all().values():
tags_list.append(tag.dict)
data = {
'success': True,
'message': 'Registry successfully read',
'cards': cards_list
'tags': tags_list
}
self.set_header('Content-type', 'application/json')
@ -95,7 +95,7 @@ class RegistryHandler(RequestHandler): # pylint: disable=abstract-method
class RegisterHandler(RequestHandler): # pylint: disable=abstract-method
'''
Request handler which registers an RFID card in the registry.
Request handler which registers an RFID tag in the registry.
'''
def initialize(self, core): # pylint: disable=arguments-differ
@ -111,19 +111,19 @@ class RegisterHandler(RequestHandler): # pylint: disable=abstract-method
Handle POST request.
'''
try:
card = cards.Card.register(
tag = tags.Tag.register(
uid=self.get_argument('uid'),
alias=self.get_argument('alias', None),
parameter=self.get_argument('parameter'),
card_type=self.get_argument('type')
tag_type=self.get_argument('type')
)
data = {
'success': True,
'message': 'Card successfully registered',
'message': 'Tag successfully registered',
}
data.update(card.dict)
data.update(tag.dict)
except ValueError as ex:
self.set_status(400)
@ -144,7 +144,7 @@ class RegisterHandler(RequestHandler): # pylint: disable=abstract-method
class TypesHandler(RequestHandler): # pylint: disable=abstract-method
'''
Request handler which returns all card types.
Request handler which returns all tag types.
'''
def initialize(self, core): # pylint: disable=arguments-differ
@ -161,12 +161,12 @@ class TypesHandler(RequestHandler): # pylint: disable=abstract-method
'''
types = {}
for cls_name in cards.__all__:
card_cls = getattr(cards, cls_name)
if card_cls is not cards.Card:
card_type = cards.Card.get_type(card_cls)
card_doc = card_cls.__doc__.strip().split('.')[0]
types[card_type] = card_doc
for cls_name in tags.__all__:
tag_cls = getattr(tags, cls_name)
if tag_cls is not tags.Tag:
tag_type = tags.Tag.get_type(tag_cls)
tag_doc = tag_cls.__doc__.strip().split('.')[0]
types[tag_type] = tag_doc
data = {
'success': True,

View file

@ -5,20 +5,20 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="style.css" rel="stylesheet" type="text/css">
<title>Pummeluff Card Management</title>
<title>Pummeluff Tag Management</title>
</head>
<body>
<header>
<h1>Pummeluff Card Management</h1>
<h1>Pummeluff Tag Management</h1>
</header>
<main>
<div id="register">
<h2>Register New Card</h2>
<h2>Register New Tag</h2>
<div>
<form id="register-form">
<label for="uid">UID</label>
<input id="uid" name="uid" type="text" placeholder="The unique card ID">
<a id="read-rfid-card" href="#">Read UID from RFID card</a>
<input id="uid" name="uid" type="text" placeholder="The unique tag ID">
<a id="read-rfid-tag" href="#">Read UID from RFID tag</a>
<label for="alias">Alias</label>
<input id="alias" name="alias" type="text" placeholder="Your personal alias / identifier">
<label for="type">Type</label>
@ -26,13 +26,13 @@
</select>
<label for="parameter">Parameter</label>
<input id="parameter" name="parameter" type="text" placeholder="A type-specific parameter">
<button id="register-button" role="submit">✓ Register Card</button>
<button id="register-button" role="submit">✓ Register Tag</button>
</form>
</div>
</div>
<div id="registry">
<h2>Registered Cards</h2>
<div id="cards"></div>
<h2>Registered Tags</h2>
<div id="tags"></div>
</div>
</main>
<script src="script.js"></script>

View file

@ -31,26 +31,26 @@ class API {
{
let callback = function(response)
{
let cardsContainer = document.getElementById('cards')
while(cardsContainer.firstChild)
cardsContainer.removeChild(cardsContainer.firstChild)
let tagsContainer = document.getElementById('tags')
while(tagsContainer.firstChild)
tagsContainer.removeChild(tagsContainer.firstChild)
for(let card of response.cards)
for(let tag of response.tags)
{
let cardElement = document.createElement('div')
cardElement.setAttribute('class', 'card')
let tagElement = document.createElement('div')
tagElement.setAttribute('class', 'tag')
let args = new Array('alias', 'uid', 'type', 'parameter')
for(let arg of args)
{
let spanElement = document.createElement('span')
let value = card[arg] ? card[arg] : '-'
let value = tag[arg] ? tag[arg] : '-'
spanElement.setAttribute('class', arg)
spanElement.innerHTML = value
cardElement.appendChild(spanElement)
tagElement.appendChild(spanElement)
}
cardsContainer.appendChild(cardElement)
tagsContainer.appendChild(tagElement)
}
}
@ -58,7 +58,7 @@ class API {
}
/*
* Refresh the card types.
* Refresh the tag types.
*/
refreshTypes()
@ -82,7 +82,7 @@ class API {
}
/*
* Register a new card.
* Register a new tag.
*/
register()
@ -110,12 +110,12 @@ class API {
}
/*
* Get latest scanned card.
* Get latest scanned tag.
*/
getLatestCard()
getLatestTag()
{
let latest_card = undefined
let latest_tag = undefined
let uid_field = document.getElementById('uid')
let alias_field = document.getElementById('alias')
@ -127,14 +127,14 @@ class API {
parameter_field.value = ''
type_select.selectIndex = 0
let link = document.getElementById('read-rfid-card')
let link = document.getElementById('read-rfid-tag')
link.classList.add('reading')
let do_request = function()
{
let callback = function(response)
{
if(latest_card && response.success && JSON.stringify(response) != JSON.stringify(latest_card))
if(latest_tag && response.success && JSON.stringify(response) != JSON.stringify(latest_tag))
{
uid_field.value = response.uid
@ -154,7 +154,7 @@ class API {
setTimeout(() => do_request(), 1000)
}
latest_card = response
latest_tag = response
}
api.request('/pummeluff/latest/', false, callback)
@ -176,4 +176,4 @@ document.getElementById('register-form').onsubmit = function()
return false;
}
document.getElementById('read-rfid-card').onclick = () => api.getLatestCard()
document.getElementById('read-rfid-tag').onclick = () => api.getLatestTag()

View file

@ -114,24 +114,24 @@ button
margin-top : 10px;
}
#read-rfid-card
#read-rfid-tag
{
text-decoration: none;
color: #fa0;
font-size: 11px;
}
#read-rfid-card.reading {
#read-rfid-tag.reading {
animation: blink 0.5s cubic-bezier(.5, 0, 1, 1) infinite alternate;
}
@keyframes blink { to { opacity: 0.25; } }
/*
* Registered Cards
* Registered Tags
*/
div.card
div.tag
{
display : inline-block;
background-color: #eee;
@ -143,14 +143,14 @@ div.card
line-height : 20px;
}
div.card span.uid,
div.card span.type,
div.card span.parameter
div.tag span.uid,
div.tag span.type,
div.tag span.parameter
{
font-family: Courier New, monospace;
}
div.card span.type
div.tag span.type
{
display : inline-block;
background-color: #888;
@ -162,8 +162,8 @@ div.card span.type
border-radius : 10px;
}
div.card span.alias,
div.card span.parameter
div.tag span.alias,
div.tag span.parameter
{
display: block;
}