Setup
SARA (Datenerfassung)
Daten der angeschlossenen Sensoren können über die Serielle Schnittstelle, genauso wie von der Bluetooth Low Energy Schnittstelle empfangen werden.
Serielle Schnittstelle
Um Daten von der Seriellen Schnittstelle zu empfangen, muss das Gerät über USB
an den Computer angeschlossen werden. Die Serielle Schnittstelle kann dann über
den Port /dev/ttyUSB0 erreicht werden. Dies kann über ein Terminalprogramm wie
minicom oder screen erfolgen.
minicom -D /dev/ttyACM0 -b 115200
Anschließend müssen Befehle an das Gerät gesendet werden, um Daten zu empfangen. Diese müssen über ein CR LF angänsel übermittelt werden Das sieht wie folgt aus:
serial.write("t\r\n");
Sara übermittelt dann die Daten in dem Muster: Computer --> "t\r\n" "t:20.45\r\n"
Befehle: - "t" -> Temperatur - "h" -> Luftfeuchtigkeit - "wd" -> Windrichtung - "rfm" -> Niederschlagsmessung - "ws" -> Windgeschwindigkeit - "ble" -> Bluetooth Low Energy Zustand - "bat" -> Batteriestatus - "help" -> Hilfe
Bluetooth Low Energy
Die Bluetooth Low Energy Schnittstelle kann über die Kennung "SARA Weather Station" erreicht werden. Diese Kennung wird auch als BLE Local Name bezeichnet. Nachdem eine Verbindung hergestellt wurde können über die BLE-Service UUIDs die Daten abgerufen werden. Folgende Services sind implementiert:
- Air Service: 0x1101
- Temperatur Charakteristik: 0x2101 (Notify/Read)
- Luftfeuchtigkeit Charakteristik: 0x2102 (Notify/Read)
- Weather Station Service: 0x1102
- Niederschlagsmessung Charakteristik: 0x2203 (Notify/Read)
- Windrichtung Charakteristik: 0x2201 (Notify/Read)
- Windgeschwindigkeit Charakteristik: 0x2202 (Notify/Read)
- Power Service: 0x1103
- Batteriestatus Charakteristik: 0x2301 (Notify/Read)
- Batteriespannung Charakteristik: 0x2302 (Notify/Read)
Notify: Hier auf auf die Charakteristik abonniert. Dabei wird bei einer Änderung der neue Wert übermittelt. Das Geschieht über die BLE-Notification, welche alle 200ms aktualisiert werden.
Read: Bei Read wird der aktuelle Wert der Charakteristik abgefragt.
Neue Services und Charakteristiken können über die Konfigurationsdatei
SARABLE.cpphinzugefügt werden.
SOPS
SOPS wird zur Verschlüsselung von Credentials verwendet. In diesem Projekt werden die Credentials in der Datei server/secrets/secrets.dev.enc.env gespeichert und mit SOPS verschlüsselt.
Für Prod und Dev werden andere Keys verwendet. Alle Entwickler*innen brauchen einen Schlüssel für die Dev Credentials. Um neue Secrets hinzuzufügen wird sops auf dem Entwicklungs-PC benötigt.
Um die Datei zu bearbeiten muss folgende Umgebungsvariable gesetzt werden. Diese zeigt auf den Schlüssel, der für die Verschlüsselung der secret Datei verwendet wurde.
SOPS_AGE_KEY_FILE: /secrets/key.txt
Mit sops edit secrets.dev.enc.env kann die Datei bearbeitet werden. Nach dem Speichern und schließen der Datei wird diese wieder verschlüsselt.
Es kommt ein Docker Deployment zum Einsatz, welches die entschlüsselung automatisch vornimmt, somit ist nur der Schlüssel in /server/secrets notwendig.
Um eine manuelle Entschlüsselung durchzuführen, kann folgender Befehl verwendet werden:
docker compose up sops --build
Das Docker Deployment ersetzt die entschlüsselte Datei nach jedem Start, sodass Änderungen in der entschlüsselten Datei nicht übernommen werden.
Grafana (Datenerfassung)
Erstellen eines Dashboards
- Öffnen Sie https://maytastix.de/grafana
- Melden Sie sich mit den gesetzten Credentials an
- Navigieren Sie zu Dashboards
- Legen Sie ein neues Diagramm an
Backend-Service
Entwickeln
Um Änderungen an der API-Vorzunehmen bearbeiten sie die DataBaseAPI.py im Verzeichnis /server/deployment.
Starten
Um die API zu starten führen Sie im Verzeichnis /server folgenden Command aus:
docker-compose up python_app --build
Die API ist dann standardmäßig über http://localhost:5000 erreichbar.
Monitoring-Service
Entwickeln
Um Änderungen an der API-Vorzunehmen bearbeiten sie die RedisMircoservie.py im Verzeichnis /server/deployment/redis_microservice.
Starten
Um die API zu starten führen Sie im Verzeichnis /server folgenden Command aus:
docker-compose up redis_microservice --build
Die beiden Websockets sind standardmäßig über ws://localhost:5001 & ws://localhost:5002 erreichbar.
NGINX
Für das Deployment wird ein NGINX-Server verwendet, der als Reverse-Proxy für die verschiedenen Services dient. Die Konfiguration für NGINX befindet sich im Verzeichnis server/prod.
Alternativ kann auch nginx proxy Manager verwendet werden. Hier muss man die Konfiguration in der GUI anpassen.
So könnte die Konfiguration innerhalb des Proxy Managers aussehen:
blickbox.maytastix.de
http://valentin:80
dhbwapi.maytastix.de
http://server-python_app-1:5000
dhbwgrafana.maytastix.de
https://grafana-server:3000
npm.maytastix.de
http://server-reverse-proxy-1:81
Um einen schon vorhandenen Nginx Server zu konfigurieren, können folgende Schritte durchgeführt werden:
- Erstelle in /srv und /opt einen Ordner
Das Deployment compose.prod.yml nutzt den Ordner /srv/blickbox für die Anwendungsdaten (volumes) Um das Prod Deployment zu starten führe folgendes Kommando aus docker compose -f compose.prod.yaml up
In /opt wird das Repository geladen In /srv werden die Anwendungsdaten, die bei der Ausführung entstehen gespeichert Die Ports der Anwendungen werden auf localhost weitergeleitet:
Port 3000 -> Grafana Port 3001 -> Valentin Port 3002 -> API
- Für die Service sind folgende Routen vorgesehen
https://blickbox.maytastix.de -> Valentin https://blickbox.maytastix.de/api -> API https://blickbox.maytastix.de/grafana -> Grafana
-
Konfigurieren des Reverse Proxies Das Deployment nutzt einen auf dem Server laufenden Nginx Reverse Proxy welcher mit der Datei blickbox.maytastix.de konfiguriert wurde
-
Erstelle die Datei in
etc/nginx/sites-availableblickbox.maytastix.de mit folgenden Inhalt
server {
listen 80;
listen [::]:80;
root /var/www/blickbox.maytastix.de;
index index.html;
server_name blickbox.maytastix.de;
}
-
Erstelle einen Symbolic Link um die Konfiguration nginx bekannt zu machen ln -s /etc/nginx/sites-available/blickbox.maytastix.de /etc/nginx/sites-enabled/
-
Rufe certbot auf und erstelle ein Zertifikat für blickbox.maytastix.de Füge anschließend folgenden Inhalt unter die Zeilen ein.
root /var/www/blickbox.maytastix.de;
index index.html;
server_name blickbox.maytastix.de;
location / {
proxy_pass http://localhost:3001/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 0;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
access_log /var/log/nginx/valentin.access.log;
error_log /var/log/nginx/valentin.error.log;
}
location /api/ {
proxy_pass http://localhost:3002/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 0;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
access_log /var/log/nginx/api.access.log;
error_log /var/log/nginx/api.error.log;
}
location /grafana/ {
proxy_pass http://localhost:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 0;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
access_log /var/log/nginx/graphana.access.log;
error_log /var/log/nginx/graphana.error.log;
}
-
Vergleich die Datei /server/prod/blickbox.maytastix.de mit deiner Konfiguration Reloade nginx systemctl reload nginx
-
Deine Services sollte über folgende Links erreichbar sein
https://blickbox.maytastix.de -> Valentin https://blickbox.maytastix.de/api -> API https://blickbox.maytastix.de/grafana -> Grafana
Jenknins Pipline
Diese Teil beschreibt die Einrichtung, Verwendung und Details der Jenkins-Pipeline für das Blickbox-Projekt.
Einrichtung der Jenkins-Pipeline
- Öffnen Sie Jenkins unter http://maytastix.de:3005/jenkins/
- Erstellen Sie ein neues Pipeline-Projekt:
- Klicken Sie auf "Neue Item" im Jenkins-Dashboard
- Geben Sie einen Namen für Ihr Projekt ein
- Wählen Sie "Pipeline" als Projekttyp
- Klicken Sie auf "OK"
- Konfigurieren Sie die Pipeline:
- Scrollen Sie zum Abschnitt "Pipeline"
- Wählen Sie "Pipeline script from SCM" als Definition
- Wählen Sie "Git" als SCM
- Geben Sie die URL Ihres Git-Repositories ein
- Stellen Sie sicher, dass der Branch "production" ausgewählt ist
- Setzen Sie "Jenkinsfile" als Script-Pfad
- Speichern Sie die Konfiguration.
Verwendung der Pipeline
Die Pipeline wird automatisch ausgeführt, wenn Änderungen im "production" Branch erkannt werden. Sie können sie auch manuell starten: 1. Navigieren Sie zu Ihrem Pipeline-Projekt in Jenkins 2. Klicken Sie auf "Build Now"
Pipeline-Schritte im Detail
Die Pipeline durchläuft folgende Hauptphasen:
| Schritt | Beschreibung |
|---|---|
| Git Checkout | Lädt den aktuellen Code aus dem Git-Repository |
| Git GitLeaks Scan | Führt einen GitLeaks-Scan durch, um sensible Daten im Code zu identifizieren |
| SARA Setup, Tests und Linting | Richtet die Build-Umgebung für SARA ein, führt Unit-Tests und Code-Linting durch |
| ADA Setup, Build, Test und Linting | Richtet die Rust-Umgebung ein, baut das ADA-Projekt, führt Tests und Sicherheits-Audits durch |
| Backend Setup, Tests und Sicherheit | Richtet die Python-Umgebung ein, führt API-Tests, Microservice-Tests und Sicherheits-Scans durch |
| Valentin Build, Tests und Sicherheit | Baut das VALENTIN-Projekt, führt Tests und Sicherheits-Checks durch |
| Docker Dockerfile Analyse | Analysiert alle Dockerfiles im Projekt mit Hadolint |
| Deployment Copy to Deploy Directory | Kopiert das Projekt in das Deployment-Verzeichnis und entschlüsselt Zugangsdaten |
| Deployment Launch | Startet die Docker-Container für die Produktion |
Hinzufügen neuer Schritte zur Pipeline
Um neue Schritte zur Pipeline hinzuzufügen:
-
Öffnen Sie die
Jenkinsfileim Root-Verzeichnis des "production" Branches. -
Fügen Sie einen neuen
stageBlock hinzu. Beispiel:
groovy
stage('Neuer Schritt') {
steps {
// Ihre Befehle hier
sh 'echo "Dies ist ein neuer Schritt"'
}
}
-
Platzieren Sie den neuen
stageBlock an der gewünschten Stelle in der Pipeline. -
Committen und pushen Sie Ihre Änderungen zum "production" Branch.
-
Jenkins wird die aktualisierte Pipeline automatisch verwenden.
Tipps für die Erweiterung der Pipeline
- Gruppieren Sie zusammengehörige Schritte in einem
stage. - Verwenden Sie aussagekräftige Namen für Ihre Stages.
- Nutzen Sie Umgebungsvariablen für wiederverwendbare Werte.
- Fügen Sie Post-Actions hinzu, um auf Erfolg oder Fehler zu reagieren.
- Nutzen Sie Parallel-Schritte für unabhängige Aufgaben, um die Ausführungszeit zu reduzieren.
- Denken Sie daran, neue Tools oder Abhängigkeiten im Jenkins-Umfeld zu installieren, wenn Sie sie in der Pipeline verwenden möchten.
Fehlerbehebung
- Überprüfen Sie die Konsolenausgabe in Jenkins für detaillierte Fehlerinformationen.
- Stellen Sie sicher, dass alle erforderlichen Tools und Abhängigkeiten auf dem Jenkins-Server installiert sind.
- Überprüfen Sie die Berechtigungen, wenn Zugriffsprobleme auftreten.
- Bei Problemen mit spezifischen Stages, isolieren Sie den Schritt und führen Sie ihn manuell aus, um das Problem einzugrenzen.
- Überprüfen Sie die Versionen der verwendeten Tools und aktualisieren Sie sie gegebenenfalls.
Bei Fragen oder Problemen wenden Sie sich bitte an das DevOps-Team.
Valentin Dashboard
Dieses Projekt wurde mit Create React App erstellt.
Verfügbare Skripte
Im Projektverzeichnis können Sie folgende Befehle ausführen:
npm install
npm start
Startet die App im Entwicklungsmodus.\ Öffnen Sie http://localhost:3000, um sie im Browser anzuzeigen.
Die Seite wird automatisch neu geladen, wenn Sie Änderungen vornehmen.\
npm run build
Erstellt die App für die Produktion im build-Ordner.\
Es bündelt React korrekt im Produktionsmodus und optimiert den Build für die beste Performance.\
Der Build wird minifiziert und die Dateinamen enthalten Hashes.
ADA (Datenvermittlung)
Rust Toolchain installieren oder updaten
Hier sind die Schritte zur Weiterentwicklung mit Rust aufgeführt.
Zuerst muss Rustup heruntergeladen werden, um Rust zu installieren.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Um die neuste Version von Rust zu verwenden, updatet folgender Befehl die Rust-Version.
rustup update
Jetzt kann Rust im Projekt verwenden werden.
cd blickbox/ada
Funktionsfähigkeit von ADA
Um ADA einzusetzen, muss das Gerät, auf dem ADA läuft, Bluetooth- und WLAN-fähig sein.
Weitere Informationen
MkDocs mit GitHub Pages
Dieses Repository enthält die Dokumentation für DHBW-Blickbox, erstellt mit MkDocs und gehostet auf GitHub Pages.
Folgen Sie diesen Schritten, um das Projekt einzurichten und die Dokumentation zu deployen:
MkDocs-Projekt Abhänigkeit
# MkDocs installieren
pip install mkdocs
pip install mkdocs-material
# In das Projektverzeichnis wechseln
cd docs/mkdocs/
Aktualisierungen vornehmen
- Nehmen Sie Änderungen an Ihren Markdown-Dateien vor
- Committen und pushen Sie die Änderungen:
git add .
# Richter Branche
git commit -m "Update documentation" # Richtiger Branche
git push
- Deployen Sie die aktualisierten Seiten:
mkdocs gh-deploy
Die Änderung erscheint nach einigen Minuten unter https://mxmueller.github.io/DHBW-Blickbox in Ihrem Browser.
Lokale Entwicklung
Um die Dokumentation lokal zu testen, führen Sie folgenden Befehl aus:
mkdocs serve
Öffnen Sie dann http://127.0.0.1:8000/ in Ihrem Browser.
Weitere Informationen
C4 Diagramme
Mermaid für Diagramme
Nach dem Vergleich verschiedener Technologien fällt die Wahl auf den Mermaid Live Editor. Dieser kann wie folgt aufgerufen werden: https://mermaid.live/
Aufbau von Mermaid
Die Dokumentation von mermaid zu C4 findet sich unter: https://mermaid.js.org/syntax/c4.html
Die Syntax von PlantUML kann verwendet werden: https://github.com/plantuml-stdlib/C4-PlantUML/blob/master/README.md
Basiscode Beispiel eines C4 Diagramms:
C4Context
title System Context diagram for Internet Banking System
Enterprise_Boundary(b0, "BankBoundary0") {
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
Person(customerB, "Banking Customer B")
Person_Ext(customerC, "Banking Customer C", "desc")
Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
Enterprise_Boundary(b1, "BankBoundary") {
SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
System_Boundary(b2, "BankBoundary2") {
System(SystemA, "Banking System A")
System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts. next line.")
}
System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")
Boundary(b3, "BankBoundary3", "boundary") {
SystemQueue(SystemF, "Banking System F Queue", "A system of the bank.")
SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
}
}
}
BiRel(customerA, SystemAA, "Uses")
BiRel(SystemAA, SystemE, "Uses")
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
Rel(SystemC, customerA, "Sends e-mails to")
UpdateElementStyle(customerA, $fontColor="red", $bgColor="grey", $borderColor="red")
UpdateRelStyle(customerA, SystemAA, $textColor="blue", $lineColor="blue", $offsetX="5")
UpdateRelStyle(SystemAA, SystemE, $textColor="blue", $lineColor="blue", $offsetY="-10")
UpdateRelStyle(SystemAA, SystemC, $textColor="blue", $lineColor="blue", $offsetY="-40", $offsetX="-50")
UpdateRelStyle(SystemC, customerA, $textColor="red", $lineColor="red", $offsetX="-50", $offsetY="20")
UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")