updated single reader example

This commit is contained in:
Kai Jan Kriegel 2022-06-16 16:01:10 +02:00
parent 233b9af159
commit 59210d1f34
3 changed files with 99 additions and 54 deletions

View File

@ -2,6 +2,7 @@ import asyncio
import socket import socket
import ssl import ssl
import capnp import capnp
import logging
connection_capnp = capnp.load('schema/connection.capnp') connection_capnp = capnp.load('schema/connection.capnp')
authenticationsystem_capnp = capnp.load('schema/authenticationsystem.capnp') authenticationsystem_capnp = capnp.load('schema/authenticationsystem.capnp')
@ -40,25 +41,23 @@ async def connect(host, port, user, pw):
# Start TwoPartyClient using TwoWayPipe (takes no arguments in this mode) # Start TwoPartyClient using TwoWayPipe (takes no arguments in this mode)
client = capnp.TwoPartyClient() client = capnp.TwoPartyClient()
cap = client.bootstrap().cast_as(connection_capnp.Bootstrap)
# Assemble reader and writer tasks, run in the background # Assemble reader and writer tasks, run in the background
coroutines = [myreader(client, reader), mywriter(client, writer)] coroutines = [myreader(client, reader), mywriter(client, writer)]
asyncio.gather(*coroutines, return_exceptions=True) asyncio.gather(*coroutines, return_exceptions=True)
auth = cap.authenticationSystem().authenticationSystem boot = client.bootstrap().cast_as(connection_capnp.Bootstrap)
req = auth.start_request() auth = await boot.createSession("PLAIN").a_wait()
req.request.mechanism = "PLAIN" p = "\0" + user + "\0" + pw
req.request.initialResponse.initial = "\0" + user + "\0" + pw response = await auth.authentication.step(p).a_wait()
rep_prom = req.send() if response.which() == 'successful':
response = await rep_prom.a_wait() return response.successful.session
if response.response.outcome.result == "successful":
return cap
else: else:
print("Auth failed") print("Authentication failed!")
return None return None
async def connect_with_fabfire_initial(host, port, uid): async def connect_with_fabfire_initial(host, port, uid):
# Setup SSL context # Setup SSL context
ctx = ssl.create_default_context( ctx = ssl.create_default_context(
@ -79,38 +78,32 @@ async def connect_with_fabfire_initial(host, port, uid):
# Start TwoPartyClient using TwoWayPipe (takes no arguments in this mode) # Start TwoPartyClient using TwoWayPipe (takes no arguments in this mode)
client = capnp.TwoPartyClient() client = capnp.TwoPartyClient()
cap = client.bootstrap().cast_as(connection_capnp.Bootstrap)
# Assemble reader and writer tasks, run in the background # Assemble reader and writer tasks, run in the background
coroutines = [myreader(client, reader), mywriter(client, writer)] coroutines = [myreader(client, reader), mywriter(client, writer)]
asyncio.gather(*coroutines, return_exceptions=True) asyncio.gather(*coroutines, return_exceptions=True)
auth = cap.authenticationSystem().authenticationSystem boot = client.bootstrap().cast_as(connection_capnp.Bootstrap)
req = auth.start_request() auth = await boot.createSession("X-FABFIRE").a_wait()
req.request.mechanism = "X-FABFIRE" response = await auth.authentication.step(uid).a_wait()
req.request.initialResponse.initial = uid logging.debug(f"got response type: {response.which()}")
rep_prom = req.send() if response.which() == "challenge":
response = await rep_prom.a_wait() logging.debug(f"challenge: {response.challenge}")
print(response.response.which()) return auth, response.challenge
if response.response.which() == "challence":
print(f"challenge: {response.response.challence}")
return auth, response.response.challence, cap
else: else:
print(f"Auth failed: {response.response.outcome.result}, additional info: {response.response.outcome.helpText}") logging.error(f"Auth failed: {response.failed.code}, additional info: {response.failed.additionalData}")
return None return None
async def connect_with_fabfire_step(auth, msg): async def connect_with_fabfire_step(auth, msg):
req = auth.step_request() response = await auth.authentication.step(msg).a_wait()
req.response = msg if response.which() == "challenge":
rep_prom = req.send() logging.debug(f"challenge: {response.challenge}")
response = await rep_prom.a_wait() return response.challenge, None # auth cap, challenge, not done
if response.response.which() == "challence": elif response.which() == "successful":
print(f"challenge: {response.response.challence}") logging.info(f"Auth completed successfully! Got additional Data: {response.successful.additionalData}")
return response.response.challence, False # auth cap, challenge, not done return response.successful.additionalData, response.successful.session # dont care, message, we are done
elif response.response.outcome.result == "successful":
print(f"Auth completed successfully! Got additional Data: {response.response.outcome.additionalData.additional}")
return response.response.outcome.additionalData.additional, True # dont care, message, we are done
else: else:
print(f"Auth failed: {response.response.outcome.result}, additional info: {response.response.outcome.helpText}") logging.error(f"Auth failed: {response.failed.code}, additional info: {response.failed.additionalData}")
return None return None

View File

@ -1,43 +1,77 @@
import asyncio import asyncio
import logging
from asyncio_mqtt import Client from asyncio_mqtt import Client
import json import json
import fabapi import fabapi
from timer import Timer
BFFHD_HOST = "127.0.0.1"
MQTT_HOST = "127.0.0.1"
MACHINE_URN = ""
READER_ID = ""
async def main(): async def main():
done = False done = False
cap = None auth_cap = None
auth = None session = None
msg = None msg = None
async with Client("192.168.178.31") as client: async with Client(MQTT_HOST) as client:
await client.publish("/cmnd/reader", payload='{"Cmd":"haltPICC"}', qos=2, retain=False) await client.publish("/cmnd/reader", payload='{"Cmd":"haltPICC"}', qos=2, retain=False)
await client.publish("/cmnd/reader", payload='{"Cmd": "message", "MssgID": 0, "AddnTxt":" Karte auflegen"}', qos=2, retain=False) await client.publish("/cmnd/reader", payload='{"Cmd": "message", "MssgID": 0, "AddnTxt":" Karte auflegen"}', qos=2, retain=False)
async with client.filtered_messages("/rfid_reader/111") as messages: async with client.filtered_messages(f"/rfid_reader/{READER_ID}") as messages:
await client.subscribe("/rfid_reader/#") await client.subscribe("/rfid_reader/#")
async for message in messages: async for message in messages:
if not auth: response_for_reader = None
auth, msg, cap = await fabapi.connect_with_fabfire_initial("192.168.178.31", 59661, message.payload) if not auth_cap:
elif not done: timeout_timer = Timer(10, lambda: handle_timeout(client))
msg, done = await fabapi.connect_with_fabfire_step(auth, message.payload) auth_cap, response_for_reader = await fabapi.connect_with_fabfire_initial(
if done: BFFHD_HOST, 59961, message.payload)
await client.publish("/cmnd/reader", payload='{"Cmd":"haltPICC"}', qos=2, retain=False) elif not session:
ms = await cap.machineSystem().a_wait() response_for_reader, session = await fabapi.connect_with_fabfire_step(auth_cap,
info = await ms.machineSystem.info().a_wait() message.payload)
ma = await info.info.getMachineURN("urn:fabaccess:resource:Testmachine").a_wait() if session:
if ma.machine.state == "inUse": timeout_timer.cancel()
await ma.machine.inuse.giveBack().a_wait() await client.publish(f"/cmnd/reader/{READER_ID}", payload='{"Cmd":"haltPICC"}', qos=2,
retain=False)
info = session.machineSystem.info
ma = await info.getMachineURN(f"{MACHINE_URN}").a_wait()
if ma.which() == "just":
ma = ma.just
else: else:
await ma.machine.use.use().a_wait() logging.critical(
done = False f"Could not get machine {MACHINE_URN}. Machine does not exist or insufficient permissions")
cap = None raise Exception(
auth = None f"Could not get machine {MACHINE_URN}. Machine does not exist or insufficient permissions")
msg = None
if ma.state == "inUse":
await ma.inuse.giveBack().a_wait()
await client.publish(f"/cmnd/reader/{READER_ID}",
payload='{"Cmd":"message","MssgID":0,"AddnTxt":""}', qos=2,
retain=False)
else:
await ma.use.use().a_wait()
await client.publish(f"/cmnd/reader/{READER_ID}", payload=response_for_reader, qos=2,
retain=False)
await asyncio.sleep(2)
await client.publish(f"/cmnd/reader/{READER_ID}",
payload='{"Cmd":"message","MssgID":3,"AddnTxt":""}', qos=2,
retain=False)
session = None
auth_cap = None
response_for_reader = None
if response_for_reader:
await client.publish(f"/cmnd/reader/{READER_ID}", payload=response_for_reader, qos=2, retain=False)
await client.publish("/cmnd/reader", payload=msg, qos=2, retain=False) await client.publish("/cmnd/reader", payload=msg, qos=2, retain=False)
async def handle_timeout(client, reader_id):
await client.publish(f"/cmnd/reader/{reader_id}", payload='{"Cmd":"haltPICC"}', qos=2,
retain=False)
logging.critical(f"authentication timed out on reader {reader_id}")
if __name__ == "__main__": if __name__ == "__main__":
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()

18
timer.py Normal file
View File

@ -0,0 +1,18 @@
import asyncio
from typing import Callable
import asyncio_mqtt
class Timer:
def __init__(self, timeout: int, callback: Callable):
self._timeout = timeout
self._callback = callback
self._task = asyncio.ensure_future(self._job())
async def _job(self):
await asyncio.sleep(self._timeout)
await self._callback()
def cancel(self):
self._task.cancel()