Initial commit
authorBenjamin Braatz <bb@bbraatz.eu>
Mon, 22 Aug 2022 12:59:58 +0000 (14:59 +0200)
committerBenjamin Braatz <bb@bbraatz.eu>
Mon, 22 Aug 2022 12:59:58 +0000 (14:59 +0200)
.gitignore [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README.md [new file with mode: 0644]
controlpi_plugins/nfc.py [new file with mode: 0644]
setup.py [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c4b769b
--- /dev/null
@@ -0,0 +1,4 @@
+__pycache__/
+dist/
+controlpi_nfc.egg-info/
+venv/
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
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 (file)
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 (file)
index 0000000..e481eef
--- /dev/null
@@ -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 (file)
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",
+    ],
+)