From 8b10defed2438a28418a0c885846827535701239 Mon Sep 17 00:00:00 2001 From: Luca Lutz Date: Fri, 4 Nov 2022 00:15:23 +0100 Subject: [PATCH] First work adding DB --- FabAccess.sql | 5 --- docker-compose.yml | 1 - fab_access/config.py | 33 ++++++++++++-------- fab_access/main.py | 11 +++++-- fab_access/sql_handler.py | 65 +++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 +-- 6 files changed, 96 insertions(+), 23 deletions(-) delete mode 100644 FabAccess.sql create mode 100644 fab_access/sql_handler.py diff --git a/FabAccess.sql b/FabAccess.sql deleted file mode 100644 index 4cfdb37..0000000 --- a/FabAccess.sql +++ /dev/null @@ -1,5 +0,0 @@ -DROP DATABASE IF EXISTS FabAccess; -CREATE DATABASE IF NOT EXISTS FabAccess; -USE FabAccess; -CREATE TABLE `ReaderPlug` (`ReaderID` INT NOT NULL , `PlugName` VARCHAR(255) NOT NULL, `PermissionPath` VARCHAR(255) NOT NULL, `Status` BOOLEAN NOT NULL, `LastUser` VARCHAR(255) NOT NULL) ENGINE = InnoDB; -INSERT INTO `ReaderPlug` (`ReaderID`, `PlugName`, `PermissionPath`, `Status`, `LastUser`) VALUES ("001", "lasercutter", "sfz.lasercutter.trotec", 0, "luca.lutz"); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6a38032..cf082e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,6 @@ services: DB_PASSWORD: ${DB_PASSWORD:?err} DB_DATABASE: ${DB_DATABASE:?err} # MQTT config - MQTT_PORT: ${MQTT_PORT:?err} MQTT_USERNAME: ${MQTT_USERNAME:?err} MQTT_PASSWORD: ${MQTT_PASSWORD:?err} MQTT_BROKER: ${MQTT_BROKER:?err} diff --git a/fab_access/config.py b/fab_access/config.py index 3ddd366..ecb8aa6 100644 --- a/fab_access/config.py +++ b/fab_access/config.py @@ -1,18 +1,25 @@ import os class Config: - mqtt_broker = os.getenv('MQTT_BROKER') - mqtt_port = int(os.getenv('MQTT_PORT')) - mqtt_client_id = os.getenv('MQTT_CLIENT') - mqtt_user_name = os.getenv('MQTT_USERNAME') - mqtt_password = os.getenv('MQTT_PASSWORD') - keycloak_url = os.getenv('KEYCLOAK_URL') - keycloak_user_name = os.getenv('KEYCLOAK_USER_NAME') - keycloak_password = os.getenv('KEYCLOAK_USER_PW') - keycloak_realm = os.getenv('KEYCLOAK_REALM') + def _read_from_env(key: str, default: str = None) -> str: + if (value := os.environ.get(key, default)) is not None: + return value + raise Exception(f'[Config] Error: Cannot find required value {key}') - db_host_name = os.getenv('DB_HOSTNAME') - db_user_name = os.getenv('DB_USERNAME') - db_password = os.getenv('DB_PASSWORD') - db_database = os.getenv('DB_DATABASE') \ No newline at end of file + mqtt_broker = _read_from_env('MQTT_BROKER') + mqtt_port = int(_read_from_env('MQTT_PORT','1883')) + mqtt_client_id = _read_from_env('MQTT_CLIENT') + mqtt_user_name = _read_from_env('MQTT_USERNAME') + mqtt_password = _read_from_env('MQTT_PASSWORD') + + keycloak_url = _read_from_env('KEYCLOAK_URL') + keycloak_user_name = _read_from_env('KEYCLOAK_USER_NAME') + keycloak_password = _read_from_env('KEYCLOAK_USER_PW') + keycloak_realm = _read_from_env('KEYCLOAK_REALM') + + db_host_name = _read_from_env('DB_HOSTNAME') + db_user_name = _read_from_env('DB_USERNAME') + db_password = _read_from_env('DB_PASSWORD') + db_database = _read_from_env('DB_DATABASE') + db_port = int(_read_from_env('DB_PORT','5432')) \ No newline at end of file diff --git a/fab_access/main.py b/fab_access/main.py index 5e895a2..35e6ad7 100644 --- a/fab_access/main.py +++ b/fab_access/main.py @@ -3,7 +3,7 @@ import os from config import Config from mqtt_client import MqttHandler from keycloak_handler import KeycloakHandler - +from sql_handler import SQLHandler def has_permission(user_permissions, machine_id): parsed_permissions = [permission.split('.') for permission in user_permissions] @@ -52,6 +52,9 @@ def handle_request(msg, client): # - get last_user from database # - get machine_status from database, is 0 for off, 1 for on # - get plug_id from database + + print(SQLHandler.get_machine_data(reader_id)) + machine_id = 'space.foo.lazerspacer' last_user = 'foo.bar' machine_status = 0 # or 1 @@ -92,9 +95,13 @@ def handle_request(msg, client): def main(): MqttHandler.setup(handle_request) + KeycloakHandler.login() + SQLHandler.setup() + MqttHandler.connect_mqtt() MqttHandler.subscribe("/rfid_reader/#") - KeycloakHandler.login() + SQLHandler.init_db() + MqttHandler.loop() if __name__ == '__main__': diff --git a/fab_access/sql_handler.py b/fab_access/sql_handler.py new file mode 100644 index 0000000..a1058d3 --- /dev/null +++ b/fab_access/sql_handler.py @@ -0,0 +1,65 @@ +import psycopg2 +from psycopg2 import sql, extensions + +from config import Config + +class SQLHandler: + @staticmethod + def setup(): + SQLHandler.cursor = None + SQLHandler.conn = None + SQLHandler.conn = psycopg2.connect(host=Config.db_host_name, user=Config.db_user_name, port=Config.db_port, password=Config.db_password, dbname=Config.db_database) + # get the isolation leve for autocommit + autocommit = extensions.ISOLATION_LEVEL_AUTOCOMMIT + print ("ISOLATION_LEVEL_AUTOCOMMIT:", extensions.ISOLATION_LEVEL_AUTOCOMMIT) + + # set the isolation level for the connection's cursors + # will raise ActiveSqlTransaction exception otherwise + SQLHandler.conn.set_isolation_level( autocommit ) + SQLHandler.cursor = SQLHandler.conn.cursor() + + @staticmethod + def get_machine_data(reader_id): + # TODO Database + # - get machine_id from database + # - get last_user from database + # - get machine_status from database, is 0 for off, 1 for on + # - get plug_id from database + SQLHandler.cursor.execute("SELECT machine_id,last_user,machine_status,plug_id FROM readerplug WHERE reader_id = %s;", (reader_id,)) + data = [row for row in SQLHandler.cursor.fetchall()] + print(data) + return { + 'machine_id': data[0], + 'last_user': data[1], + 'machine_status': data[2], + 'plug_id': data[3] + } + + + @staticmethod + def init_db(): + SQLHandler.cursor.execute("SELECT datname FROM pg_database;") + dbs = [row[0] for row in SQLHandler.cursor.fetchall()] + if not (Config.db_database in dbs): + print(f"Missing database ({Config.db_database}) -> creating new db") + SQLHandler.cursor.execute(sql.SQL("CREATE DATABASE {};").format(sql.Identifier( Config.db_database ))) + else: + print(f"Found DB {Config.db_database} -> Using existing one") + + SQLHandler.cursor.execute("SELECT * FROM pg_catalog.pg_tables\ + WHERE schemaname != 'pg_catalog' AND \ + schemaname != 'information_schema';") + tables = [row[1] for row in SQLHandler.cursor.fetchall()] + if not ("readerplug" in tables): + print("Missing table -> creating new table in db") + SQLHandler.cursor.execute("\ + CREATE TABLE readerplug (\ + reader_id int NOT NULL, \ + plug_id varchar(255) NOT NULL, \ + machine_id varchar(255) NOT NULL, \ + machine_status boolean NOT NULL, \ + last_user varchar(255) NOT NULL \ + )") + else: + print("Found Table -> Using existing one") + SQLHandler.conn.commit() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index c57afff..6a6ef13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ keycloak_wrapper paho-mqtt -psycopg[binary] -python-keycloak +psycopg2-binary +python-keycloak \ No newline at end of file