--- /dev/null
+__pycache__/
+dist/
+controlpi_nfc.egg-info/
+venv/
--- /dev/null
+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.
--- /dev/null
+# 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.
--- /dev/null
+"""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)
--- /dev/null
+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",
+ ],
+)