From 9f02fba74ae34d8b029766e9e62f37d41d9107db Mon Sep 17 00:00:00 2001 From: Valentin Ochs Date: Tue, 9 Mar 2021 16:09:42 +0100 Subject: [PATCH] Update buildroot stuff --- .gitmodules | 3 + br_external/Config.in | 2 + br_external/external.desc | 1 + br_external/external.mk | 1 + br_external/package/libfreefare_git/Config.in | 12 + .../libfreefare_git/libfreefare_git.mk | 18 + br_external/package/poll_desfire/Config.in | 7 + .../package/poll_desfire/poll_desfire.mk | 19 + door_control | 1 + root_overlay/bin/poll_desfire | Bin 19252 -> 0 bytes root_overlay/bin/test.py | 340 ------------------ 11 files changed, 64 insertions(+), 340 deletions(-) create mode 100644 br_external/Config.in create mode 100644 br_external/external.desc create mode 100644 br_external/external.mk create mode 100644 br_external/package/libfreefare_git/Config.in create mode 100644 br_external/package/libfreefare_git/libfreefare_git.mk create mode 100644 br_external/package/poll_desfire/Config.in create mode 100644 br_external/package/poll_desfire/poll_desfire.mk create mode 160000 door_control delete mode 100755 root_overlay/bin/poll_desfire delete mode 100644 root_overlay/bin/test.py diff --git a/.gitmodules b/.gitmodules index e1d58ff..9324a37 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "buildroot"] path = buildroot url = https://github.com/buildroot/buildroot.git +[submodule "door_control"] + path = door_control + url = ssh://irgit@imaginaerraum.de:2201/apo/DoorControl.git diff --git a/br_external/Config.in b/br_external/Config.in new file mode 100644 index 0000000..6cbca1d --- /dev/null +++ b/br_external/Config.in @@ -0,0 +1,2 @@ +source "$BR2_EXTERNAL_DOOR_PI_PATH/package/poll_desfire/Config.in" +source "$BR2_EXTERNAL_DOOR_PI_PATH/package/libfreefare_git/Config.in" diff --git a/br_external/external.desc b/br_external/external.desc new file mode 100644 index 0000000..f356f48 --- /dev/null +++ b/br_external/external.desc @@ -0,0 +1 @@ +name: DOOR_PI diff --git a/br_external/external.mk b/br_external/external.mk new file mode 100644 index 0000000..76ba2a5 --- /dev/null +++ b/br_external/external.mk @@ -0,0 +1 @@ +include $(sort $(wildcard $(BR2_EXTERNAL_DOOR_PI_PATH)/package/*/*.mk)) diff --git a/br_external/package/libfreefare_git/Config.in b/br_external/package/libfreefare_git/Config.in new file mode 100644 index 0000000..e765dd7 --- /dev/null +++ b/br_external/package/libfreefare_git/Config.in @@ -0,0 +1,12 @@ +config BR2_PACKAGE_LIBFREEFARE_GIT + bool "libfreefare (git)" + depends on BR2_TOOLCHAIN_HAS_THREADS # libusb + select BR2_PACKAGE_OPENSSL + select BR2_PACKAGE_LIBNFC + help + Library for high level manipulation of MIFARE cards. + + http://nfc-tools.org/index.php?title=Libfreefare + +comment "libfreefare needs a toolchain w/ threads" + depends on !BR2_TOOLCHAIN_HAS_THREADS diff --git a/br_external/package/libfreefare_git/libfreefare_git.mk b/br_external/package/libfreefare_git/libfreefare_git.mk new file mode 100644 index 0000000..02c7e3a --- /dev/null +++ b/br_external/package/libfreefare_git/libfreefare_git.mk @@ -0,0 +1,18 @@ +################################################################################ +# +# libfreefare +# +################################################################################ + +LIBFREEFARE_GIT_VERSION = e95406c +# Do not use the github helper here, the generated tarball is *NOT* +# the same as the one uploaded by upstream for the release. +LIBFREEFARE_GIT_SITE = $(call github,nfc-tools,libfreefare,$(LIBFREEFARE_GIT_VERSION)) +LIBFREEFARE_GIT_DEPENDENCIES = host-pkgconf libnfc openssl +LIBFREEFARE_GIT_INSTALL_STAGING = YES +LIBFREEFARE_GIT_LICENSE = LGPL-3.0+ with exception +LIBFREEFARE_GIT_LICENSE_FILES = COPYING +LIBFREEFARE_GIT_CONF_ENV += LIBS=`$(PKG_CONFIG_HOST_BINARY) --libs openssl` +LIBFREEFARE_GIT_AUTORECONF = YES + +$(eval $(autotools-package)) diff --git a/br_external/package/poll_desfire/Config.in b/br_external/package/poll_desfire/Config.in new file mode 100644 index 0000000..53c065c --- /dev/null +++ b/br_external/package/poll_desfire/Config.in @@ -0,0 +1,7 @@ +config BR2_PACKAGE_POLL_DESFIRE + bool "poll_desfire" + select BR2_PACKAGE_LIBFREEFARE_GIT + help + poll desfire cards + + https://git.imaginaerraum.de/apo/PollDesfire diff --git a/br_external/package/poll_desfire/poll_desfire.mk b/br_external/package/poll_desfire/poll_desfire.mk new file mode 100644 index 0000000..d73463c --- /dev/null +++ b/br_external/package/poll_desfire/poll_desfire.mk @@ -0,0 +1,19 @@ +POLL_DESFIRE_VERSION = 0.0.1 +POLL_DESFIRE_SOURCE = poll_desfire_v$(POLL_DESFIRE_VERSION).tar.gz +POLL_DESFIRE_SITE = https://git.imaginaerraum.de/apo/PollDesfire/archive +POLL_DESFIRE_DEPENDENCIES = libfreefare_git host-pkgconf +POLL_DESFIRE_LICENSE = GPL-3.0 + +define POLL_DESFIRE_BUILD_CMDS +$(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) all +endef + +define POLL_DESFIRE_INSTALL_STAGING_CMDS + $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) PREFIX=$(STAGING_DIR) install +endef + +define POLL_DESFIRE_INSTALL_TARGET_CMDS + $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) PREFIX=$(TARGET_DIR) install +endef + +$(eval $(generic-package)) diff --git a/door_control b/door_control new file mode 160000 index 0000000..e48f0f6 --- /dev/null +++ b/door_control @@ -0,0 +1 @@ +Subproject commit e48f0f63385f5990440524c66ba925466f8e292f diff --git a/root_overlay/bin/poll_desfire b/root_overlay/bin/poll_desfire deleted file mode 100755 index f199e2d85c74d694b53318e53c7fc7457f7212cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19252 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 diff --git a/root_overlay/bin/test.py b/root_overlay/bin/test.py deleted file mode 100644 index 9557c91..0000000 --- a/root_overlay/bin/test.py +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/python -import os, serial, socket, subprocess, select, datetime, sys -import paho.mqtt.client as mqcl -import argparse - -OPEN_THRESHOLD = 80 -CLOSED_THRESHOLD = 100 -CLOSED_WANT = 160 - -parser = argparse.ArgumentParser() -parser.add_argument("--serial_port", default="/dev/serial/by-id/usb-Imaginaerraum.de_DoorControl_43363220195053573A002C0-if01") -parser.add_argument("--nfc_fifo", default="/tmp/nfc_fifo") -parser.add_argument("--control_socket", default="/tmp/nfc.sock") -parser.add_argument("--valid_tokens", default="/etc/door_tokens") -parser.add_argument("--log_file", default="/tmp/nfc.log") -parser.add_argument("--state_timeout", type=float, default=10) -parser.add_argument("--repeat_time", type=float, default=5) -parser.add_argument("--mqtt_host", default="10.10.21.2") - -config = parser.parse_args() - -mqttc = mqcl.Client() - -def timestamp(): - return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") - -# Log data to stdout and the log file -def log(*args): - data = "%s %s" % (timestamp(), " ".join(str(i) for i in args)) - lgf.write(data + "\n") - lgf.flush() - print(data) - -def mqtt(topic, msg, persistent = True): - mqttc.publish("door/" + topic, msg, qos=2, retain=persistent) - -# Opens the socket that can control the daemon -# Commands are TBD -def open_control_socket(): - global control_socket - global config - global comm_channels - - if os.path.exists(config.control_socket): - os.unlink(config.control_socket) - - control_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - control_socket.bind(config.control_socket) - control_socket.listen(5) - comm_channels = [] - -# Opens the serial port to talk to the lock actuator -# Might return a failure. In that case, it will be tried again later -def open_serial_port(): - global serial_port - global config - - try: - serial_port = serial.Serial(config.serial_port, timeout=2) - except: - serial_port = None - pass - -# Detected tokens are passed in through a FIFO -def open_nfc_fifo(): - global nfc_fifo - global config - - nfc_fifo = open(config.nfc_fifo, "r") - -# Refresh valid tokens from the configured file -def read_valid_tokens(): - global valid - global config - - try: - log("Loading tokens") - valid = {} - lines =[ s.strip() for s in open(config.valid_tokens, "r").readlines() ] - for l in lines: - l = l.split(' ', 1) - if len(l) > 1: - if l[0] in valid: - log("Warning: Overwriting token %s" % (l[0],)) - log("Got token: %s (%s)" % (l[0], l[1])) - valid[l[0]] = l[1] - else: - log("Got unnamed token: %s" % (l[0],)) - valid[l[0]] = None - except: - valid = {} - log("Error reading token file") - raise - -# Opens the log file for writing -def open_logfile(): - global lgf - global config - - lgf = open(config.log_file, "a+") - -# Actions -IDLE, CLOSE, OPEN_THEN_CLOSE, OPEN, CLOSE_THEN_OPEN = range(5) -state_names = { - OPEN: "open", - CLOSE: "close" -} -action_names = { - IDLE: "idling", - OPEN: "waiting for open door", - CLOSE: "waiting for closed door", - OPEN_THEN_CLOSE: "waiting for open door, then closing again", - CLOSE_THEN_OPEN: "waiting for closed door, then opening again" -} -# Current door state -state = None -state_pos = 0 -# Current target action -action = CLOSE -# Start time of the current action -start_time = None -# How often the action was repeated -repeats = 0 - -# Read the state of the door from the serial port -def poll_door_state(): - global state - global state_pos - global serial_port - serial_port.reset_input_buffer() - serial_port.write(b"R") - data = serial_port.readline().strip().split() - if data[0] == b'pos:': - data = int(data[1]) - if state_pos != data: - mqtt("position/value", data, True) - state_pos = data - changed = False - if data < OPEN_THRESHOLD and state != OPEN: - state = OPEN - changed = True - mqtt("state/value", "open", True) - elif data > CLOSED_THRESHOLD and state != CLOSE: - state = CLOSE - changed = True - mqtt("state/value", "closed", True) - return state - -# Check the door state and send commands through a state machine -def handle_door_state(): - global action, target, serial_port, start_time, repeats - - # Commands associated with each target state - target_state_cmd = { - OPEN: b'O', - CLOSE: b'C' - } - - old_state = state - - # If no serial port, try to open it or return - if not serial_port: - try: - open_serial_port() - except: - return - - # Get new state - poll_door_state() - - # Idle + change = key? - if action == IDLE: - if state != old_state: - log("Door changed unexpectedly:", state_names[state]) - start_time = datetime.datetime.now() - if start_time and (datetime.datetime.now() - start_time).total_seconds() >= config.state_timeout: - start_time = None - if state_pos >= CLOSED_THRESHOLD and state_pos < CLOSED_WANT: - log("Closing door a bit more") - serial_port.write(target_state_cmd[CLOSE]) - return - - # Target state, next action, timeout action - actions = { - OPEN: (OPEN, IDLE, CLOSE_THEN_OPEN ), - CLOSE: (CLOSE, IDLE, OPEN_THEN_CLOSE ), - OPEN_THEN_CLOSE: (OPEN, CLOSE, CLOSE ), - CLOSE_THEN_OPEN: (CLOSE, OPEN, OPEN ) - } - - if start_time == None: - start_time = datetime.datetime.now() - serial_port.write(target_state_cmd[actions[action][0]]) - - # Target state reached - if state == actions[action][0]: - # Select next action, reset start time and repetitions - action = actions[action][1] - start_time = datetime.datetime.now() - repeats = 0 - # On idle, we're done - if action == IDLE: - log("Reached target position:", state_names[state]) - return - - # Execution time - t = (datetime.datetime.now() - start_time).total_seconds() - if t >= config.state_timeout: - # Timeout -> switch to timeout action - action = actions[action][2] - start_time = None - repeats = 0 - log("Timeout. Switching to", action_names[action]) - elif t >= (1 + repeats) * config.repeat_time: - # Repeat every couple of seconds - repeats += 1 - serial_port.write(target_state_cmd[actions[action][0]]) - log("Repeating command:", target_state_cmd[actions[action][0]]) - -def open_door(): - global action - global start_time - log("Opening the door") - action = OPEN - start_time = None - mqtt("state/target", "open", True) - handle_door_state() - -def close_door(): - global action - global start_time - log("Closing the door") - action = CLOSE - start_time = None - mqtt("state/target", "closed", True) - handle_door_state() - -def toggle_door_state(): - global state, action - if state == CLOSE: - open_door() - else: - close_door() - -def handle_nfc_token(token = None): - global valid - - if not token: - token = nfc_fifo.readline() - if token == "": - open_nfc_fifo() - - token = token.strip() - if token in valid: - name = valid[token] - if name: - name = "%s (%s)" % (token, name) - else: - name = token - log("Valid token: %s" % name) - toggle_door_state() - else: - log("Invalid token:", token) - mqtt("token/last_invalid", "%s;%s" % (timestamp(), token)) - -class LineBuffer(object): - def __init__(self, f, handler): - self.data = b'' - self.f = f - self.handler = handler - - def update(self): - data = self.f.recv(1024) - if not data: - return False - self.data += data - d = self.data.split(b'\n') - d, self.data = d[:-1], d[-1] - for i in d: - self.handler(self.f, i) - return True - -def handle_cmd(comm, data): - cmd = data.decode('utf8').split() - cmd, args = cmd[0], cmd[1:] - log("Got command:", data) - - send = lambda x: comm.send(x.encode('utf8')) - - if cmd == 'fake': - log("Faking token", args[0]) - send("Handling token\n") - handle_nfc_token(args[0]) - elif cmd == 'open': - log("Control socket opening door") - send("Opening door") - open_door() - elif cmd == 'close': - log("Control socket closing door") - send("Closing door") - close_door() - elif cmd == 'rld': - log("Reloading tokens") - send("Reloading tokens") - read_valid_tokens() - elif cmd == 'stat': - send("Door status is %s, position is %d. Current action: %s (%g seconds ago)\n" % ( - state_names.get(state, "None"), - state_pos, - action_names[action], - (datetime.datetime.now() - start_time).total_seconds())) - -open_logfile() -read_valid_tokens() -open_nfc_fifo() -open_serial_port() -open_control_socket() - -mqttc.on_connect = lambda client, userdata, flags, rc: log("Connected to mqtt host with result %s" % (str(rc), )) -mqttc.connect_async(config.mqtt_host, keepalive = 60) -mqttc.loop_start() - -buffers = {} -while True: - readable = select.select([ nfc_fifo, control_socket ] + comm_channels, [], [], 1)[0] - - for c in readable: - if c == nfc_fifo: - handle_nfc_token() - elif c == control_socket: - log("Got connection") - sock = control_socket.accept()[0] - buffers[sock] = LineBuffer(sock, handle_cmd) - comm_channels += [sock] - else: - if not buffers[c].update(): - log("Lost connection") - del buffers[c] - comm_channels.remove(c) - handle_door_state()