mirror of
https://github.com/elem74/fabaccess-config-generator.git
synced 2025-03-12 06:41:45 +01:00
2024.5
This commit is contained in:
parent
39bf58928d
commit
1a7f4037e5
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
__pycache__
|
||||
output/*
|
||||
dev.py
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Wolfram
|
||||
Copyright (c) 2024 Wolfram Günther
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
254
README.md
254
README.md
@ -1,2 +1,254 @@
|
||||
# fabaccess-config-generator
|
||||
# fabaccess-config-generator <!-- omit from toc -->
|
||||
Automatische Generierung von Maschinen, Rollen, Aktoren und Aktor-Verbindungen auf Basis einer Maschinenliste im CSV-Format.
|
||||
|
||||
- [Funktionsumfang](#funktionsumfang)
|
||||
- [Funktionsweise](#funktionsweise)
|
||||
- [Bereichskonzept](#bereichskonzept)
|
||||
- [Rollenkonzept \& Berechtigungen](#rollenkonzept--berechtigungen)
|
||||
- [Beispielwerkstatt](#beispielwerkstatt)
|
||||
- [Auszug aus der CSV](#auszug-aus-der-csv)
|
||||
- [Werkstattdiagramm](#werkstattdiagramm)
|
||||
- [Erklärung der Konfiguration](#erklärung-der-konfiguration)
|
||||
- [Nutzung des Python-Skripts](#nutzung-des-python-skripts)
|
||||
- [Anlegen von Maschinen (maschinenliste.csv)](#anlegen-von-maschinen-maschinenlistecsv)
|
||||
- [Einstellungen des Skripts (settings.ini)](#einstellungen-des-skripts-settingsini)
|
||||
- [Aktorenbibliothek (actors.ini)](#aktorenbibliothek-actorsini)
|
||||
- [Beispiel für die Erstellung eines Aktor-Typs](#beispiel-für-die-erstellung-eines-aktor-typs)
|
||||
- [Verschiedene Informationen](#verschiedene-informationen)
|
||||
- [ID-Schema für Rollen, Maschinen und Aktoren](#id-schema-für-rollen-maschinen-und-aktoren)
|
||||
- [Ausnahme: Alternativrollen](#ausnahme-alternativrollen)
|
||||
- [Aktualisierung einer bestehenden bffh.dhall](#aktualisierung-einer-bestehenden-bffhdhall)
|
||||
|
||||
|
||||
# Funktionsumfang
|
||||
- Generierung von Maschinen
|
||||
- Generierung von Rollen
|
||||
- Generierung von Aktoren
|
||||
- Generierung von einfachen Aktoren-Verbindungen
|
||||
- Export einer gesonderten Rollenliste (interne ID & Anzeigename der Rolle)
|
||||
- Abbildung der Struktur mittels Mermaid-Diagramm
|
||||
- Direkte Aktualisierung einer bestehenden `bffh.dhall`
|
||||
|
||||
# Funktionsweise
|
||||
Die CSV-Zeile enthält pro Zeile einen Eintrag für eine Maschine. Neben Angaben zur Maschine selbst (ID, Wiki-URL etc.) werden Angaben zum Bereich vermerkt, in dem sich die Maschine befindet. Aus den Angaben zu den Bereichen werden dann alle Rollen abgeleitet.
|
||||
|
||||
## Bereichskonzept
|
||||
Innerhalb der globalen Infrastruktur existieren die folgenden Einheit:
|
||||
- **Domäne**: Fasst die gesamte Werkstatt zusammen und unterteilt sich in mehrere Bereiche (=Gewerke). Bei Bedarf können auch mehrere Domänen definiert werden.
|
||||
- **Bereich**: Entspricht üblicherweise einem Gewerk (z.B. Holzwerkstatt, Siebdruck), aber kann auch genutzt werden, um andere Maschinen zu gruppieren (z.B. Eingangstüren). Ein Bereich kann bei Bedarf über Unterbereiche verfügen.
|
||||
- **Unterbereich**: Ein Unterbereich ermöglicht einzelne Maschinen/ Maschinengruppen separat zu behandeln.
|
||||
|
||||
## Rollenkonzept & Berechtigungen
|
||||
| Rolle | Berechtigungen | Infrastruktur | Domäne | Bereich | Unterbereich | Spezifische Maschinen |
|
||||
| --------------- | ---------------------------------------------------------------------- | ------------- | -------- | ------- | ------------ | --------------------- |
|
||||
| Administrator | - *bffh.users.manage*<br> - *bffh.users.info*<br> - *bffh.users.admin* | Ja | - | - | - | - |
|
||||
| Manager | - *read*<br> - *write*<br> - *disclose*<br> - *manage* | - | Optional | Ja | Optional | - |
|
||||
| Benutzer | - *read*<br> - *write*<br> - *disclose* | - | - | Ja | Ja | - |
|
||||
| Alternativrolle | - *read*<br> - *write*<br> - *disclose* | - | - | - | - | Ja |
|
||||
|
||||
- Berechtigungen werden grundsätzlich via Wildcard vergeben und gelten somit für eine gesamte Einheit (Infrastruktur/ Domäne/ Bereich/ Unterbereich).
|
||||
- Berechtigungen für Bereich und Unterbereich sind getrennt. Benutzer eines Bereichs haben keinen Zugriff auf Maschinen eines Unterbereichs (und umgekehrt).
|
||||
- **Ausnahme: Alternativrolle**
|
||||
- Die Alternativrolle dient der Erstellung einer bereichsübergreifenden Berechtigung für einzelne Maschine. Diese wird vergeben, wenn in mehreren Bereichen die gleiche (bzw. eine ähnliche) Maschinen existieren und dafür nur eine Einweisung notwendig ist.
|
||||
|
||||
## Beispielwerkstatt
|
||||
|
||||
Die CSV-Datei `beispielwerkstatt.csv` und das Diagramm `beispielwerkstatt.svg` befinden sich im Unterordner `docs`.
|
||||
|
||||
### Auszug aus der CSV
|
||||
|
||||
| Name Domäne | Name Bereich | Name Unterbereich | Name Maschine | Manager Unterbereich | Name Alternativrolle |
|
||||
| ----------------- | --------------- | ----------------- | ------------------- | -------------------- | -------------------- |
|
||||
| Beispielwerkstatt | Holzwerkstatt | Bandsäge | Bandsäge | | |
|
||||
| Beispielwerkstatt | Holzwerkstatt | Hobelmaschine | Hobelmaschine | | |
|
||||
| Beispielwerkstatt | Holzwerkstatt | CNC-Fräse | CNC-Fräse | | |
|
||||
| Beispielwerkstatt | Holzwerkstatt | | Kappsäge | | |
|
||||
| Beispielwerkstatt | Holzwerkstatt | | Bandschleifer | | |
|
||||
| Beispielwerkstatt | Holzwerkstatt | | Ständerbohrmaschine | | |
|
||||
| Beispielwerkstatt | Textilwerkstatt | | Nähmaschine 1 | | |
|
||||
| Beispielwerkstatt | Textilwerkstatt | | Nähmaschine 2 | | |
|
||||
| Beispielwerkstatt | FabLab | 3D-Druck | 3D-Drucker 1 | x | |
|
||||
| Beispielwerkstatt | FabLab | 3D-Druck | 3D-Drucker 2 | x | |
|
||||
| Beispielwerkstatt | FabLab | Laser | Lasercutter | x | |
|
||||
| Beispielwerkstatt | FabLab | Laser | Kühlung | x | |
|
||||
| Beispielwerkstatt | Siebdruck | | SD-Belichter | | |
|
||||
| Beispielwerkstatt | Siebdruck | | A3-Drucker | | Druckernutzung |
|
||||
| Beispielwerkstatt | Büro | | Drucker | | Druckernutzung |
|
||||
|
||||
|
||||
### Werkstattdiagramm
|
||||

|
||||
|
||||
|
||||
### Erklärung der Konfiguration
|
||||
- **Textilwerkstatt**
|
||||
- In der Textilwerkstatt verwaltet eine Person den gesamten Bereich.
|
||||
- Eine Einweisung deckte alle Maschinen ab, daher gibt es keine Unterbereiche.
|
||||
- **Holzwerkstatt**
|
||||
- In der Holzwerkstatt verwaltet eine Person den gesamten Bereich.
|
||||
- Es gibt unterschiedliche Einweisungen:
|
||||
- Holzwerkstatt Allgemein (Kappsäge, Bandschleifer, Ständerbohrmaschine)
|
||||
- Bandsäge
|
||||
- Hobelmaschine
|
||||
- CNC-Fräse
|
||||
- Bandsäge, Hobelmaschine, CNC-Fräse verfügen jeweils über einen eigenen Unterbereich, um für jede Maschine eine eigene Berechtigung vergeben zu können.
|
||||
- **FabLab**
|
||||
- Im FabLab sind mehrere Personen für die Verwaltung zuständig:
|
||||
- Person A ist im Allgemenien für das FabLab zuständig. Hier gib es keine Maschinen, die von von FabAccess verwaltet werden.
|
||||
- Person B ist für die 3D-Drucker zuständig.
|
||||
- Person C ist für den Lasercutter inkl. Kühlung zuständig.
|
||||
- Beide Maschinengruppen (3D-Drucker & Laser) sind in einem eigenen Unterbereich, um eine eigene Berechtigung vergeben zu können.
|
||||
- Beide Unterbereiche verfügen über einen Unterbereich-Manager, damit Person A und B ihren jeweiligen Bereich verwalten können.
|
||||
- **Siebdruck & Büro**
|
||||
- Es gibt eine allgemeine Drucker-Einweisung, die zur Nutzung aller Drucker in beiden Bereichen berechtigt. Die Drucker der beiden Bereiche sind mit der Alternativrolle _Druckernutzung_ verknüpft.
|
||||
|
||||
|
||||
# Nutzung des Python-Skripts
|
||||
- Eingelesen wird die Datei `maschinenliste.csv`
|
||||
- Die Spaltennamen dienen der Zuordnung und dürfen nicht umbenannt werden.
|
||||
- Die Reihenfolge der Spalten kann nach Belieben verändert werden.
|
||||
- Zentrale Einstellungen können in der `settings.ini` vorgenommen werden,
|
||||
- Aktor-Typen können in der `actors.ini` definiert
|
||||
- Erzeugte Daten werden im Unterordner `output` gespeichert.
|
||||
|
||||
## Anlegen von Maschinen (maschinenliste.csv)
|
||||
- Verwendetes Trennzeichen: `;`
|
||||
- IDs können Buchstaben und Zahlen enthalten.
|
||||
- Alle Großbuchstaben werden automatisch in Kleinbuchstaben umgewandelt.
|
||||
- Deutsche Sonderzeichen werden automatisch umgewandelt (ä = ae, ö = oe, ü = ue, ß = ss).
|
||||
- Alle übrigen Zeichen werden automatisch entfernt.
|
||||
|
||||
|
||||
| Feld | Info | Pflichtfeld |
|
||||
| ------------------------ | --------------------------------------------------------------------- | ----------- |
|
||||
| **ID Domäne** | Eindeutige ID einer Domäne. | Ja |
|
||||
| **ID Bereich** | Eindeutige ID eines Bereichs. | Ja |
|
||||
| **ID Unterbereich** | Eindeutige ID eines Unterbereichs. | - |
|
||||
| **ID Maschine** | Eindeutige ID der Maschine. | Ja |
|
||||
| **Unterbereich Manager** | Erstellung einer Manager-Rolle für den dazugehörigen Unterbereich | - |
|
||||
| **Name Bereich** | Anzeigename des Bereichs. | Ja |
|
||||
| **Name Unterbereich** | Anzeigename des Unterbereichs. | - |
|
||||
| **Name Maschine** | Anzeigename der Maschine. | Ja |
|
||||
| **Maschinbeschreibung** | Feld `description` einer Maschine in FabAccess. | - |
|
||||
| **Wiki-URL** | Feld `wiki` einer Maschine in FabAccess. | - |
|
||||
| **Aktor ID** | Eindeutige ID eines Aktors. | - |
|
||||
| **Aktor Typ** | Definiert den Aktorentyp, der aus der Aktorenbibliothek geladen wird. | - |
|
||||
| **ID Alternativrolle** | Eindeutige ID einer alternativen Rolle. | - |
|
||||
| **Name Alternativrolle** | Anzeigename einer alterantiven Rolle. | - |
|
||||
| **Anmerkungen** | Zusatzfeld für Anmerkungen, wird nicht verarbeitet. | - |
|
||||
|
||||
Hinweis zum Feld `Unterbereich Manager`:
|
||||
- Für die Erstellung der Rolle muss eni Unterbereich definiert sein.
|
||||
- Das Feld wird aktiv sobald ein beliebiger Inhalt eingetragen wird.
|
||||
- Das Feld muss nur für eine Maschine des Unterbereichs ausgefüllt werden.
|
||||
|
||||
## Einstellungen des Skripts (settings.ini)
|
||||
| Einstellung | Info |
|
||||
| -------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||
| **multi_domains** | Verwendung mehrer Domänen. Es wird dann automatisch eine Manager-Rolle für jede Domäne erstellt. |
|
||||
| **manager_schichtleitung** | Rolle "Schichtleitung" erstellen, die über Manager-Berechtigungen für alle Domänen verfügt. |
|
||||
| **manager_area** | Manager-Rolle für jeden Bereich erstellen. |
|
||||
| **manager_subarea** | Spalte "Unterbereich Manager" der CSV beachten (True) oder nicht (False). |
|
||||
| **fa_update_dhall** | Automatische Aktualisierung einer bestehenden `bffh.dhall`. |
|
||||
| **fa_dhall_file** | Pfad zur bffh.dall. |
|
||||
| **generate_mermaid** | Mermaid-Code erzeugen, der Bereiche und Rolle in einem Diagramm abbildet. [^1] |
|
||||
| **create_file_roles** | Erstellung einer gesonderten CSV-Datei, die jede Rollen-ID und den dazugehörigen Rollen-Name beinhaltet. |
|
||||
| **show_machines** | Alle importierten Maschinen-Daten anzeigen. |
|
||||
| **show_roles** | Alle erzeugten Rollen-Daten anzeigen. |
|
||||
| **string_adminhandle** | Kennzeichnung von Administrator-Rollen im Anzeigename. Der String wird dem Namen der Rolle vorangestellt. [^2] |
|
||||
| **string_managerhandle** | Kennzeichnung für Manager-Rollen, steht am Anfang des Namens der Rolle. [^2] |
|
||||
| **string_userhandle** | Kennzeichnung von Benutzer-Rollen im Anzeigename. Der String wird dem Namen der Rolle vorangestellt. [^2] |
|
||||
|
||||
[^1]: Ausgabe erfolgt in die Datei `mermaid-code.txt`. Der enthaltene Code kann auf [mermaid.live](https://mermaid.live/) eingefügt werden, um das Diagramm als Grafik zu speichern.
|
||||
[^2]: Der Anzeigename wird aktuell nur im Diagramm verwendet.
|
||||
|
||||
|
||||
## Aktorenbibliothek (actors.ini)
|
||||
In der Aktorenbibliothek können Vorlagen für Aktor-Typen angelegt werden. Ein bestimmter Aktor muss somit nur einmal angelegt werden und kann in der `maschinenliste.csv` angegeben werden.
|
||||
|
||||
Ein Aktor-Typ besteht immer aus:
|
||||
- Titel des Aktors. Dieser wird in eckigen Klammern angegeben und definiert den Aktor.
|
||||
- Angabe zum Feld `module` von FabAccess.
|
||||
|
||||
Darüber hinaus können beliebig viele eigene Parameter übergeben werden. Diese müssen mit Präfix `param_` als Parameter gekennzeichnet sein.
|
||||
|
||||
|
||||
### Beispiel für die Erstellung eines Aktor-Typs
|
||||
Angelegt wird der Aktor *shellyplus*. Für diesen wird anschließend in der `maschinenliste.csv` eine Maschine mit der Aktor-ID *test12345* angelegt.
|
||||
|
||||
> Groß- und Kleinschreibung spielt für die Datenverarbeitung keine Rolle. Sowohl der Aktor-Name als auch alle Parameter werden automatisch in Kleinbuchstaben umgewandelt.
|
||||
<br/>
|
||||
|
||||
Aktor-Definition in der actors.ini
|
||||
```
|
||||
[shellyplus]
|
||||
module = "MqttSwitch"
|
||||
param_topic = "shellyplus1pm-$actor_id/rpc",
|
||||
param_onMsg = "{\"id\": 1, \"src\": \"bffh\", \"method\": \"Switch.Set\", \"params\": {\"id\": 0, \"on\": true}"
|
||||
param_offMsg= "{\"id\": 1, \"src\": \"bffh\", \"method\": \"Switch.Set\", \"params\": {\"id\": 0, \"on\": false}"
|
||||
```
|
||||
<br/>
|
||||
|
||||
Fertiger Aktor in der `bffh.dhall`:
|
||||
```
|
||||
shellyplus_test12345 =
|
||||
{
|
||||
module = ""MqttSwitch"",
|
||||
params =
|
||||
{
|
||||
topic = "shellyplus1pm-bbbb/rpc",,
|
||||
onmsg = "{\"id\": 1, \"src\": \"bffh\", \"method\": \"Switch.Set\", \"params\": {\"id\": 0, \"on\": true}",
|
||||
offmsg = "{\"id\": 1, \"src\": \"bffh\", \"method\": \"Switch.Set\", \"params\": {\"id\": 0, \"on\": false}",
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
# Verschiedene Informationen
|
||||
## ID-Schema für Rollen, Maschinen und Aktoren
|
||||
| ID | Schema |
|
||||
| ------------ | --------------------------------------------------------- |
|
||||
| **Rolle** | domäne.bereich.bereich.rollentyp bzw. domäne.unterbereich.rollentyp |
|
||||
| **Maschine** | domäne-bereich-bereich-maschinen bzw. domäne-unterbereich-maschinen |
|
||||
| **Aktor** | aktortyp_aktorid |
|
||||
|
||||
**Auszug aus der Beispielwerkstatt: Unterbereich FabLab Laser**
|
||||
- Rolle "*Manager FabLab Laser*": beispielw_fablab_laser_manager
|
||||
- Rolle "*Benutzer FabLab Laser*": beispielw_fablab_laser_user
|
||||
- Maschinen-IDs:
|
||||
- Maschine "*Lasercutter*": beispielw-fablab-laser-laser3000
|
||||
- Maschine "*Kühlung*": beispielw-fablab-laser-kuehlung3000
|
||||
|
||||
### Ausnahme: Alternativrollen
|
||||
Bei einer Alternativrolle weicht die Rollen-ID von der Maschinen-ID ab, da es sich um eine bereichsübergreifende Rolle handelt. Die Rollen-ID beinhaltet keine Bereichszuordnung. Die Maschinen-ID beinhaltet nach wie vor eine Bereichszuordnung, um die Maschine eindeutig in der Werkstatt verorten zu können.
|
||||
|
||||
**Auszug aus der Beispielwerkstatt: Alternative Rolle für Druckernutzung**
|
||||
- Rolle "*Benutzer Druckerbenutzung*": beispielw_drucker
|
||||
- Maschinen-IDs:
|
||||
- beispielw-siebdruck-a3drucker
|
||||
- beispielw-buero-drucker
|
||||
|
||||
## Aktualisierung einer bestehenden bffh.dhall
|
||||
Eine bestehende `bffh.dhall` kann auf Wunsch automatisch aktualisiert werden. Dabei wird der Inhalt der bestehenden `bffh.dhall` eingelesen und die vom Config-Generator erzeugten Daten an einer vordefinierten Stelle eingesetzt.
|
||||
|
||||
**Einstellungen in der settings.ini setzen**
|
||||
Hierfür müssen in der `settings.ini` die folgenden Einstellungen gesetzt sein:
|
||||
- `fa_update_dhall`auf `True`
|
||||
- `fa_dhall_file` muss die Pfandangabe zur bffh.dhall enthalten
|
||||
|
||||
**bffh.dhall vorbereiten**
|
||||
1. Bestehende Datenstrukturen löschen:
|
||||
- roles
|
||||
- maschines
|
||||
- actors
|
||||
- actor_connections
|
||||
2. Die folgenden Zeilen einfügen.
|
||||
- `-- ||| GENERATOR START`
|
||||
- ` -- ||| GENERATOR END`
|
||||
|
||||
Das Skript fügt die erzeugten Daten automatisch zwischen beiden Platzhaltern ein. Bestehender Inhalt zwischen den Platzhaltern wird dabei überschrieben.
|
||||
|
||||
>
|
||||
> **Hinweis**
|
||||
> Ein Vorlage für eine entsprechend angepasste `bffh.dhall` befindet sich im Unterordner `docs`
|
||||
>
|
14
actors.ini
Normal file
14
actors.ini
Normal file
@ -0,0 +1,14 @@
|
||||
[tasmota]
|
||||
module = Process
|
||||
param_cmd = "/usr/local/lib/bffh/adapters/tasmota/main.py"
|
||||
param_args = "--host mqtt --tasmota $actor_id"
|
||||
|
||||
[shelly]
|
||||
module = 'Shelly'
|
||||
param_topic = "shellyplug-$actor_id"
|
||||
|
||||
[SHellyplus]
|
||||
module = "MqttSwitch"
|
||||
param_topic = "shellyplus1pm-$actor_id/rpc",
|
||||
param_onMsg = "{\"id\": 1, \"src\": \"bffh\", \"method\": \"Switch.Set\", \"params\": {\"id\": 0, \"on\": true}"
|
||||
param_offMsg= "{\"id\": 1, \"src\": \"bffh\", \"method\": \"Switch.Set\", \"params\": {\"id\": 0, \"on\": false}"
|
81
config-generator.py
Normal file
81
config-generator.py
Normal file
@ -0,0 +1,81 @@
|
||||
__version__ = 2024.5
|
||||
|
||||
import time
|
||||
time_start = time.perf_counter()
|
||||
|
||||
from pathlib import Path
|
||||
from generator.core import *
|
||||
from generator.helpers import *
|
||||
|
||||
input_file = 'maschinenliste.csv'
|
||||
|
||||
# Output-Ordner anlegen
|
||||
directory = "output"
|
||||
path = Path(directory)
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print(f' --- Datei = {input_file}')
|
||||
|
||||
# Maschinenliste einlesen
|
||||
print(' --- Maschinen importieren:')
|
||||
machines = import_machines(input_file)
|
||||
|
||||
# Rollen für FabAccess erzeugen
|
||||
print(' --- Rollen erzeugen')
|
||||
roles = generate_roles(machines)
|
||||
|
||||
# Finale DHALL-Daten erzeugen
|
||||
export_roles = generate_bffh_roles(roles)
|
||||
export_machines = generate_bffh_machines(machines)
|
||||
export_actors = generate_bffh_actors(machines)
|
||||
export_actorconnections = generate_bffh_actorconnections(machines)
|
||||
export_all = export_roles + export_machines + export_actors + export_actorconnections
|
||||
|
||||
|
||||
# Anzeigen der erzeugten Daten
|
||||
if settings["show_machines"] == True:
|
||||
for m in machines:
|
||||
display_machine(m)
|
||||
|
||||
if settings["show_roles"] == True:
|
||||
print_dict(roles)
|
||||
|
||||
# Daten exportieren
|
||||
print(' --- DHALL-Daten exportieren')
|
||||
write_file('output/bffh-dhall-data.txt', export_all)
|
||||
|
||||
if settings["create_file_roles"] == True:
|
||||
print(' --- Rollen exportieren in roles.csv')
|
||||
content = generate_csv_roles(roles)
|
||||
write_file('output/roles.csv', content)
|
||||
|
||||
if settings["fa_update_dhall"] == True:
|
||||
print(' --- Aktualisierung der bffh.dhall')
|
||||
fa_dhall_file = settings["fa_dhall_file"]
|
||||
|
||||
# Pfadangabe "fa_dhall_file" hat Inhalt
|
||||
if len(fa_dhall_file) > 0:
|
||||
|
||||
# Daten schreiben
|
||||
dhall_content = generate_bffh_dhall(export_all)
|
||||
|
||||
if len(dhall_content) > 0:
|
||||
write_file(fa_dhall_file, dhall_content)
|
||||
|
||||
# Pfadangabe "fa_dhall_file" ist leer
|
||||
else:
|
||||
print('Einstellung "fa_dhall_file" ist leer, es wurde kein Pfad zur bffh.dhall angegeben.')
|
||||
print('Bitte das Feld ausfüllen oder "fa_update_dhall" auf "False" setzen.')
|
||||
|
||||
# Mermaid-Code
|
||||
if settings["generate_mermaid"] == True:
|
||||
print(' --- Mermaid-Code erzeugen')
|
||||
graphelements = graph_create_elements(machines)
|
||||
mermaidcode = graph_create_mermaidcode(graphelements)
|
||||
write_file('output/mermaid-code.txt', mermaidcode)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
time_end = time.perf_counter()
|
||||
time_span = round(time_end - time_start, 2)
|
||||
print('-------------------------')
|
||||
print(f'Laufzeit: {time_span} Sekunden')
|
16
docs/beispielwerkstatt.csv
Normal file
16
docs/beispielwerkstatt.csv
Normal file
@ -0,0 +1,16 @@
|
||||
Name Domäne;Name Bereich;Name Unterbereich;Name Maschine;Maschinenbeschreibung;Manager Unterbereich;ID Alternativrolle;Name Alternativrolle;Wiki-URL;ID Domäne;ID Bereich;ID Unterbereich;ID Maschine;Aktor ID;Aktor Typ;Kommentar
|
||||
Beispielwerkstatt;Holzwerkstatt;Bandsäge;Bandsäge;Bandsäge im Holzbereich;;;;;beispielw;holz;bandsaege;bandsaege;1;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;Hobelmaschine;Hobelmaschine;Hobelmaschine im Holzbereich;;;;;beispielw;holz;hobelmaschine;hobelmaschine;2;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;CNC-Fräse;CNC-Fräse;CNC Fräse im Holzbereich;;;;;beispielw;holz;holzcnc;holzcncfraese;6;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;;Kappsäge;Kappsäge mit allgemeiner Einweisung Holz;;;;;beispielw;holz;;kappsaege;7;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;;Bandschleifer;Bandschleifer mit allgemeiner Einweisung Holz;;;;;beispielw;holz;;bandschleifer;8;Tasmota;Irgendein Kommentar
|
||||
Beispielwerkstatt;Holzwerkstatt;;Ständerbohrmaschine;Ständerbohrmaschine mit allgemeiner Einweisung Holz;;;;;beispielw;holz;;staenderbohrmaschine;9;Tasmota;
|
||||
Beispielwerkstatt;Textilwerkstatt;;Nähmaschine 1;Nähmaschine Nummer 1;;;;;beispielw;textil;;naehmaschine1;10;Tasmota;
|
||||
Beispielwerkstatt;Textilwerkstatt;;Nähmaschine 2;Nähmaschine Nummer 2;;;;;beispielw;textil;;naehmaschine2;11;Tasmota;
|
||||
Beispielwerkstatt;FabLab;3D-Druck;3D-Drucker 1;3D-Drucker Modell 111;x;;;;beispielw;fablab;3dprint;3ddrucker1;12;Tasmota;
|
||||
Beispielwerkstatt;FabLab;3D-Druck;3D-Drucker 2;3D-Drucker Modell 222;x;;;;beispielw;fablab;3dprint;3ddrucker2;13;Tasmota;
|
||||
Beispielwerkstatt;FabLab;Laser;Lasercutter;Modell Laser3000;x;;;https://www.fiktivedoku.de;beispielw;fablab;laser;laser3000;14;Tasmota;
|
||||
Beispielwerkstatt;FabLab;Laser;Kühlung;Modell Kühlung3000;x;;;;beispielw;fablab;laser;kühlung3000;15;Tasmota;
|
||||
Beispielwerkstatt;Siebdruck;;SD-Belichter;Belichter für die Siebe;;;;;beispielw;siebdruck;;sdbelichter;16;Tasmota;
|
||||
Beispielwerkstatt;Siebdruck;;A3-Drucker;A3 Drucker im Siebdruck Bereich;;drucker;Druckernutzung;;beispielw;siebdruck;;a3drucker;17;Tasmota;
|
||||
Beispielwerkstatt;Büro;;Drucker;;;drucker;Druckernutzung;;beispielw;büro;;drucker;18;Tasmota;
|
|
1
docs/beispielwerkstatt.svg
Normal file
1
docs/beispielwerkstatt.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 33 KiB |
67
docs/bffh-vorlage.dhall
Normal file
67
docs/bffh-vorlage.dhall
Normal file
@ -0,0 +1,67 @@
|
||||
{- Main configuration file for bffh
|
||||
- ================================
|
||||
-
|
||||
- In this configuration file you configure almost all parts of how bffh operates, but most importantly:
|
||||
- * Machines
|
||||
- * Initiators and Actors
|
||||
- * Which Initiators and Actors relate to which machine(s)
|
||||
- * Roles and the permissions granted by them
|
||||
-}
|
||||
|
||||
-- The config is in the configuration format/language dhall. You can find more information about dhall over at
|
||||
-- https://dhall-lang.org
|
||||
|
||||
-- (Our) Dhall is somewhat similar to JSON and YAML in that it expects a top-level object containing the
|
||||
-- configuration values
|
||||
{
|
||||
-- Configure the addresses and ports bffh listens on
|
||||
listens = [
|
||||
-- BFFH binds a port for every listen object in this array.
|
||||
-- Each listen object is of the format { address = <STRING>, port = <INTEGER> }
|
||||
-- If you don't specify a port bffh will use the default of `59661`
|
||||
-- 'address' can be a IP address or a hostname
|
||||
-- If bffh can not bind a port for the specified combination if will log an error but *continue with the remaining ports*
|
||||
{ address = "127.0.0.1", port = 59661 },
|
||||
{ address = "::1", port = 59661 },
|
||||
{ address = "steak.fritz.box", port = 59661 }
|
||||
],
|
||||
|
||||
-- Configure TLS. BFFH requires a PEM-encoded certificate and the associated key as two separate files
|
||||
certfile = "examples/self-signed-cert.pem",
|
||||
keyfile = "examples/self-signed-key.pem",
|
||||
|
||||
-- BFFH right now requires a running MQTT broker.
|
||||
mqtt_url = "tcp://localhost:1883",
|
||||
|
||||
-- Path to the database file for bffh. bffh will in fact create two files; ${db_path} and ${db_path}.lock.
|
||||
-- BFFH will *not* create any directories so ensure that the directory exists and the user running bffh has write
|
||||
-- access into them.
|
||||
db_path = "/tmp/bffh",
|
||||
|
||||
-- Audit log path. Bffh will log state changes into this file, one per line.
|
||||
-- Audit log entries are for now JSON:
|
||||
-- {"timestamp":1641497361,"machine":"Testmachine","state":{"state":{"InUse":{"uid":"Testuser","subuid":null,"realm":null}}}}
|
||||
auditlog_path = "/tmp/bffh.audit",
|
||||
|
||||
|
||||
-- ||| GENERATOR START
|
||||
-- ||| GENERATOR END
|
||||
|
||||
|
||||
-- Initiators are configured almost the same way as Actors, refer to actor documentation for more details
|
||||
-- The below '{=}' is what you need if you want to define *no* initiators at all and only use the API with apps
|
||||
-- to let people use machines.
|
||||
initiators = {=},
|
||||
-- The "Dummy" initiator will try to use and return a machine as the given user every few seconds. It's good to
|
||||
-- test your system but will spam your log so is disabled by default.
|
||||
--initiators = { Initiator = { module = "Dummy", params = { uid = "Testuser" } } },
|
||||
|
||||
-- Linking up machines to initiators. Similar to actors a machine can have several initiators assigned but an
|
||||
-- initiator can only be assigned to one machine.
|
||||
-- The below is once again how you have to define *no* initiators.
|
||||
init_connections = [] : List { machine : Text, initiator : Text },
|
||||
--init_connections = [{ machine = "Testmachine", initiator = "Initiator" }]
|
||||
|
||||
instanceurl = "https://example.com",
|
||||
spacename = "examplespace"
|
||||
}
|
854
generator/core.py
Normal file
854
generator/core.py
Normal file
@ -0,0 +1,854 @@
|
||||
from string import Template
|
||||
|
||||
from generator.globals import *
|
||||
from generator.helpers import *
|
||||
|
||||
string_userhandle = settings["string_userhandle"] + ' '
|
||||
string_adminhandle = settings["string_adminhandle"] + ' '
|
||||
string_managerhandle = settings["string_managerhandle"] + ' '
|
||||
|
||||
# ------------ Klassen
|
||||
|
||||
class Domain:
|
||||
def __init__(self, domain_id, domain_name):
|
||||
name_handle = domain_name
|
||||
perm_handle = domain_id + '.'
|
||||
id_handle = perm_handle.replace('.', '_')
|
||||
|
||||
perms_manager = [perm_handle + '*']
|
||||
|
||||
self.domain = {
|
||||
"id": domain_id,
|
||||
"name": domain_name
|
||||
}
|
||||
|
||||
self.domain_manager = {
|
||||
"id": id_handle + 'manager',
|
||||
"name": string_managerhandle + domain_name,
|
||||
"perms": perms_manager
|
||||
}
|
||||
|
||||
def get_domain(self):
|
||||
return self.domain
|
||||
|
||||
def get_domain_manager(self):
|
||||
return self.domain_manager
|
||||
|
||||
|
||||
class Area(Domain):
|
||||
def __init__(self, domain_id, domain_name, area_id, area_name):
|
||||
super().__init__(domain_id, domain_name)
|
||||
|
||||
self.area_id = area_id
|
||||
self.area_name = area_name
|
||||
|
||||
if settings["multi_domains"] == True:
|
||||
name_handle = domain_name + area_name
|
||||
else:
|
||||
name_handle = area_name
|
||||
|
||||
perm_handle = domain_id + '.' + area_id + '.'
|
||||
id_handle = perm_handle.replace('.', '_')
|
||||
|
||||
perms_manager = [perm_handle + '*']
|
||||
perms_user = [
|
||||
perm_handle + 'disclose.*',
|
||||
perm_handle + 'read.*',
|
||||
perm_handle + 'write.*'
|
||||
]
|
||||
|
||||
self.area_manager = {
|
||||
"id": id_handle + 'manager',
|
||||
"name": string_managerhandle + name_handle,
|
||||
"perms": perms_manager
|
||||
}
|
||||
|
||||
self.area_user = {
|
||||
"id": id_handle + 'user',
|
||||
"name": string_userhandle + name_handle,
|
||||
"perms": perms_user
|
||||
}
|
||||
|
||||
def get_area(self):
|
||||
area = {
|
||||
"id": self.area_id,
|
||||
"name": self.area_name
|
||||
}
|
||||
return area
|
||||
|
||||
def get_area_manager(self):
|
||||
return self.area_manager
|
||||
|
||||
def get_area_user(self):
|
||||
return self.area_user
|
||||
|
||||
class Subarea(Area):
|
||||
def __init__(self, domain_id, domain_name, area_id, area_name, subarea_id, subarea_name, subarea_manager):
|
||||
super().__init__(domain_id, domain_name, area_id, area_name)
|
||||
|
||||
self.subarea_id = subarea_id
|
||||
self.subarea_name = subarea_name
|
||||
|
||||
if settings["multi_domains"] == True:
|
||||
name_handle = domain_name + area_name + ' ' + subarea_name
|
||||
else:
|
||||
name_handle = area_name + ' ' + subarea_name
|
||||
|
||||
perm_handle = domain_id + '.' + area_id + '.' + subarea_id + '.'
|
||||
id_handle = perm_handle.replace('.', '_')
|
||||
|
||||
perms_manager = [perm_handle + '*']
|
||||
perms_user = [
|
||||
perm_handle + 'disclose.*',
|
||||
perm_handle + 'read.*',
|
||||
perm_handle + 'write.*'
|
||||
]
|
||||
|
||||
# Unterbereich prüfen
|
||||
if len(subarea_id) > 0 and len(subarea_name) > 0:
|
||||
self.subarea_state = True
|
||||
else:
|
||||
self.subarea_state = False
|
||||
|
||||
# Unterbereich-Manager prüfen
|
||||
if len(subarea_manager) > 0:
|
||||
self.subarea_manager_state = True
|
||||
else:
|
||||
self.subarea_manager_state = False
|
||||
|
||||
self.subarea_manager = {
|
||||
"id": id_handle + 'manager',
|
||||
"name": string_managerhandle + name_handle,
|
||||
"perms": perms_manager
|
||||
}
|
||||
|
||||
self.subarea_user = {
|
||||
"id": id_handle + 'user',
|
||||
"name": string_userhandle + name_handle,
|
||||
"perms": perms_user
|
||||
}
|
||||
|
||||
def get_subarea(self):
|
||||
subarea = {
|
||||
"id": self.subarea_id,
|
||||
"name": self.subarea_name
|
||||
}
|
||||
return subarea
|
||||
|
||||
def get_subarea_manager(self):
|
||||
return self.subarea_manager
|
||||
|
||||
def get_subarea_user(self):
|
||||
return self.subarea_user
|
||||
|
||||
def has_subarea(self):
|
||||
return self.subarea_state
|
||||
|
||||
def has_subarea_manager(self):
|
||||
return self.subarea_manager_state
|
||||
|
||||
|
||||
class Machine(Subarea):
|
||||
def __init__(self, data):
|
||||
|
||||
area_name = data["area_name"].strip()
|
||||
subarea_name = data["subarea_name"].strip()
|
||||
domain_id = string_clean(data["domain_id"].strip()).lower()
|
||||
area_id = string_clean(data["area_id"].strip()).lower()
|
||||
subarea_id = string_clean(data["subarea_id"].strip()).lower()
|
||||
machine_id = string_clean(data["machine_id"].strip()).lower()
|
||||
subarea_manager = data["subarea_manager"].strip()
|
||||
area_name = data["area_name"].strip()
|
||||
subarea_name = data["subarea_name"].strip()
|
||||
machine_name = string_removequotes(data["machine_name"]).strip()
|
||||
machine_desc = string_removequotes(data["machine_desc"]).strip()
|
||||
wikiurl = data["wikiurl"].strip()
|
||||
actor_id = string_clean(data["actor_id"].strip()).lower()
|
||||
# actor_module = data["actor_module"].strip()
|
||||
actor_type = data["actor_type"].strip().lower()
|
||||
|
||||
customrole_id = string_clean(data["customrole_id"].strip()).lower()
|
||||
customrole_name = data["customrole_name"].strip()
|
||||
domain_name = data["domain_name"].strip() + ' '
|
||||
|
||||
super().__init__(domain_id, domain_name, area_id, area_name, subarea_id, subarea_name, subarea_manager)
|
||||
# ----------------------------
|
||||
|
||||
# Alternativrolle prüfen
|
||||
if len(customrole_id) > 0 and len(customrole_name) > 0:
|
||||
|
||||
self.customrole_state = True
|
||||
else:
|
||||
self.customrole_state = False
|
||||
|
||||
if self.subarea_state == True:
|
||||
# Unterbereich
|
||||
fa_id = domain_id + '-' + area_id + '-' + subarea_id + '-' + machine_id
|
||||
string_perm = domain_id + '.' + area_id + '.' + subarea_id + '.|ACTION|.' + machine_id
|
||||
else:
|
||||
# Bereich
|
||||
fa_id = domain_id + '-' + area_id + '-' + machine_id
|
||||
string_perm = domain_id + '.' + area_id + '.|ACTION|.' + machine_id
|
||||
|
||||
permlist = ["disclose", "read", "write", "manage"]
|
||||
|
||||
perms_machine = []
|
||||
perms_machine_names = []
|
||||
perms_user = []
|
||||
|
||||
for p in permlist:
|
||||
perms_machine.append(string_perm.replace('|ACTION|', p))
|
||||
perms_machine_names.append(p)
|
||||
if p != 'manage':
|
||||
perms_user.append(string_perm.replace('|ACTION|', p))
|
||||
|
||||
|
||||
self.machine_specs = {
|
||||
"id": machine_id,
|
||||
"fa_id": fa_id,
|
||||
"name": machine_name,
|
||||
"perms": perms_machine,
|
||||
"perms_names": perms_machine_names,
|
||||
"category": area_name,
|
||||
"desc": machine_desc,
|
||||
"wikiurl": wikiurl,
|
||||
"actor_id": actor_id,
|
||||
"actor_type": actor_type
|
||||
}
|
||||
|
||||
self.customrole = {
|
||||
"id": domain_id + '_' + customrole_id,
|
||||
"name": string_userhandle + customrole_name,
|
||||
"perms": perms_user
|
||||
}
|
||||
|
||||
def get_machine(self):
|
||||
return self.machine_specs
|
||||
|
||||
def has_customrole(self):
|
||||
return self.customrole_state
|
||||
|
||||
def get_customrole(self):
|
||||
return self.customrole
|
||||
|
||||
|
||||
class GraphElement:
|
||||
def __init__(self, id, name, parent):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.parent = parent
|
||||
self.level = id.count('_')
|
||||
self.roles = []
|
||||
self.machines = []
|
||||
|
||||
def get_level(self):
|
||||
return self.level
|
||||
|
||||
def get_id(self):
|
||||
return self.id
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_parent(self):
|
||||
return self.parent
|
||||
|
||||
def add_machine(self, machine_name, customrole = ''):
|
||||
if len(customrole) > 0:
|
||||
self.machines.append(f'{machine_name} ({icon_custom}{customrole})')
|
||||
else:
|
||||
self.machines.append(machine_name)
|
||||
|
||||
def get_machines(self):
|
||||
return self.machines
|
||||
|
||||
def add_role(self, roles_name):
|
||||
self.roles.append(roles_name)
|
||||
|
||||
def get_roles(self):
|
||||
return self.roles
|
||||
|
||||
|
||||
# ------------ Funktionen
|
||||
|
||||
# Maschinen aus der CSV-importieren
|
||||
def import_machines(file):
|
||||
machines = {}
|
||||
data = csv_listdict(file, csv_match)
|
||||
|
||||
count = 2
|
||||
print(f'{"Zeile": ^8} | {"Status": ^24} | {"Zusatzinformation": ^20}')
|
||||
print(f'{"1": ^8} | {"Kopfzeile": ^24} | {"Kopfzeile wird nicht verarbeitet.": ^20}')
|
||||
|
||||
for entry in data:
|
||||
|
||||
# ------- Felder übrprüfen
|
||||
errors = []
|
||||
|
||||
# Pflichtfelder
|
||||
|
||||
for el in importcheck["single"].keys():
|
||||
|
||||
# Einzelfeld ist leer?
|
||||
|
||||
if len(entry[el]) == 0:
|
||||
name = importcheck["translate"][el]
|
||||
errors.append(f'Pflichtfeld "{name}" ist leer')
|
||||
|
||||
# Optionales Felderpaar vollständig?
|
||||
for field1, field2 in importcheck["pairs"].items():
|
||||
|
||||
for key, value in csv_match.items():
|
||||
if value == field1:
|
||||
field1_name = key
|
||||
if value == field2:
|
||||
field2_name = key
|
||||
|
||||
if len(entry[field1]) > 0 and len(entry[field2]) == 0:
|
||||
errors.append(f'Optionales Felderpaar unvollständig: Feld "{field1_name}" ist ausgefüllt, aber Feld "{field2_name}" ist leer.')
|
||||
|
||||
if len(entry[field2]) > 0 and len(entry[field1]) == 0:
|
||||
errors.append(f'Optionales Felderpaar unvollständig: Feld "{field2_name}" ist ausgefüllt, aber Feld "{field1_name}" ist leer.')
|
||||
|
||||
status = 'Eintrag übersprungen'
|
||||
info = f'Fehlerhafte Konfiguration. ID = {entry["machine_id"]}'
|
||||
if len(errors) > 0:
|
||||
print(f'{count: ^8} | {status: ^24} | {info: ^20}')
|
||||
for e in errors:
|
||||
print(f'{"":>36}| ' + e)
|
||||
count += 1
|
||||
continue
|
||||
|
||||
# Maschine anlegen
|
||||
temp = Machine(entry)
|
||||
fa_id = temp.get_machine()["fa_id"]
|
||||
|
||||
if fa_id not in machines.keys():
|
||||
machines.update({
|
||||
f'{fa_id}': Machine(entry)
|
||||
})
|
||||
|
||||
status = 'Maschine angelegt'
|
||||
info = f'FA_ID = {fa_id}'
|
||||
|
||||
print(f'{count: ^8} | {status: ^24} | {info: ^20}')
|
||||
else:
|
||||
status = 'Eintrag übersprungen'
|
||||
info = f'ID bereits vergeben. ID = {entry["machine_id"]}'
|
||||
print(f'{count: ^8} | {status: ^24} | {info: ^20}')
|
||||
|
||||
count += 1
|
||||
|
||||
return machines
|
||||
|
||||
|
||||
|
||||
|
||||
# Rollen erstellen
|
||||
def generate_roles(machines):
|
||||
|
||||
roles = {}
|
||||
|
||||
# Globalen Admin erstellen
|
||||
roledata = admin_global
|
||||
|
||||
if roledata["id"] not in roles.keys():
|
||||
roles[roledata["id"]] = roledata
|
||||
|
||||
|
||||
# Schichtleitung anlegen
|
||||
if settings["manager_schichtleitung"] == True:
|
||||
roledata = manager_schichtleitung
|
||||
|
||||
if roledata["id"] not in roles.keys():
|
||||
roles[roledata["id"]] = roledata
|
||||
|
||||
|
||||
# Domänen durchlaufen
|
||||
for id, m in machines.items():
|
||||
|
||||
# Domänen-Berechtigung an Manager & Schichtleitung vergeben
|
||||
roledata = m.get_domain_manager()
|
||||
for perm in roledata["perms"]:
|
||||
if perm not in roles[admin_global["id"]]["perms"]:
|
||||
roles[admin_global["id"]]["perms"].append(perm)
|
||||
|
||||
if settings["manager_schichtleitung"] == True:
|
||||
for perm in roledata["perms"]:
|
||||
if perm not in roles[manager_schichtleitung["id"]]["perms"]:
|
||||
roles[manager_schichtleitung["id"]]["perms"].append(perm)
|
||||
|
||||
# Manager: Domain
|
||||
if settings["multi_domains"] == True:
|
||||
roledata = m.get_domain_manager()
|
||||
|
||||
if roledata["id"] not in roles.keys():
|
||||
roles[roledata["id"]] = roledata
|
||||
|
||||
# Manager: Area
|
||||
if settings["manager_area"] == True:
|
||||
roledata = m.get_area_manager()
|
||||
|
||||
if roledata["id"] not in roles.keys():
|
||||
roles[roledata["id"]] = roledata
|
||||
|
||||
# Manager: Subarea
|
||||
if settings["manager_subarea"] == True:
|
||||
if m.has_subarea() == True:
|
||||
if m.has_subarea_manager() == True:
|
||||
roledata = m.get_subarea_manager()
|
||||
|
||||
if roledata["id"] not in roles.keys():
|
||||
roles[roledata["id"]] = roledata
|
||||
|
||||
# Benutzer: Daten abrufen
|
||||
|
||||
if m.has_customrole() == True:
|
||||
# Extrarolle
|
||||
roledata = m.get_customrole()
|
||||
|
||||
if roledata["id"] in roles.keys():
|
||||
# Extrarolle vorhanden --> Berechtigungen hinzufügen
|
||||
for p in roledata["perms"]:
|
||||
roles[roledata["id"]]["perms"].append(p)
|
||||
|
||||
else:
|
||||
|
||||
if m.has_subarea() == True:
|
||||
# Unterbereich
|
||||
roledata = m.get_subarea_user()
|
||||
else:
|
||||
# Bereich
|
||||
roledata = m.get_area_user()
|
||||
|
||||
# print_dict(roledata)
|
||||
|
||||
# Benutzer: Hinzufügen
|
||||
if roledata["id"] not in roles.keys():
|
||||
roles[roledata["id"]] = roledata
|
||||
|
||||
return roles
|
||||
|
||||
|
||||
def generate_bffh_roles(roles):
|
||||
|
||||
data = []
|
||||
|
||||
# Rollen
|
||||
data.append(space + 'roles = {')
|
||||
|
||||
for role in roles:
|
||||
data.append(space * 2 + f'{role}' + ' = {')
|
||||
data.append(space * 3 + 'permissions = [')
|
||||
for perm in roles[role]["perms"]:
|
||||
data.append(space * 4 + f'"{perm}",')
|
||||
data.append(space * 3 + ']')
|
||||
data.append(space * 2 + '},')
|
||||
data.append(' ')
|
||||
|
||||
data.append(space + '},')
|
||||
|
||||
return data
|
||||
|
||||
# Maschinen
|
||||
def generate_bffh_machines(machines):
|
||||
|
||||
data = []
|
||||
|
||||
data.append(space + 'machines = {')
|
||||
for id, m in machines.items():
|
||||
specs = m.get_machine()
|
||||
data.append(space * 2 + f'{specs["fa_id"]}' + ' = {')
|
||||
data.append(space * 3 + f'name = "{specs["name"]}",')
|
||||
data.append(space * 3 + f'description = "{specs["desc"]}",')
|
||||
data.append(space * 3 + f'wiki = "{specs["wikiurl"]}",')
|
||||
data.append(space * 3 + f'category = "{specs["category"]}",')
|
||||
|
||||
|
||||
for i in range(len(specs["perms"])):
|
||||
data.append(space * 3 + f'{specs["perms_names"][i]} = "{specs["perms"][i]}",')
|
||||
|
||||
data.append(space * 2 + '},')
|
||||
data.append(' ')
|
||||
data.append(space + '},')
|
||||
|
||||
return data
|
||||
|
||||
# Aktoren
|
||||
def generate_bffh_actors(machines):
|
||||
|
||||
data = []
|
||||
|
||||
data.append(space + 'actors = {')
|
||||
|
||||
for id, m in machines.items():
|
||||
specs = m.get_machine()
|
||||
|
||||
if len(specs["actor_id"]) > 0 and len(specs["actor_type"]) > 0:
|
||||
actor_handle = specs["actor_type"] + '_' + specs["actor_id"]
|
||||
|
||||
# 2do Actor Library Funktionalität
|
||||
|
||||
data.append(f' {actor_handle} =')
|
||||
data.append(' {')
|
||||
data.append(f' module = "{actor_library[specs["actor_type"]]["module"]}",')
|
||||
data.append(' params =')
|
||||
data.append(' {')
|
||||
|
||||
# Aktor-ID der aktuellen Maschine speichern
|
||||
replace = {
|
||||
"actor_id": specs["actor_id"]
|
||||
}
|
||||
|
||||
for key, value in actor_library[specs["actor_type"]]["params"].items():
|
||||
template = Template(value)
|
||||
string = template.substitute(replace)
|
||||
data.append(f' {key} = {string},')
|
||||
data.append(' }')
|
||||
data.append(' },')
|
||||
data.append(' ')
|
||||
data.append(space + '}, ')
|
||||
|
||||
return data
|
||||
|
||||
|
||||
# Aktoren-Verbindungen
|
||||
def generate_bffh_actorconnections(machines):
|
||||
|
||||
data = []
|
||||
|
||||
data.append(space + 'actor_connections = [')
|
||||
|
||||
for id, m in machines.items():
|
||||
specs = m.get_machine()
|
||||
|
||||
if len(specs["actor_id"]) > 0 and len(specs["actor_type"]) > 0:
|
||||
actor_fullid = specs["actor_type"] + '_' + specs["actor_id"]
|
||||
data.append(space * 2 + '{ ' + f'machine = "{specs["fa_id"]}", actor = "{actor_fullid}"' + ' },')
|
||||
|
||||
data.append(space + '],')
|
||||
|
||||
return data
|
||||
|
||||
|
||||
# CSV-Rollenliste
|
||||
|
||||
def generate_csv_roles(roles):
|
||||
data = []
|
||||
data.append('ID der Rolle; Name der Rolle')
|
||||
for id, values in roles.items():
|
||||
string = id + ';' + values["name"]
|
||||
data.append(string)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
|
||||
# bffh.dhall aktualisieren
|
||||
|
||||
def generate_bffh_dhall(generated_content):
|
||||
|
||||
dhall_file = settings["fa_dhall_file"]
|
||||
|
||||
reader = open(dhall_file, "r", encoding='utf-8')
|
||||
|
||||
data_write = []
|
||||
|
||||
inside_generator_block = False
|
||||
found_generator_block = False
|
||||
|
||||
count = 1
|
||||
|
||||
# bffh.dhall zeilenweise durchlaufen
|
||||
for line in reader:
|
||||
|
||||
# Beginn des Generator-Blocks gefunden --> Erzeugte Daten anhängen, Variablen umschalten
|
||||
if 'GENERATOR START' in line:
|
||||
found_generator_block = True
|
||||
inside_generator_block = True
|
||||
data_write.append(line.replace('\n', ''))
|
||||
data_write.append(' ')
|
||||
data_write += generated_content
|
||||
data_write.append(' ')
|
||||
added_generated_content = True
|
||||
# print(f'{count} Generatorblock-Anfang gefunden')
|
||||
|
||||
# Beginn des Generator-Blocks gefunden --> Variable umschalten
|
||||
if 'GENERATOR END' in line:
|
||||
inside_generator_block = False
|
||||
# print(f'{count} Generatorblock-Ende gefunden')
|
||||
|
||||
# Zeile liegt außerhalb des Generator-Blocks --> Zeile übernehmen
|
||||
if inside_generator_block == False:
|
||||
data_write.append(line.replace('\n', ''))
|
||||
|
||||
# Zeile liegt innerhalb des Generator-Blocks --> Zeile übernehmen
|
||||
if inside_generator_block == True:
|
||||
# Einfügung wurden vorgenommen, Zeile aus bffh.dhall ignorieren
|
||||
continue
|
||||
|
||||
if found_generator_block == True:
|
||||
return data_write
|
||||
else:
|
||||
print('Datei "bffh.dhall" enthält keinen Platzhalter zum automatischen Einfügen.')
|
||||
return []
|
||||
|
||||
|
||||
# Maschine vollständig ausgeben
|
||||
def display_machine(machine_object):
|
||||
|
||||
# ------------ DOMAIN
|
||||
|
||||
scope = machine_object.get_domain()
|
||||
print('\n--- Domain: ' + scope["name"])
|
||||
print('id = ' + scope["id"])
|
||||
print('name = ' + scope["name"])
|
||||
|
||||
role = machine_object.get_domain_manager()
|
||||
print('\n[Admin: ' + scope["name"] + ']')
|
||||
print('id = ' + role["id"])
|
||||
print('name = ' + role["name"])
|
||||
print('perms = ')
|
||||
for p in role["perms"]:
|
||||
print(' ' + p)
|
||||
|
||||
|
||||
# ------------ AREA
|
||||
scope = machine_object.get_area()
|
||||
print('\n--- Area: ' + scope["name"])
|
||||
print('id = ' + scope["id"])
|
||||
print('name = ' + scope["name"])
|
||||
|
||||
role = machine_object.get_area_manager()
|
||||
print('\n[Admin: ' + scope["name"] + ']')
|
||||
print('id = ' + role["id"])
|
||||
print('name = ' + role["name"])
|
||||
print('perms = ')
|
||||
for p in role["perms"]:
|
||||
print(' ' + p)
|
||||
|
||||
role = machine_object.get_area_user()
|
||||
print('\n[User: ' + scope["name"] + ']')
|
||||
print('id = ' + role["id"])
|
||||
print('name = ' + role["name"])
|
||||
print('perms = ')
|
||||
for p in role["perms"]:
|
||||
print(' ' + p)
|
||||
|
||||
# ------------ SUBAREA
|
||||
scope = machine_object.get_subarea()
|
||||
print('\n--- Subarea: ' + scope["name"])
|
||||
print('id = ' + scope["id"])
|
||||
print('name = ' + scope["name"])
|
||||
print('state = ' + str(machine_object.has_subarea()))
|
||||
|
||||
role = machine_object.get_subarea_manager()
|
||||
print('\n[Admin: ' + scope["name"] + ']')
|
||||
print('id = ' + role["id"])
|
||||
print('name = ' + role["name"])
|
||||
print('perms = ')
|
||||
for p in role["perms"]:
|
||||
print(' ' + p)
|
||||
|
||||
role = machine_object.get_subarea_user()
|
||||
print('\n[User: ' + scope["name"] + ']')
|
||||
print('id = ' + role["id"])
|
||||
print('name = ' + role["name"])
|
||||
print('perms = ')
|
||||
for p in role["perms"]:
|
||||
print(' ' + p)
|
||||
|
||||
# ------------ MACHINE
|
||||
scope = machine_object.get_machine()
|
||||
print('\n--- Machine: ' + scope["name"])
|
||||
print('id = ' + scope["id"])
|
||||
print('fa_id = ' + scope["fa_id"])
|
||||
print('name = ' + scope["name"])
|
||||
print('desc = ' + scope["desc"])
|
||||
print('wikiurl = ' + scope["wikiurl"])
|
||||
print('perms = ')
|
||||
for p in scope["perms"]:
|
||||
print(' ' + p)
|
||||
print('actor_id = ' + scope["actor_id"])
|
||||
print('actor_type = ' + scope["actor_type"])
|
||||
|
||||
print('\n[Alternativrolle: '+ role["name"] + ']')
|
||||
print('state = ' + str(machine_object.has_customrole()))
|
||||
role = machine_object.get_customrole()
|
||||
print('id = ' + role["id"])
|
||||
print('name = ' + role["name"])
|
||||
print('perms = ')
|
||||
for p in role["perms"]:
|
||||
print(' ' + p)
|
||||
|
||||
|
||||
def graph_create_elements(machines):
|
||||
data = {}
|
||||
data["_root"] = GraphElement("root", "Infrastruktur", '')
|
||||
data["_root"].add_role(f'{icon_admin}{admin_global["name"]}')
|
||||
if settings["manager_schichtleitung"] == True:
|
||||
data["_root"].add_role(f'{icon_admin}{manager_schichtleitung["name"]}')
|
||||
|
||||
for key, m in machines.items():
|
||||
|
||||
# Domain
|
||||
domain = m.get_domain()
|
||||
domain_id = f'root_{domain["id"]}'
|
||||
|
||||
if domain_id not in data.keys():
|
||||
data[f'{domain_id}'] = GraphElement(domain_id, domain["name"], 'root')
|
||||
|
||||
data[domain_id].add_role(f'{icon_admin}{m.get_domain_manager()["name"]}')
|
||||
|
||||
# Area
|
||||
area = m.get_area()
|
||||
area_id = f'{domain_id}_{area["id"]}'
|
||||
|
||||
if area_id not in data.keys():
|
||||
data[f'{area_id}'] = GraphElement(area_id, area["name"], domain_id)
|
||||
|
||||
data[area_id].add_role(f'{icon_admin}{m.get_area_manager()["name"]}')
|
||||
data[area_id].add_role(f'{icon_user}{m.get_area_user()["name"]}')
|
||||
|
||||
# Subarea
|
||||
if m.has_subarea() == True:
|
||||
subarea = m.get_subarea()
|
||||
subarea_id = f'{area_id}_{subarea["id"]}'
|
||||
|
||||
if subarea_id not in data.keys():
|
||||
data[f'{subarea_id}'] = GraphElement(subarea_id, subarea["name"], area_id)
|
||||
|
||||
data[subarea_id].add_role(f'{icon_admin}{m.get_subarea_manager()["name"]}')
|
||||
data[subarea_id].add_role(f'{icon_user}{m.get_subarea_user()["name"]}')
|
||||
|
||||
# Machine
|
||||
if m.has_subarea() == False:
|
||||
handle = area_id
|
||||
else:
|
||||
handle = subarea_id
|
||||
|
||||
if m.has_customrole() is True:
|
||||
customrole = m.get_customrole()["name"]
|
||||
data[handle].add_role(f'{icon_custom}{customrole}')
|
||||
else:
|
||||
customrole = ''
|
||||
|
||||
machine_name = m.get_machine()["name"]
|
||||
|
||||
data[handle].add_machine(machine_name, customrole)
|
||||
|
||||
data = dict_sort(data)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def graph_create_mermaidcode(graphelements):
|
||||
linedata = []
|
||||
|
||||
wrapper = True
|
||||
wrapper_open = False
|
||||
wrapper_current = ''
|
||||
|
||||
font_sizes = [2, 1.75, 1.5, 1.25]
|
||||
connectors = ['---', '------', '----', '------', '------']
|
||||
|
||||
crossing = '''
|
||||
$id{"<p style="opacity: 0;">.</p>"}
|
||||
$id--------$parent
|
||||
style $id fill: black, stroke: none
|
||||
'''
|
||||
|
||||
subgraph = '''
|
||||
subgraph $id["
|
||||
<p style="font-size: $fontsizeem">$name</p><p style="text-align: left; margin-top: 20px;">$string_roles</p>
|
||||
<p style="text-align: left; margin-top: 0px;">$string_machines</p>
|
||||
<p style="opacity: 0;">.</p>
|
||||
"]
|
||||
end'''
|
||||
|
||||
fillernode = '''
|
||||
subgraph filler_$id_1["
|
||||
<p style="opacity: 0;">
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
</p>"]
|
||||
end
|
||||
style filler_$id_1 fill: none, stroke: none
|
||||
$id~~~~~~filler_$id_1
|
||||
|
||||
subgraph filler_$id_2["
|
||||
<p style="opacity: 0;">
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
</p>"]
|
||||
end
|
||||
style filler_$id_2 fill: none, stroke: none
|
||||
filler_$id_1~~~~~filler_$id_2
|
||||
'''
|
||||
|
||||
linedata.append('%%{init: {"flowchart" : {"curve" : "linear"}}}%%')
|
||||
linedata.append(' ')
|
||||
linedata.append('flowchart TD')
|
||||
linedata.append(' ')
|
||||
linedata.append(' ')
|
||||
|
||||
for id, data in graphelements.items():
|
||||
|
||||
if wrapper == True:
|
||||
if data.get_level() == 2 and wrapper_open == True:
|
||||
if wrapper_current not in id:
|
||||
linedata.append(' ')
|
||||
linedata.append('end')
|
||||
linedata.append(' ')
|
||||
wrapper_open = False
|
||||
|
||||
if data.get_level() == 2 and wrapper_open == False:
|
||||
linedata.append(' ')
|
||||
# linedata.append(f'{data.get_parent()} {data.get_level() * '---'} {data.get_id()}_wrapper')
|
||||
linedata.append(f'{data.get_parent()} {connectors[data.get_level()]} {data.get_id()}_wrapper')
|
||||
linedata.append(f'subgraph {data.get_id()}_wrapper["<p style="opacity: 0;">.</p>"]')
|
||||
linedata.append(f'style {data.get_id()}_wrapper stroke: none, fill: none')
|
||||
linedata.append(' ')
|
||||
wrapper_open = True
|
||||
wrapper_current = id
|
||||
|
||||
if len(data.get_roles()) > 0:
|
||||
string_roles = '<b><center>Rollen</center></b>$roles</p>'
|
||||
string_roles = string_roles.replace('$roles', list_join(data.get_roles(), '<br>'))
|
||||
else:
|
||||
string_roles = ''
|
||||
|
||||
if len(data.get_machines()) > 0:
|
||||
string_machines = '<b><center>Maschinen</center></b>$machines'
|
||||
string_machines = string_machines.replace('$machines', list_join(data.get_machines(), '<br>'))
|
||||
else:
|
||||
string_machines = ''
|
||||
|
||||
|
||||
graph = subgraph.replace('$id', data.get_id())
|
||||
graph = graph.replace('$fontsize', str(font_sizes[data.get_level()]))
|
||||
graph = graph.replace('$name', data.get_name())
|
||||
graph = graph.replace('$string_roles', string_roles)
|
||||
graph = graph.replace('$string_machines', string_machines)
|
||||
|
||||
linedata.append(graph)
|
||||
linedata.append(' ')
|
||||
|
||||
if data.get_level() > 0:
|
||||
if data.get_level() != 2:
|
||||
# linedata.append(f'{data.get_parent()} {data.get_level() * '------'} {id}')
|
||||
linedata.append(f'{data.get_parent()} {connectors[data.get_level()]} {id}')
|
||||
|
||||
linedata.append(' ')
|
||||
|
||||
if data.get_level() == 2:
|
||||
if dict_keycount(graphelements, id) == 1:
|
||||
node = fillernode.replace('$id', id)
|
||||
|
||||
linedata.append(' ')
|
||||
linedata.append(node)
|
||||
linedata.append(' ')
|
||||
|
||||
|
||||
linedata.append(' ')
|
||||
linedata.append('end')
|
||||
|
||||
return linedata
|
62
generator/globals.py
Normal file
62
generator/globals.py
Normal file
@ -0,0 +1,62 @@
|
||||
from generator.helpers import config_load
|
||||
from generator.helpers import load_actors
|
||||
|
||||
# Daten für Generator
|
||||
settings = config_load('settings.ini', 'generator')
|
||||
actor_library = load_actors('actors.ini')
|
||||
|
||||
icon_admin = "🛠️"
|
||||
# icon_user = "🧍"
|
||||
icon_user = "👷♂️"
|
||||
icon_custom = '👩🚀'
|
||||
|
||||
admin_global = {
|
||||
"id": "Admin",
|
||||
"name": "_Admin FabAccess",
|
||||
"perms": ["bffh.users.manage", "bffh.users.info", "bffh.users.admin"]
|
||||
}
|
||||
|
||||
manager_schichtleitung = {
|
||||
"id": "_manager_schichtleitung",
|
||||
"name": "_Manager Schichtleitung",
|
||||
"perms": []
|
||||
}
|
||||
|
||||
# Daten für CSV-Import
|
||||
csv_match = {
|
||||
"Name Domäne": "domain_name",
|
||||
"Name Bereich": "area_name",
|
||||
"Name Unterbereich": "subarea_name",
|
||||
"ID Domäne": "domain_id",
|
||||
"ID Bereich": "area_id",
|
||||
"ID Unterbereich": "subarea_id",
|
||||
"ID Maschine": "machine_id",
|
||||
"Manager Unterbereich": "subarea_manager",
|
||||
"Name Bereich": "area_name",
|
||||
"Name Unterbereich": "subarea_name",
|
||||
"Name Maschine": "machine_name",
|
||||
"Maschinenbeschreibung": "machine_desc",
|
||||
"Wiki-URL": "wikiurl",
|
||||
"Aktor ID": "actor_id",
|
||||
"Aktor Modul": "actor_module",
|
||||
"Aktor Typ": "actor_type",
|
||||
"ID Alternativrolle": "customrole_id",
|
||||
"Name Alternativrolle": "customrole_name",
|
||||
}
|
||||
|
||||
importcheck = {
|
||||
"single": {
|
||||
"domain_name": "",
|
||||
"domain_id": "",
|
||||
"area_id": "",
|
||||
"machine_id": "",
|
||||
"area_name": "",
|
||||
"machine_name": "",
|
||||
},
|
||||
"pairs": {
|
||||
"subarea_id": "subarea_name",
|
||||
"customrole_id": "customrole_name",
|
||||
}
|
||||
}
|
||||
|
||||
space = '\t'
|
223
generator/helpers.py
Normal file
223
generator/helpers.py
Normal file
@ -0,0 +1,223 @@
|
||||
import os
|
||||
import re
|
||||
import csv
|
||||
from configparser import ConfigParser
|
||||
|
||||
current_directory = os.path.dirname(os.path.realpath(__file__))
|
||||
parent_directory = os.path.dirname(current_directory)
|
||||
app_path = parent_directory
|
||||
|
||||
# String Cleanup
|
||||
def string_clean(string):
|
||||
|
||||
zeichen = {
|
||||
"ä": "ae",
|
||||
"ö": "oe",
|
||||
"ü": "ue",
|
||||
"Ä": "Ae",
|
||||
"Ö": "Oe",
|
||||
"Ü": "Ue",
|
||||
"ß": "ss",
|
||||
"²": "2",
|
||||
"³": "3",
|
||||
}
|
||||
|
||||
for el in zeichen:
|
||||
string = string.replace(el, zeichen[el])
|
||||
|
||||
string = re.sub('[^a-zA-Z0-9]','',string)
|
||||
|
||||
return string
|
||||
|
||||
def string_removequotes(string):
|
||||
string = string.replace('"', '')
|
||||
|
||||
return string
|
||||
|
||||
def dict_sort(data):
|
||||
data = dict(sorted(data.items()))
|
||||
return data
|
||||
|
||||
def dict_keycount(data, key):
|
||||
count = 0
|
||||
for d in data:
|
||||
if key in d:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def list_join(my_list, insert):
|
||||
my_string = f'{insert}'.join(str(element) for element in my_list)
|
||||
return my_string
|
||||
|
||||
# CSV einlesen: Erzeugt eine Liste, die für jede Zeile ein Dictionary mit Header und Value ausgibt
|
||||
def csv_listdict(filename, replacedict = {}):
|
||||
|
||||
csvfile = open(filename, 'r', encoding='utf-8-sig')
|
||||
tempfile = ''
|
||||
|
||||
# Dictionary mit Ersetzungen vorhanden:
|
||||
if len(replacedict) > 0:
|
||||
tempdata = []
|
||||
|
||||
# Tempfile mit aktualisiertem Header erzeugen
|
||||
for el in csvfile:
|
||||
tempdata.append(el)
|
||||
|
||||
for key in replacedict:
|
||||
tempdata[0] = tempdata[0].replace(key, replacedict[key])
|
||||
|
||||
tempfile = 'temp.csv'
|
||||
csvfile.close()
|
||||
|
||||
write_file(tempfile, tempdata)
|
||||
filename = tempfile
|
||||
|
||||
|
||||
# Dictionary bilden
|
||||
csvfile = open(filename, mode='r', encoding='utf-8-sig')
|
||||
reader = csv.DictReader(csvfile, delimiter=';')
|
||||
|
||||
finaldata = []
|
||||
|
||||
for row in reader:
|
||||
finaldata.append(row)
|
||||
csvfile.close()
|
||||
|
||||
if len(tempfile) > 0:
|
||||
os.remove(tempfile)
|
||||
|
||||
return finaldata
|
||||
|
||||
# Datei schreiben
|
||||
def write_file(filename, content):
|
||||
f = open(filename, "w", encoding='utf-8', newline='\n')
|
||||
for line in content:
|
||||
if '\n' in line:
|
||||
f.write(line)
|
||||
else:
|
||||
f.write(line + '\n')
|
||||
f.close()
|
||||
|
||||
# Dictionary schön ausgeben
|
||||
def print_dict(d,depth=0):
|
||||
|
||||
if depth == 0:
|
||||
print('')
|
||||
print(' ----- Dictionary ----- ')
|
||||
|
||||
space = " "
|
||||
if depth == 0:
|
||||
string = ''
|
||||
else:
|
||||
string = space * depth + '|- '
|
||||
|
||||
for k,v in sorted(d.items(),key=lambda x: x[0]):
|
||||
if isinstance(v, dict):
|
||||
print(string + ("%s" % k))
|
||||
print_dict(v,depth+1)
|
||||
else:
|
||||
print(string + "%s = %s" % (k, v))
|
||||
|
||||
# Array ausgeben
|
||||
def print_array(array):
|
||||
for el in array:
|
||||
print(el)
|
||||
|
||||
# Gesamte Config einlesen und Sektionen als Einzelwerte speichern
|
||||
def config_load(file, section = 'all'):
|
||||
dict_settings = {}
|
||||
|
||||
filehandle = app_path + f'/{file}'
|
||||
|
||||
config = ConfigParser()
|
||||
config.read(filehandle)
|
||||
|
||||
list_sections = config.sections()
|
||||
|
||||
if section == 'all':
|
||||
# Mehrere Sections
|
||||
for section in list_sections:
|
||||
|
||||
dict_settings[section] = {}
|
||||
|
||||
content = dict(config.items(section))
|
||||
|
||||
for key in content:
|
||||
|
||||
value = content[key]
|
||||
|
||||
# Integer
|
||||
if value.isdigit() == True:
|
||||
save = int(value)
|
||||
# Boolean
|
||||
elif value == 'True':
|
||||
save = True
|
||||
elif value == 'False':
|
||||
save = False
|
||||
else:
|
||||
save = value
|
||||
|
||||
dict_settings[section][key] = save
|
||||
else:
|
||||
# Einzelne Section
|
||||
content = dict(config.items(section))
|
||||
|
||||
for key in content:
|
||||
|
||||
value = content[key]
|
||||
|
||||
# Integer
|
||||
if value.isdigit() == True:
|
||||
save = int(value)
|
||||
# Boolean
|
||||
elif value == 'True':
|
||||
save = True
|
||||
elif value == 'False':
|
||||
save = False
|
||||
else:
|
||||
save = value
|
||||
|
||||
dict_settings[key] = save
|
||||
|
||||
return dict_settings
|
||||
|
||||
|
||||
# ------------------ ALT ---------------
|
||||
|
||||
|
||||
# Maschinen-Dictionary sortieren
|
||||
|
||||
# Actor-Library einlesen
|
||||
def load_actors(file):
|
||||
dict_actors = {}
|
||||
|
||||
filehandle = app_path + f'/{file}'
|
||||
|
||||
config = ConfigParser()
|
||||
config.read(filehandle)
|
||||
|
||||
section_list = config.sections()
|
||||
|
||||
for section in section_list:
|
||||
|
||||
actor = section.lower()
|
||||
dict_actors[actor] = {
|
||||
"module": '',
|
||||
"params": {}
|
||||
}
|
||||
|
||||
content = dict(config.items(section))
|
||||
|
||||
for key, value in content.items():
|
||||
|
||||
|
||||
if key == "module":
|
||||
dict_actors[actor]["module"] = value
|
||||
|
||||
if 'param_' in key:
|
||||
param_name = key.replace('param_', '').lower()
|
||||
dict_actors[actor]["params"][param_name] = value
|
||||
|
||||
# print (f'{key} = {value}')
|
||||
|
||||
return dict_actors
|
16
maschinenliste.csv
Normal file
16
maschinenliste.csv
Normal file
@ -0,0 +1,16 @@
|
||||
Name Domäne;Name Bereich;Name Unterbereich;Name Maschine;Maschinenbeschreibung;Manager Unterbereich;ID Alternativrolle;Name Alternativrolle;Wiki-URL;ID Domäne;ID Bereich;ID Unterbereich;ID Maschine;Aktor ID;Aktor Typ;Kommentar
|
||||
Beispielwerkstatt;Holzwerkstatt;Bandsäge;Bandsäge;Bandsäge im Holzbereich;;;;;beispielw;holz;bandsaege;bandsaege;1;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;Hobelmaschine;Hobelmaschine;Hobelmaschine im Holzbereich;;;;;beispielw;holz;hobelmaschine;hobelmaschine;2;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;CNC-Fräse;CNC-Fräse;CNC Fräse im Holzbereich;;;;;beispielw;holz;holzcnc;holzcncfraese;6;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;;Kappsäge;Kappsäge mit allgemeiner Einweisung Holz;;;;;beispielw;holz;;kappsaege;7;Tasmota;
|
||||
Beispielwerkstatt;Holzwerkstatt;;Bandschleifer;Bandschleifer mit allgemeiner Einweisung Holz;;;;;beispielw;holz;;bandschleifer;8;Tasmota;Irgendein Kommentar
|
||||
Beispielwerkstatt;Holzwerkstatt;;Ständerbohrmaschine;Ständerbohrmaschine mit allgemeiner Einweisung Holz;;;;;beispielw;holz;;staenderbohrmaschine;9;Tasmota;
|
||||
Beispielwerkstatt;Textilwerkstatt;;Nähmaschine 1;Nähmaschine Nummer 1;;;;;beispielw;textil;;naehmaschine1;10;Tasmota;
|
||||
Beispielwerkstatt;Textilwerkstatt;;Nähmaschine 2;Nähmaschine Nummer 2;;;;;beispielw;textil;;naehmaschine2;11;Tasmota;
|
||||
Beispielwerkstatt;FabLab;3D-Druck;3D-Drucker 1;3D-Drucker Modell 111;x;;;;beispielw;fablab;3dprint;3ddrucker1;12;Tasmota;
|
||||
Beispielwerkstatt;FabLab;3D-Druck;3D-Drucker 2;3D-Drucker Modell 222;x;;;;beispielw;fablab;3dprint;3ddrucker2;13;Tasmota;
|
||||
Beispielwerkstatt;FabLab;Laser;Lasercutter;Modell Laser3000;x;;;https://www.fiktivedoku.de;beispielw;fablab;laser;laser3000;14;Tasmota;
|
||||
Beispielwerkstatt;FabLab;Laser;Kühlung;Modell Kühlung3000;x;;;;beispielw;fablab;laser;kühlung3000;15;Tasmota;
|
||||
Beispielwerkstatt;Siebdruck;;SD-Belichter;Belichter für die Siebe;;;;;beispielw;siebdruck;;sdbelichter;16;Tasmota;
|
||||
Beispielwerkstatt;Siebdruck;;A3-Drucker;A3 Drucker im Siebdruck Bereich;;drucker;Druckernutzung;;beispielw;siebdruck;;a3drucker;17;Tasmota;
|
||||
Beispielwerkstatt;Büro;;Drucker;;;drucker;Druckernutzung;;beispielw;büro;;drucker;18;Tasmota;
|
|
45
settings.ini
Normal file
45
settings.ini
Normal file
@ -0,0 +1,45 @@
|
||||
; ------------ Einstellungen für den DHALL-Generator ------------
|
||||
; Einstellung aktiv = True
|
||||
; Einstellung inkativ = False
|
||||
|
||||
[generator]
|
||||
; Verwendung mehrer Domänen. Bei Verwendung mehrer Domänen werden einzelne Admins nur für die Domäne erstellt
|
||||
multi_domains = False
|
||||
|
||||
; Rolle "Schichtleitung" erstellen, die über Manager-Berechtigungen für alle Domänen verfügt
|
||||
manager_schichtleitung = True
|
||||
|
||||
; Manager-Rolle für jeden Bereich erstellen
|
||||
manager_area = True
|
||||
|
||||
; Spalte "Unterbereich Manager" der CSV beachten (True) der nicht (False).
|
||||
manager_subarea = True
|
||||
|
||||
; Automatisches Einfügen aller erzeugten Daten (Maschinen, Rolle, Aktoren, Aktor-Verbindungen) in die bffh.dhall
|
||||
; Die Datei muss über Platzhalter verfügen, siehe Beispieldatei ( /docs/bffh-vorlage.dhall )
|
||||
fa_update_dhall = False
|
||||
|
||||
; Pfad zur bffh.dall von FabAccess. Der Pfad muss vollständig sein und die bffh.dhall beinhalten.
|
||||
; Beispiel: D:\FabAccess\config\bffh\bffh.dhall bzw. /home/fabaccess/bffh/bffh.dhall
|
||||
fa_dhall_file =
|
||||
|
||||
; Mermaid-Code erzeugen
|
||||
generate_mermaid = True
|
||||
|
||||
; Gesonderte Datei die eine Liste aller Rollen enthält
|
||||
create_file_roles = True
|
||||
|
||||
; Anzeige aller erzeugten Maschinendaten
|
||||
show_machines = False
|
||||
|
||||
; Anzeige aller erzeugten Rollendaten
|
||||
show_roles = False
|
||||
|
||||
; Kennzeichnung für Administrator-Rollen, steht am Anfang des Namens der Rolle.
|
||||
string_adminhandle = Admin
|
||||
|
||||
; Kennzeichnung für Manager-Rollen, steht am Anfang des Namens der Rolle.
|
||||
string_managerhandle = Manager
|
||||
|
||||
; Kennzeichnung für Benutzer-Rollen, steht am Anfang des Namens der Rolle.
|
||||
string_userhandle = Benutzer
|
Loading…
x
Reference in New Issue
Block a user