From: Benjamin Braatz Date: Mon, 22 Aug 2022 12:59:58 +0000 (+0200) Subject: Initial commit X-Git-Url: http://git.graph-it.com/?a=commitdiff_plain;h=944fdc68db9d00a2ce6c392b1e481126bdcc83cd;p=graphit%2Fcontrolpi-nfc.git Initial commit --- 944fdc68db9d00a2ce6c392b1e481126bdcc83cd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4b769b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__/ +dist/ +controlpi_nfc.egg-info/ +venv/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ebb8ac1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021 Graph-IT GmbH + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5643f9 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# ControlPi Plugin for NFC Card Reader +This distribution package contains a plugin for the +[ControlPi system](https://docs.graph-it.com/graphit/controlpi), that +listens on a USB NFC card reader and pushes the identities seen there on +the ControlPi message bus. + +Documentation (in German) can be found at [doc/index.md](doc/index.md) in +the source repository and at +[https://docs.graph-it.com/graphit/controlpi-nfc/](https://docs.graph-it.com/graphit/controlpi-nfc/). +Code documentation (in English) including doctests is contained in the +source files. diff --git a/controlpi_plugins/nfc.py b/controlpi_plugins/nfc.py new file mode 100644 index 0000000..e481eef --- /dev/null +++ b/controlpi_plugins/nfc.py @@ -0,0 +1,79 @@ +"""ControlPi Plugin for NFC Card Reader.""" +import asyncio + +from smartcard.CardMonitoring import CardMonitor, CardObserver # type: ignore + +from controlpi import BasePlugin, Message, MessageTemplate +from controlpi.baseplugin import JSONSchema + + +class ControlPiCardObserver(CardObserver): + """Card Observer that calls ControlPi plugin on changes.""" + + def __init__(self, plugin): + """Register the plugin to be called back.""" + self._plugin = plugin + super().__init__() + + def update(self, observable, handlers): + """Get the ID of the NFC card and call back plugin.""" + added, removed = handlers + for card in added: + connection = card.createConnection() + connection.connect() + data, sw1, sw2 = connection.transmit([0xFF, 0xCA, + 0x00, 0x00, 0x00]) + identifier = bytes(data).hex() + self._plugin._set_state(True, identifier) + for card in removed: + self._plugin._set_state(False, "") + + +class NFCReader(BasePlugin): + """ControlPi plugin for NFC card reader.""" + + CONF_SCHEMA: JSONSchema = {} + + def process_conf(self) -> None: + """Register bus client.""" + self._state = False + self._card = "" + self.bus.register(self.name, 'NFCReader', + [MessageTemplate({'event': + {'const': 'changed'}, + 'state': + {'type': 'boolean'}, + 'card': + {'type': 'string'}}), + MessageTemplate({'state': + {'type': 'boolean'}, + 'card': + {'type': 'string'}})], + [([MessageTemplate({'target': + {'const': self.name}, + 'command': + {'const': 'get state'}})], + self._get_state)]) + + async def _get_state(self, message) -> None: + await self.bus.send(Message(self.name, {'state': self._state, + 'card': self._card})) + + def _set_state(self, state: bool, card: str) -> None: + changed = False + if card != self._card: + self._card = card + changed = True + if state != self._state: + self._state = state + changed = True + if changed: + self.bus.send_nowait(Message(self.name, {'event': 'changed', + 'state': state, + 'card': card})) + + async def run(self) -> None: + """Run no code proactively.""" + self._monitor = CardMonitor() + self._observer = ControlPiCardObserver(self) + self._monitor.addObserver(self._observer) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..fdd5dd8 --- /dev/null +++ b/setup.py @@ -0,0 +1,25 @@ +import setuptools + +with open("README.md", "r") as readme_file: + long_description = readme_file.read() + +setuptools.setup( + name="controlpi-nfc", + version="0.2.0", + author="Graph-IT GmbH", + author_email="info@graph-it.com", + description="ControlPi Plugin for NFC Card Reader", + long_description=long_description, + long_description_content_type="text/markdown", + url="http://docs.graph-it.com/graphit/controlpi-nfc", + packages=["controlpi_plugins"], + install_requires=[ + "pyscard", + "controlpi @ git+git://git.graph-it.com/graphit/controlpi.git", + ], + classifiers=[ + "Programming Language :: Python", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], +)