gesundheit_4.0/F\303\274r-Anwender:-Recom-Grips-\303\266ffnen.md
... ...
@@ -0,0 +1,12 @@
1
+## Voraussetzungen
2
+
3
+- Ihr Computer befindet sich im Uni-Netz bzw. im TUM-VPN
4
+- Sie haben das Programm Microsoft Remote Desktop installiert (kostenlos für PC und Mac verfügbar)
5
+
6
+## Vorgehen
7
+
8
+- Microsoft Remote Desktop öffnen
9
+- unter "+"-Symbol "PC hinzufügen"
10
+- Bei "PC Name" eingeben: `TUEDS09-RECOM.srv.mwn.de`
11
+- Mit TUM-Kennung anmelden
12
+- Die Software "GRIPS_V5" von Desktop-Verknüpfung aus starten. (Falls die Software nicht zu finden ist: Admin benachrichtigen)
... ...
\ No newline at end of file
gesundheit_4.0/Recom.md
... ...
@@ -0,0 +1,33 @@
1
+# Setup
2
+
3
+Die Software von Recom ("Recom Grips") läuft auf einer VM beim LRZ: `tueds09-recom.srv.mwn.de`. Zugriff auf die VM-Konsole, d. h. die Verwaltungsoberfläche der VM beim LRZ, hat Bert Krohn.
4
+
5
+# Admin-Zugriff
6
+
7
+Auf der VM selbst ist auch Joachim Siegert mit seiner LRZ-Kennung `ge52jep` als Admin angelegt sowie der Benutzer `RECOM` zur Nutzung durch Recom (insbesondere Gohl).
8
+
9
+# Remote Desktop Verbindungen
10
+
11
+Für einen RDP-Zugriff muss der Benutzer der Gruppe "Remotedesktopbenutzer" hinzugefügt sein und sich im TUM-VPN befinden (zu Testen: geht es aus dem MWN auch ohne VPN?).
12
+Der für RDP-Zugriffe verwendete Port 3389 ist in der Firewall nur für TUM-VPN sowie für die einzelne IP `217.239.200.202` freigegeben; diese verwendet Recom.
13
+RDP-Lizenzen haben wir extra dafür gekauft, falls die Frage jemals aufkommt.
14
+
15
+# Benutzer anlegen
16
+
17
+Studierende sollen per Remote Desktop-Zugriff mit Recom Grips arbeiten. Es ist zu klären, wie wir den Zugriff auf die VM effizient verwalten.
18
+
19
+## Variante 1: Mit TUM-Kennung
20
+
21
+Aktueller Weg: Wenn `{TUM-Kennung}` mit Recom arbeiten können soll, dann als Admin
22
+1. Startmenü -> Systemsteuerung -> Benutzerkonten -> "Anderen Benutzern Zugriff auf diesen Computer geben" (ggf. mit Admin-Anmeldedaten bestätigen) -> "Hinzufügen" -> "Durchsuchen…" -> `{TUM-Kennung}` eingeben und "Namen überprüfen" -> OK -> weiter -> Frage nach Zugriffsebene: Unter "Andere" "Remotedesktopbenutzer" auswählen. Benutzer kann sich also per RDP anmelden.
23
+2. Bei erstmaliger Anmeldung des Benutzers wird das Verzeichnis `OSDisk (C:)/Benutzer/{TUM-Kennung}` angelegt. Für Zugriff auf Recom Grips nun die Verknüpfung dazu in `OSDisk (C:)/Benutzer/{TUM-Kennung}/Desktop` kopieren, damit der Benutzer sie gleich auf dem Desktop sieht.
24
+
25
+TO DO: Mit Bert und ggf. Gohl klären, ob das ein sinnvolles Multi-User-Setup ist. Wenn ja, Prozess automatisieren (insb. automatische Erstellung der Grips-Verknüpfung, damit da nicht auf den ersten Login gewartet werden muss).
26
+
27
+## Variante 2: Lokale Benutzer
28
+
29
+Wir können auch ADS-unabhängige Benutzerkonten anlegen, z. B. `Max Mustermann`, und dann die Login-Daten für solche lokalen "Avatare" den Studierenden für die Lehre weitergeben. Vorteile: Man kann die gleichen Avatare im nächsten Semester weiter benutzen, und man muss nicht nach Erstanmeldung der Studierenden noch die Verknüpfung zu Recom Grips bereitstellen sondern kann die Erstanmeldung ein mal selbst durchführen. Außerdem könnte man die gleichen Benutzer mit dem gleichen Passwort innerhalb von Recom Grips anlegen.
30
+
31
+# Recom Grips nutzen
32
+
33
+Im Zuge einer Schulung wurden die meisten TAT4.0/DigiLLab-Teammitglieder als Nutzer in Recom Grips angelegt. Passwort ist jeweils der Nachname.
... ...
\ No newline at end of file
gesundheit_4.0/Remote-Desktop-Zugriff-und-Lizenzierung.md
... ...
@@ -0,0 +1,17 @@
1
+# Kurzfassung
2
+
3
+Da Recom keine Web-Oberfläche anbietet, sind parallele Zugriffe auf Recom Grips nur über parallele Remote Desktop Sessions auf dem Server `tueds09-recom.srv.mwn.de` möglich. Wir haben 25 Remote Desktop Lizenzen erworben und auf dem Server eingerichtet.
4
+
5
+# Konfiguration auf dem Server
6
+
7
+Dank Beratung durch das LRZ (Indicent Nr. 193572 von Joachim Siegert angelegt, Bert Krohn im cc) haben im Endeffekt folgende Schritte gefruchtet:
8
+1. https://learn.microsoft.com/en-us/troubleshoot/windows-server/remote/install-rds-host-role-service-without-connection-broker befolgen, einschließlich https://learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-activate-license-server, wo ich in Schritt 7 von "Activate the License Server" allerdings den Wizzard genutzt habe (und die Aktivierungsnummer unserer Bestellung ohne Fehlermeldung angenommen wurde).
9
+2. "Remote Desktop Session Host" Rolle installieren
10
+3. In den Gruppenrichtlinien für den Remotedesktopsitzungs-Host den Lizenzierungsmodus von "Benutzer" auf "Gerät" umgestellt
11
+
12
+# Lizenzlage
13
+
14
+Sauber ist das nicht, denn wir haben User CALs gekauft, nicht Device CALs. Eigentlich müssten wir den Server also auf nutzerbasierte Lizenzierung umstellen, also nicht mit Lokalen Benutzern passend zu den Recom-Avataren ("Max Mustermann") arbeiten, sondern tatsächlich für jede Studierenden-Kohorte die ADS-Kennungen als Benutzer anlegen. Das ist entweder viel Klickarbeit für einen HiWi, dem man Admin-Rechte geben müsste, oder wir müssen uns eine geeignete Automatisierung überlegen. Die Frage ist aufgeschoben, bis tatsächlich mal die erste LV mit Recom läuft; auf Grundlage der Erfahrungen dort können wir uns das nochmal überlegen.
15
+
16
+Ob man die User CALs so lange nach Kauf gegen Device CALs umtauschen könnte, um sich diese Umstellung auf Nutzerbasierung zu sparen, ist unklar.
17
+Die Rechnung mit der siebenstelligen Vertragsnummer, die die Lizenzen identifiziert, liegt im Projektordner unter `TAT4_0/05_Organisation/02_DigiLLab/05_EPA/Recom/Microsoft\ Lizenzen/CCF_000354.pdf`
... ...
\ No newline at end of file
industrie_4.0/DigiLLab-Factory:-Papier-Digital-Wechsel.md
... ...
@@ -0,0 +1,45 @@
1
+### Grundidee: Fortsetzung des letzten Zustands
2
+
3
+In einem neuen Training wird die Montage in dem Zustand wieder aufgenommen, den das letzte Training hinterlassen hat. Am Ende eines Trainings muss jede Station ihren aktuellen Auftrag fertigstellen und in ihren Ausgang legen. Am Anfang eines neuen Trainings muss also lediglich der Logistiker ein mal rumgehen und schon sind alle Stationen mit Arbeit versorgt.
4
+
5
+
6
+### Im Vorfeld
7
+
8
+- [ ] Im DigiLLab prüfen, ob genügend Kisten im Startzustand vorhanden sind, d. h. Kisten im Eingangslager=rechter Logistikplatz (diese enthalten das Auto im Roh-Zustand). Falls nicht: Fertige Kisten in Startzustand zurücksetzen (siehe unten "Im Nachgang").
9
+- [ ] Stationen so verschieben, dass alle Monteure genug Platz zum Arbeiten haben.
10
+- [ ] Gedrucke Montage-Anleitungen an den Stationen auslegen.
11
+
12
+### Erste Runde: Papierbasierte Montage
13
+
14
+- [ ] Auf dem Meister-PC Firefox öffnen und das Lesezeichen "Odoo" anklicken. Odoo öffnet sich mit einer Ansicht der aktuellen Fertigungsaufträge.
15
+- [ ] Um Fertigungsaufträge hinzuzufügen: **a) Make to stock**: Oben links "Neu", dann als Produkt "Racer" eintippen und eine der gespeicherten Varianten auswählen, und oben links "Bestätigen". **b) Make to order:** Gleiches Vorgehen, anhand eines eingegangenen Auftrags (Brief, Email; TO DO Joachim: Beispiel-Bestellungen ausdrucken bzw. Email-Eingang simulieren)
16
+
17
+Die folgenden Schritte sind nur nötig, wenn zuletzt digital produziert wurde, was der Regelfall ist. Sollte ausnahmsweise zuletzt ohnehin schon papierbasiert produziert worden sein, dann liegen bereits überall Umlaufzettel bereit und die papierbasierte Fertigung kann direkt aufgenommen werden.
18
+
19
+- [ ] Umlaufzettel ausdrucken: Alle Fertigungsaufträge in Odoo auswählen, dann auf das Drucker-Symbol (mittig über der Auftragsliste) klicken, vierten Menüpunkt "Production Order mit Konfiguration" auswählen. Nach <1min Wartezeit wird eine mehrseitige PDF erzeugt. Diese ausdrucken (Papier dabei nur einseitig bedrucken).
20
+- [ ] Umlaufzettel verteilen: Odoo zeigt in der Spalte "current location" den letzten digital erfassten Standort an, was also dem anfänglichen Standort in der Papierrunde entspricht. Die Umlaufzettel der Aufträge, die schon an Stationen sind, in die entsprechenden Kisten legen. Die Umlaufzettel der Aufträge mit Standort "Lager" und Status "bestätigt" in beliebige Kisten des Eingangslagers legen. Sonderfall: Gibt es einen Auftrag mit Standort "Lager", der schon den Status "In Bearbeitung" hat, so muss dessen Umlaufzettel in diejenige Kiste gelegt werden, die für diesen Auftrag gescannt worden ist (zeigt die entsprechende Auftragsnummer auf e-Ink-Display an).
21
+- [ ] In Odoo die Spalte "current location" ausblenden durch Klick auf Schieberegler oben rechts in der Liste der Fertigungsaufträge und Entfernen des Hakens bei "current location", denn die dort angezeigten Informationen verlieren in der Papierrunde ihre Gültigkeit.
22
+- [ ] Einarbeitungsrunde: Alle Stationen einen Auftrag ohne Zeitangabe abarbeiten lassen, damit sich die Schulungsteilnehmer ein mal mit den Anleitungen und Montageschritten vertraut machen können, und Logistiker sowie Produktionsleiter einweisen. [Wie kommen Umlaufzettel vom Produktionsleitstand zum Eingangslager und vom Ausgangslager zum Leitstand? Macht das der Logistiker oder der Produktionsleiter?]
23
+- [ ] Produktion: Monteure ihre Arbeitszeiten mittels Stoppuhr erfassen lassen (To Do Joachim: bestellen). Ist ein Auftrag fertig montiert, so muss der Produktionsleiter die erfassten Zeiten eingeben, indem er den Auftrag in Odoo öffnet und dann im Reiter "Arbeitsaufträge" in der Spalte "tatsächliche Dauer" die Zeit einträgt. [TO DO: In Kopie der DB testen!]
24
+- [ ] Am Ende der Produktion: Alle Monteure ihren aktuellen Arbeitsschritt beenden und die Zeit notieren lassen.
25
+
26
+### Umstellung Papier -> digital
27
+
28
+- [ ] Stationen hochfahren und Server einschalten (vgl. Anleitung zu reinem digital-Ablauf)
29
+- [ ] Für die offenen Aufträge laut Logistik-Display in der Reihenfolge, in der sie angezeigt werden, erstens die zugehörige Kiste von der Station holen und einscannen, damit ihr dieser Auftrag zugewiesen wird, und wieder an die Station zurücktragen, und zweitens die Zeiten aus dem Umlaufzettel in Odoo abtippen damit der Fertigungsfortschritt erfasst ist
30
+- [ ] Dann Hochfahren der Produktion entsprechend Anleitung zu reinem digital-Ablauf
31
+
32
+
33
+
34
+### Im Nachgang
35
+
36
+Fertig montierte Autos sammeln sich im Ausgangslager (=linker Logistikplatz) an. Die e-Ink-Displays der Kisten dort zeigen dementsprechend "Produktion abgeschlossen" an. Um das Eingangslager wieder aufzufüllen:
37
+- [ ] Alle(!) Autos in den fertigen Kisten wieder demontieren.
38
+- [ ] "Steuerung öffnen" (wenn der Server nicht mehr läuft, muss er hierfür gestartet werden), "Erweitert" anklicken, "Alle fertigen Boxen zurücksetzen" anklicken. Alle Kisten, die bis dahin "Produktion abgeschlossen" angezeigt hatten, werden nun zurückgesetzt und können für neue Aufträge genutzt werden.
39
+- [ ] Alle Kisten ins Eingangslager (=rechter Logistikplatz) legen.
40
+
41
+Zuletzt den Server stoppen und den Strom an den Stationen mit der Fernbedienung, Taste A Off, abschalten.
42
+
43
+### Troubleshooting
44
+
45
+Wenn sich eine Station nicht verbindet oder es an einer Station ein Problem gibt, wie z. B. ein nicht verbundener RFID-Scanner (Scan einer Box verursacht nur Piepen, aber kein Update im Fertigungsfortschritt), dann das Stromkabel, das den Kleincomputer dieser Station versorg, ab- und anstecken um die Station neu zu starten.
industrie_4.0/DigiLLab-Factory:-Schulung-durchf\303\274hren.md
... ...
@@ -0,0 +1,98 @@
1
+### Grundidee: Fortsetzung des letzten Zustands
2
+
3
+In einem neuen Training wird die Montage in dem Zustand wieder aufgenommen, den die letzte Nutzung hinterlassen hat. Am Anfang eines neuen Trainings sind also direkt alle Stationen mit Arbeit versorgt.
4
+
5
+| Achtung |
6
+| ------ |
7
+| Wenn Kisten für andere als Schulungszwecke bewegt werden (Fototermine o. ä.), dann nachher an die ursprüngliche Position zurückstellen; sonst divergieren physischer Zustand und digitaler Zustand. Wenn für Demo-Zwecke die Factory hochgefahren und Kisten gescannt werden, dann gilt wie in Schulungen (s. u.), dass an jeder Station alle Schritte zum laufenden Auftrag (Standort "Station X Desk") fertig gemeldet werden müssen bevor wieder heruntergefahren werden kann. |
8
+
9
+
10
+
11
+### Im Vorfeld
12
+
13
+- [ ] Im DigiLLab prüfen, ob genügend Bauteile an den Stationen und genügend Kisten im Startzustand vorhanden sind, d. h. Kisten im Eingangslager=rechter Logistikplatz (diese enthalten das Auto im Roh-Zustand). Falls nicht: Fertige Aufträge demontieren (siehe unten "Im Nachgang").
14
+- [ ] Vergewissern, dass die Kisten an der richtigen Stelle stehen: Im Stationseingang (=obere Rutsche) von Station Y dürfen nur Kisten stehen, deren e-Ink-Display den Transportauftrag X->Y anzeigt, und im Stationsausgang (=untere Rutsche) von Station Y dürfen nur Kisten stehen, deren e-Ink-Display den Transportauftrag Y->Z anzeigt.
15
+
16
+### Trainingsablauf
17
+- [ ] Stationen so verschieben, dass alle genug Platz zum Montieren haben.
18
+- [ ] Alle Stationen mit der Fernbedienung einschalten (Taste A). Es ertönten zwei Pieps pro Station (eines je RFID-Scanner). Mit den nächsten Schritten fortfahren, während die Stationen hochfahren (was ein paar Minuten dauern kann).
19
+- [ ] Falls der Server auf dem Meister-PC noch nicht läuft, mit der Verknüpfung "DigiLLab Factory Starten" auf dem Desktop starten und dann auf "Server starten/neustarten" klicken.
20
+![grafik](uploads/92ac8da2a4033bec8077285472dbb0f9/grafik.png)
21
+- [ ] Auf dem Surface Hub im Browser zwei Seiten öffnen: Erstens `http://192.168.188.41:3030/dashbard.html` für das Dashboard (exakt so eingeben, insb. mit `http://`) und zweitens `https://odoo-mrp.erp.digit40.edu.sot.tum.de` für den Webshop.
22
+- [ ] Am Meister-PC auf "Odoo öffnen" klicken bzw. in Firefox das Lesezeichen "Odoo DigiLLab Factory" öffnen. Odoo öffnet sich mit einer Ansicht der aktuellen Fertigungsaufträge.
23
+- [ ] Um Fertigungsaufträge hinzuzufügen: **a) Make to stock**: Oben links "Neu", dann als Produkt "Racer" eintippen und eine der gespeicherten Varianten auswählen, und oben links "Bestätigen". **b) Make to order:** Bestellung(en) im Webshop [https://odoo-mrp.erp.digit40.edu.sot.tum.de](https://odoo-mrp.erp.digit40.edu.sot.tum.de) platzieren. Das kann man am Surface Hub im Webshop selber machen und/oder t von Schulungsteilnehmern machen lassen, indem man ihnen den Link als QR-Code gibt (liegt ausgedruckt am Meister-PC). Dann in Odoo ins "Verkauf"-Modul wechseln, dort das Angebot öffnen und "bestätigen", dann zurück ins "Fertigung"-Modul, wo nun automatisch ein entsprechender Fertigungsauftrag erzeugt worden ist. Dieser erscheint nun auch auf dem Logistik-Monitor in der Liste neuer Aufträge.
24
+- [ ] Das Lesezeichen "Steuerung" in neuem Tab öffnen und vergewissern, dass alle Stationen verbunden sind. Falls nicht, obwohl schon ein paar Minuten seit Einschalten vergangen sind, siehe hier unten "Troubleshooting".
25
+- [ ] Einarbeitungsrunde: Allen Schulungsteilnehmern die Aufgaben des Logistikers erklären sodass bekannt ist, wo Ein- und Ausgang der Stationen sind und wie die Kisten zu scannen sind. Im Zuge dieser Einarbeitung ggf. so viele Kisten bewegen wie nötig, damit in jedem Stationseingang etwas liegt. Nun an allen Stationen einen Auftrag abarbeiten lassen, damit sich die Monteure ein mal mit den Anleitungen und Montageschritten vertraut machen können. Nach Abschluss ihres ersten Auftrags sollen alle Monteure warten (noch keine neue Kiste scannen).
26
+- [ ] Schicht starten: In Odoo -> Fertigung unter "Production Cycles" (oben drittes von links) einen Produktionszyklus erstellen und benennen.
27
+- [ ] Den Production Cycle mit Klick auf den grünen Button "Start" rechts in seiner Zeile starten. Ab jetzt gehen die Zeiten in die Statistiken und die Ablaufanzeige auf dem Dashboard ein. Lesezeichen "Dashboard" öffnen um dieses anzuzeigen bzw. auf dem Surface Hub zeigen.
28
+- [ ] Am Ende der Produktion: den Production Cycle in Odoo beenden und alle Monteure ihre aktuelle Kiste vollständig bearbeiten, fertig melden und in den Stationsausgang legen lassen.
29
+
30
+
31
+| Achtung |
32
+| ------ |
33
+| Am Schulungsende müssen alle Arbeitsschritte des aktuellen Auftrags an jeder Station fertig gemeldet und die Kiste danach in den Ausgang gelegt werden; andernfalls kann die nächste Schulungsgruppe die Produktion möglicherweise nicht richtig aufnehmen. Aus Zeitgründen kann notfalls auf die tatsächliche Ausführung der Schritte verzichtet werden, aber der Klick auf "fertig" für jeden Schritt ist unbedingt nötig, damit die nächste Gruppe an den Stationen jeweils von vorne starten kann. |
34
+
35
+### Im Nachgang
36
+
37
+Fertig montierte Autos sammeln sich im Ausgangslager (=linker Logistikplatz) an. Die e-Ink-Displays der Kisten dort zeigen dementsprechend "Produktion abgeschlossen" an. Um das Eingangslager wieder aufzufüllen:
38
+- [ ] Alle(!) Autos in den fertigen Kisten wieder demontieren.
39
+- [ ] "Steuerung öffnen" (wenn der Server nicht mehr läuft, muss er hierfür gestartet werden) und "Alle fertigen Boxen zurücksetzen" anklicken. Alle Kisten, die bis dahin "Produktion abgeschlossen" angezeigt hatten, werden nun zurückgesetzt und können für neue Aufträge genutzt werden.
40
+- [ ] Alle Kisten ins Eingangslager (=rechter Logistikplatz) legen.
41
+
42
+Zuletzt den Server stoppen und den Strom an den Stationen mit der Fernbedienung, Taste A Off, abschalten. Den Meister-PC laufen lassen, damit der für Fernzugriffe verfügbar bleibt.
43
+
44
+### Troubleshooting
45
+
46
+Wenn sich eine Station nicht verbindet:
47
+1. Vergewissern, dass sie Strom hat (Fernbedienung vor die Funksteckdose der Station halten und Taste A on drücken; rote Kontrollleuchte an Funksteckdose muss leuchten).
48
+2. Vergewissern, dass der Monitor an ist.
49
+3. Ggf. den Kleincomputer dieser Station ab- und anstecken um die Station neu zu starten. (Stromkabel steckt in Funksteckdose.)
50
+
51
+
52
+Wenn der Scan einer Kiste an einem Montage-Tisch nicht wie erwartet den Montage-Schritt startet (Anleitung anzeigt):
53
+1. E-Ink Display der Kiste prüfen um sicherzugehen, dass die Kiste an diese Station gehört. Mögliche Fehlerquellen: Logistiker hat die Kiste nicht am Eingangslager gescannt, sodass sie überhaupt keinem Auftrag zugeordnet ist, oder die Kiste steht im Ein- statt Ausangslager der Station (vgl. oben "im Vorfeld")
54
+2. Ggf. Neustart der Station durch ab- und anstecken des Stromkabels des Kleincomputers (steckt in weißer Funksteckdose).
55
+3. Vergewissern, dass die Positionen aller Kisten tatsächlich den Positionen gemäß Odoo entsprechen. Insbesondere vergewissern, dass kein Auftrag den Standort "Station X Desk" anzeigt, der dort gar nicht tatsächlich in Arbeit ist. Wenn es eine Abweichung gibt, dann den Fertigungsschritt des fraglichen Fertigungsauftrag händisch in Odoo als abgeschlossen melden.
56
+
57
+## Infos für Entwickler
58
+
59
+Der zentrale Websocket Server für die Odoo Factory läuft auf dem Meister-Arbeitsplatz PC. Alle Raspis im lokalen Netz verbinden sich mit diesem über `tuedfed-dl01.fritz.box:3030` bzw. `192.168.188.41:3030`. Um die Bedienung so einfach wie möglich zu machen gibt es eine kleine graphische Anwendung (`windows.py`), mit der man den Server auf dem Meister-PC starten kann:
60
+
61
+![grafik](uploads/92ac8da2a4033bec8077285472dbb0f9/grafik.png)
62
+
63
+Der Ordner links enthält das Verzeichnis `Lokaler-Server` aus dem Repo, sowie ein virtualenv (Einrichtung siehe unten). Rechts ist eine Verknüpfung, die `Lokaler-Server\windows.py` aufruft:
64
+
65
+![grafik](uploads/b2252f7e6e4e208ab3de2cc02c820d70/grafik.png)
66
+
67
+Das Fenster im Hintergrund zeigt den Log und eventuelle Fehlermeldungen. Mit dem Fenster im Vordergrund kann man Odoo oder das Control Panel im Browser öffnen und den Server im Hintergrund starten/stoppen. Der Server wird nicht automatisch gestartet, wenn man das Fenster öffnet, das heißt man muss ihn einmal am Anfang starten. Wenn der Server und alle Raspis laufen und verbunden sind, ist die Odoo Factory einsatzbereit.
68
+
69
+Verbindungsprobleme können leider manchmal auftreten, wenn Router und Raspis falsch zueinander stehen.
70
+
71
+### Production Cycle
72
+Für die Statistiken gibt es in Odoo Produktionszyklen (Manufacturing->Production Cycles), mit denen man einen Referenzzeitraum für die Produktion vorgibt. Das Dashboard zeigt immer den aktuell laufenden Produktionszyklus, oder den als letztes beendeten, bei dem "show after finish" in Odoo gesetzt ist.
73
+
74
+### Dashboard
75
+Auf dem Surface Hub ist das Dashboard unter `tuedfed-dl01.fritz.box:3030/dashboard.html` erreichbar. Prinzipiell kann man das Dashboard auch auf anderen Geräten öffnen, es ist aber vom Layout auf das Surface Hub angepasst (evtl. hilft zoomen). Die Metriken der aktuellen Produktion werden alle 10s geupdatet, der Workorder Plan alle 20s. Die Updates werden nur gemacht, wenn das Dashboard offen ist, weil sie vom Dashboard initiiert werden.
76
+
77
+### Stationen sperren
78
+Über das Control Panel lassen sich alle Station sperren. Die Bildschirme zeigen dann nur den Namen der Station und den Verbindungsstatus an (Praktisch wird ein Overlay angezeigt, das heißt noch offene Workorder laufen weiter). Scans an den RFID Scannern haben dann keinen Effekt mehr.
79
+
80
+In der Praxis ist das auch ein praktischer Test, ob alle Station noch verbunden sind. Der Status im Control Panel updatet sich nicht sofort, sondern erst nach einem Timeout.
81
+
82
+# Einrichtung
83
+### Venv
84
+Der Server läuft mit Python, das mit dem offiziellen Installer auf dem Meister-PC installiert ist. Das Programm ist auf dem Desktop unter `DigiLLab-Factory\Lokaler-Server\` abgelegt. Das venv lässt sich mit der Power Shell einrichten mit:
85
+```powershell
86
+# Im Ordner "DigiLLab-Factory":
87
+py.exe -m venv .\venv
88
+.\venv\Scripts\pip.exe install -r .\Lokaler-Server\requirements.txt
89
+```
90
+Nur der Server selbst (`server.py`) verwendet und braucht das venv, das GUI Programm `windows.py` nicht.
91
+
92
+### Konfiguration
93
+Die Konfiguration des Server liegt in `DigiLLab-Factory\Lokaler-Server\server-config.ini` auf dem Desktop. Möchte man eigene Anleitungen den Arbeitsstationen zur Verfügung stellen, kann man die in `DigiLLab-Factory\Lokaler-Server\web` ablegen. Die URLs in der Odoo Einstellung dazu sind immer relativ zu diesem Verzeichnis. Wichtig ist, dass PDFs immer im Unterordner `pdf` und MP4 Videos im Unterordner `mp4` abgelegt werden, weil der relative einfache statische Server von socketio nur so den richtigen Content-Type gibt. Die Content-Types sind in `server.py` eingerichtet.
94
+Eine flexiblere Lösung wäre ein richtiger Webserver, der dann aber ein passenden CORS Header braucht (die erlaubte Quelle muss `tuedfed-dl01.fritz.box` sein). Sofern CORS eingerichtet ist, können in Odoo zu den Anleitungen auch vollständige URLs (http://...) eingegeben werden.
95
+
96
+### Firewall
97
+Damit man vom lokalen Netzwerk aus den Server auf Port 3030 erreichen kann, muss man in Windows eine Firewall Regel einrichten:
98
+![Firewall](uploads/1c1401b67421c46b7586affee397ab8b/Firewall.png)
... ...
\ No newline at end of file
industrie_4.0/Drucker-auf-VM-verf\303\274gbar-machen.md
... ...
@@ -0,0 +1,22 @@
1
+## Zweck
2
+
3
+Der USB-Drucker sollte sowohl vom Host-Betriebssystem als auch von der SLF-VM aus erreichbar sein, damit es egal ist, in welchem Kontext Druckbefehle gegeben werden (insb. für die Startaufträge in der papierbasierten Runde).
4
+
5
+## Gewähltes Vorgehen
6
+Damit der Drucker auch von der VM aus angesprochen werden kann, hat JS entsprechend [dieser Anleitung](https://docs.microsoft.com/en-us/troubleshoot/windows-server/remote/printer-redirection-not-work) zuerst den aktuellen Security Descriptor des Print Spoolers anzeigen lassen:
7
+
8
+```
9
+sc sdshow spooler
10
+```
11
+Der Output war genau wie in der Anleitung
12
+```
13
+D:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)
14
+```
15
+Dem war nochmal der Block `(A;;CCLCSWLOCRRC;;;AU)` hinzuzufügen, also mit folgendem Befehl zu setzen (ggf. anzupassen, wenn obiger Output anders aussieht):
16
+```
17
+sc sdset spooler D:(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)
18
+```
19
+Dieser Befehl musste als Admin ausgeführt werden, also in das Suchfenster von Windows eingegeben werden und dann die Option "Als Administrator ausführen" angeklickt werden.
20
+
21
+## Alternativen
22
+Mit einem Netzwerkdrucker sollten keine derartigen Anpassungen vonnöten sein, da die VM ja normalen Netzwerkzugriff hat. Falls USB also hartnäckig Probleme macht, sollten wir einfach ein Netzwerkkabel in den Drucker stecken.
... ...
\ No newline at end of file
industrie_4.0/Fragen-an-Odoo-Beratung.md
... ...
@@ -0,0 +1,18 @@
1
+Hier werden Fragen für die Beratung gesammelt. Alternativ kann auch einfach das Label ["Beratungsfrage"](https://gitlab.lrz.de/teachtum40/industrie4.0/-/boards?label_name[]=Beratungsfrage) bei Issues gesetzt werden, für die die Beratung herangezogen werden sollte. Die Reihenfolge der Auflistung entspricht der Priorisierung.
2
+
3
+# Prio 1) Fragen zur Benutzung von Odoo
4
+
5
+@all bitte hier eure Fragen reinschreiben
6
+- **Buchhaltungs-Modul**: Was ist zu tun, um Buchhaltung in Odoo CE zu ermöglichen? Laut Gespräch mit much.consulting am 08.12.2022 gibt es dafür ein geeignetes Modul, das von der Community gepflegt wird (Buchhaltung inkl. Personalkostenplanung, aber ohne rechtssichere Lohnabrechnung, was für unsere Zwecke ja auch völlig egal ist)
7
+- **Fertigungsstraße mit Odoo MRP Modul betreiben**: Wie gut würde sich unsere Fertigungsstraße (vier Montagestationen + Qualitätssicherung, die i.d.R. der Reihe nach durchlaufen werden) im Odoo-Fertigungsmodul abbilden lassen? Hab gesehen dass man Anleitungen bereitstellen und verschiedene "Assembly lines" definieren kann, aber wir haben ja vielmehr die Situation, dass Aufträge nicht parallel auf Stationen verteilt werden, sondern seriell durch eine Folge von Stationen abgearbeitet werden.
8
+- **Trends**: Kann Odoo Trends abbilden bzw. Forecasts ausgeben? Ist eine KI Anbindung hier möglich?
9
+
10
+
11
+# Prio 2) Fragen zur Entwicklung von Odoo
12
+
13
+- **Standardworkflow in MRP Modul, und überhaupt Dokumentation**: Die [SLF-Odoo-Schnittstelle](https://gitlab.lrz.de/teachtum40/industrie4.0/-/blob/main/Odoo-SLF-Verbindung/slf_to_odoo.py) löst je nach Fertigungsfortschritt in unserer Montagestraße Odoo-Funktionen aus, um den Durchlauf eines Fertigungsauftrags von Bestätigung bis Abschluss abzubilden. Diese Funktionen habe ich ermittelt, indem ich den Standardworkflow in Odoo durchgeklickt und dabei die Debugging-Konsole im Blick behalten habe (und dann natürlich getestet). Ist das der übliche Weg, die Funktionsweise eines Odoo-Moduls nachzuvollziehen, oder gibt es irgendwo noch eine Modul-spezifische Entwicklerdokumentation?
14
+- **Beispieldaten/Zurücksetzen auf Startzustand**: Wir wollen unsere Datenbank(en) immer wieder in einen gewissen Startzustand zurückversetzen können. Was ist grundsätzlich der stabilere Weg? Eher von Hand eine DB erstellen und als .zip ablegen, oder eher Skripte schreiben und in ein Addon-Modul packen, das unsere Daten in die DB schreibt? Wie läuft das eigentlich mit den Möbelladen-Beispieldaten?
15
+- **Custom JavaScript**: Wir haben als Beispiel für die Personalisierung in Webshops ein sehr kurzes Skript, das eine teurere Konfiguration des Autos auswählt, wenn die Seite mit einem Apple-Gerät (insb. iPhone) aufgerufen wird (#21 ). Wo würde man dies Skript innerhalb von Odoo am besten hinpacken (siehe Kommentare in der Issue)?
16
+- **Varianten-Kombinatorik**: Die Auswahlmöglichkeiten bei der Konfiguration des Autos, das der Webshop anbietet, ergeben ca. 27.000 Varianten. Via GUI kann man so viele Varianten nicht statisch in Odoo anlegen. Und wenn man doch alle 27k Varianten haben will, anstatt kleinere Variantenzahl statisch oder alle Varianten dynamisch zu generieren (Vgl. #25 und #7 )? Geht Postgres dann in die Knie, oder muss man bloß irgendwo ein Limit hochsetzen und dann ein mal ein bisschen Geduld mitbringen?
17
+- **Odoo auf Raspberry Pi**: Welche Konfiguration ist geeignet? Joachim hat aktuell Raspberry Lite 32-bit laufen. Hintergründe: much.consulting hatte erwähnt, dass man (bis zu gewisser Anzahl zeitgleicher Nutzer) mit dem Raspi zurechtkommt. Das kann nützlich sein für 1) Entwicklung ohne VM, 2) Transfer an Schulen, insb. portables Industrie-Szenario, 3) Kostenneutraler Betrieb über Projektende hinaus (ein Raspi als Odoo-Server im MWN und fertig)
18
+- **Speicherung von Bildern**: Nur so aus Neugierde: Kommen die Bilder, die man für eine Webseite und Produkte hochlädt, als Blobs in die zugehörige DB?
industrie_4.0/Logging-in-SLF-Datenbank.md
... ...
@@ -0,0 +1,24 @@
1
+# Zweck
2
+
3
+Nachvollziehbar machen, welche Handlungen in der SLF mit welchen Änderungen in der SLF-Datenbank korrespondieren. Auf Grundlage dieser Erkenntnisse wird es vielleicht möglich, weitere Kennzahlen zu generieren, die die Datenbank nicht direkt ausgibt.
4
+
5
+# Konfiguration
6
+
7
+Die Datei ```C:\Program Files\PostgreSQL\13\data\postgresql.conf``` auf der VM ist wie in [https://stackoverflow.com/questions/722221/how-to-log-postgresql-queries](https://stackoverflow.com/questions/722221/how-to-log-postgresql-queries) beschrieben verändert, außer dass
8
+```
9
+log_statement = 'mod'
10
+```
11
+gesetzt ist um das richtige Logging-Level zu erhalten.
12
+Das Log liegt in ```C:\Program Files\PostgreSQL\13\data\log\...```
13
+
14
+Um nur eine spezifische Datenbank zu loggen, kann man das log_statement oben auf `none` setzen, und stattdessen mit pgAdmin über das Query Tool (Button direkt unter "Tools" ganz oben) folgendes eingeben:
15
+
16
+```sql
17
+ALTER DATABASE slf
18
+SET log_statement = 'mod';
19
+```
20
+
21
+# PostgreSQL neustarten
22
+1. Eingabeaufforderung als Admin starten (danach suchen und dann Rechtsklick)
23
+2. `services.msc` eingeben, und dann Enter
24
+3. In der Liste `postgresql-13` suchen, und mit Rechtsklick neustarten
... ...
\ No newline at end of file
industrie_4.0/Meisterplatz-Anleitung.md
... ...
@@ -0,0 +1,4 @@
1
+- [ ] Um Fertigungsaufträge hinzuzufügen: **a) Make to stock**: Oben links "Neu", dann als Produkt "Racer" eintippen und eine der gespeicherten Varianten auswählen, und oben links "Bestätigen". **b) Make to order:** Bestellung(en) im Webshop [https://odoo-mrp.erp.digit40.edu.sot.tum.de](https://odoo-mrp.erp.digit40.edu.sot.tum.de) platzieren (das kann auch gut von Schulungsteilnehmern gemacht werden; den Link am besten als QR-Code bereitstellen). Dann in Odoo ins "Verkauf"-Modul wechseln, dort das Angebot öffnen und "bestätigen", dann zurück ins "Fertigung"-Modul, wo nun automatisch ein entsprechender Fertigungsauftrag erzeugt worden ist. Dieser erscheint nun auch auf dem Logistik-Monitor in der Liste neuer Aufträge.
2
+- [ ] Produktion: Unter "Production Cycles" (oben drittes von links) einen Produktionszyklus erstellen und benennen.
3
+- [ ] Den Production Cycle in Odoo starten. Ab jetzt gehen die Zeiten in die Statistiken und die Ablaufanzeige auf dem Dashboard ein.
4
+- [ ] Am Ende der Produktion: den Production Cycle in Odoo beenden und alle Monteure ihren aktuellen Auftrag vollständig bearbeiten und dann in den Stationsausgang legen lassen. **Achtung**: nicht einfach inmitten eines Auftrags die Schraubendreher fallen lassen und die Fabrik herunterfahren, denn dann findet sich die nächste Gruppe, die die Fertigung wieder aufnimmt, nicht zurecht.
industrie_4.0/Modellauto-Konfiguration-aus-Odoo-DB.md
... ...
@@ -0,0 +1,19 @@
1
+Die Konfiguration (Motor, Stoßdämpfer usw.) eines Fertigungsauftrags für ein Modellauto ergibt sich wie folgt:
2
+
3
+Jeder Fertigungsauftrag der Tabelle `mrp_production` hat eine `product_id` die auf `product_product` verweist, und die Tabelle `product_product` hat eine Spalte `combination_indices`, die einen String der Konfiguration enthält, z. B. `40,41,46,47,49,51,54,57,60`.
4
+
5
+Diese Indices entsprechen den IDs von
6
+```
7
+select product_template_attribute_value.id, product_attribute_value.attribute_id, product_attribute_value.name from product_template_attribute_value join product_attribute_value on product_template_attribute_value.product_attribute_value_id=product_attribute_value.id;
8
+```
9
+also zum Beispiel für den Motor
10
+
11
+| id | attribute_id | name |
12
+| ------ | ------ | ------ |
13
+| 38 | 6 | {"de_DE": "193kW", "en_US": "193kW"} |
14
+| 39 | 6 | {"de_DE": "245kW", "en_US": "245kW"} |
15
+| 40 | 6 | {"de_DE": "615kW", "en_US": "615kW"} |
16
+
17
+d. h. die 40 in obigen `combination_indices` bedeutet, dass der 615kW-Motor gewählt wurde.
18
+
19
+Mit `select id,name from product_attribute;` gibt's den Text zu obiger `attribute_id` (und es gäbe alles auf einmal, wenn man einen doppelten `join` syntaxfehlerfrei hinbekäme).
... ...
\ No newline at end of file
industrie_4.0/Odoo-Entwicklung-auf-Raspberry-Pi-4.md
... ...
@@ -0,0 +1,57 @@
1
+# Installation
2
+## a) Zum schnellen Ausprobieren
3
+
4
+Raspberry Pi OS (32-bit) auf SD-Karte schreiben. Installation gemäß [Doku für Odoo 16-Installation auf Debian/Ubuntu](https://www.odoo.com/documentation/16.0/administration/install/install.html). Erstmal Postgres:
5
+```
6
+sudo apt install postgresql
7
+```
8
+Dann das Odoo-Repository:
9
+```
10
+wget -q -O - https://nightly.odoo.com/odoo.key | sudo gpg --dearmor -o /usr/share/keyrings/odoo-archive-keyring.gpg
11
+echo 'deb [signed-by=/usr/share/keyrings/odoo-archive-keyring.gpg] https://nightly.odoo.com/16.0/nightly/deb/ ./' | sudo tee /etc/apt/sources.list.d/odoo.list
12
+sudo apt-get update && sudo apt-get install odoo
13
+```
14
+Und jetzt im Browser `localhost:8069` öffnen und loslegen.
15
+
16
+## b) Zum Entwickeln
17
+
18
+Wie in Kapitel 2 von [Odoo 15 Development Essentials](https://www.oreilly.com/library/view/odoo-15-development/9781800200067/) S. 46-50 beschrieben vorgehen, d. h. Odoo **nicht** über apt installieren, sondern git-Verzeichnis klonen und virtuelle Python-Umgebung erstellen.
19
+Ist alles installiert, startet man mit `odoo` die Instanz und kann dann im lokalen Netzwerk über `{IP des Raspi}:8069` die GUI aufrufen.
20
+
21
+## wkhtmltopdf installieren
22
+
23
+Damit PDFs, also z. B. Rechnungen, erstellt werden können, muss wkhtmltopdf installiert werden. Das ist nicht teil der Standard-Paketquellen, man muss also die [passenden präkombilierten Binaries](https://wkhtmltopdf.org/downloads.html) herunterladen. Für Raspberry Pi bedeutete das zuletzt:
24
+```
25
+wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.raspberrypi.bullseye_armhf.deb
26
+sudo apt install ./wkhtmltox_0.12.6.1-2.raspberrypi.bullseye_armhf.deb
27
+```
28
+
29
+
30
+## pgadmin zur Postgres-Entwicklung
31
+
32
+Um nicht an der Kommandozeilen-Eingabe von Funktionen in Postgres zu verzweifeln, empfiehlt sich die Verwendung von pgadmin. Auf dem Raspi selbst läuft pgadmin4 mangels arm-Unterstützung nicht, also: pgadmin4 von anderem Computer aus verwenden mit SSL-Tunneling, siehe [Postgres: lokaler und remote Zugriff](https://gitlab.lrz.de/teachtum40/industrie4.0/-/wikis/Postgres:-lokaler-und-remote-Zugriff).
33
+
34
+
35
+# Entwicklung
36
+
37
+## Häufige Befehle
38
+
39
+Python-Umgebung aktivieren:
40
+```
41
+source ~/odoo-entwicklung/py_env/bin/activate
42
+```
43
+Odoo so starten, dass bei Quellcode-Änderungen sofort neugestartet wird:
44
+```
45
+odoo --dev=reload
46
+```
47
+
48
+Odoo mit eigenem Addons-Verzeichnis starten, z. B. dasjenige für die Bücherei-App (vgl. Buch):
49
+```
50
+odoo --addons-path="~/odoo-16-playground/odoo/addons, ~/odoo-16-playground/library"
51
+```
52
+Direkt mit der Bücherei-App installiert (entsprechende .conf vorausgesetzt):
53
+```
54
+odoo -c ~/odoo-16-playground/library/library_app/library.conf -d library -i \
55
+library_app
56
+```
57
+Bei Entwicklung unterwegs am Handy-Hotspot: Beachten, dass selten die gleiche IP an den Raspi vergeben wird. Das muss bei SSL-Tunneling in pgAdmin berücksichtigt werden (vgl. Kommentare in pgAdmin auf Macbook).
... ...
\ No newline at end of file
industrie_4.0/Odoo-SLF-Schnittstelle-demonstrieren.md
... ...
@@ -0,0 +1,67 @@
1
+# Vorbereitungen
2
+
3
+## Odoo kontrollieren
4
+
5
+Auf https://erp-test.oct.re sollte Odoo unter Verwendung der Datenbank `schnittstelle-erste-iteration` erreichbar sein. Kontrolle durch Blick auf https://erp-test.oct.re/web/database/manager. (Die Datenbank ist auf `tuedfed-tat40web.srv.mwn.de` in `/etc/odoo/odoo.conf` festgelegt, und mit dieser Config startet der Service).
6
+Die DB sollte in einem Zustand sein, wo
7
+- Der Racer in der einfachsten Variante über Stückliste, Arbeitsauftrag und automatische Aufstockung verfügt
8
+- Vom Racer in der einfachsten Variante kein Exemplar vorrätig bzw. als bald vorrätig prognostiziert ist (zum Beispiel aus make-to-stock Aufträgen, die man im Fertigungsmodul erteilt hat)
9
+- Von den Einzelteilen der Stückliste genügend vorhanden ist (also nicht alles durch Rumspielen im Fertigungsmodul verbraucht)
10
+- Max Mustermann als Kunde existiert
11
+
12
+## Skripte starten
13
+
14
+Auf `tuedfed-tat40web.srv.mwn.de` die Skripte starten, und zwar am besten in zwei sichtbaren Fenstern um etwaige Fehlermeldungen sofort mitzukriegen.
15
+```
16
+python3 /home/joachim/industrie4.0/Odoo-SLF-Verbindung/slf_to_odoo.py
17
+```
18
+```
19
+python3 /home/joachim/industrie4.0/Odoo-SLF-Verbindung/odoo_to_slf.py
20
+```
21
+
22
+## SLF zurücksetzen
23
+Im Trainer Interface zurücksetzen, falls noch eine Produktion vorbereitet ist: http://10.162.111.159:8080/
24
+Dadurch wird das aktuelle Szenario beendet und mit ihm alle zwischenzeitlich über die Schnittstelle geschickten Aufträge weggeräumt
25
+
26
+## Browser-Fenster vorbereiten
27
+
28
+Entweder mit Admin-Konto alles machen, oder zwei getrennte Sessions (Inkognito-Fenster, mit dem Surface in Edge erst mal testen ob Tabs reichen) mit Max Mustermann zum Bestellen und Admin zur Weiterverarbeitung
29
+
30
+## Falls nicht vor Ort: pgAdmin für SLF-DB starten
31
+
32
+Nur nötig für virtuelle Demo, d. h. wenn man nicht vor Ort die Kisten durchschieben kann um den Fertigungsstatus zu verändern. Auf Workstation (Host, nicht VM) mit Benutzer `DigiLLab` pgAdmin öffnen.
33
+
34
+# Durchführen
35
+
36
+## SLF vorbereiten und sichtbar machen
37
+
38
+- Im Trainer Interface Produktion vorbereiten: http://10.162.111.159:8080/
39
+- Dashboard öffnen: http://10.162.111.159:3000/d/zaRwSgS7k/lab-main-dashboard?orgId=1&refresh=1s&kiosk&var-plant_id=3 und dort zur Auftragsliste scrollen
40
+
41
+
42
+## a) Make to Stock
43
+
44
+1. Odoo öffnen https://erp-test.oct.re (damit die hübsche Webseite zumindest kurz sichtbar ist)
45
+2. Modul "Manufacturing" öffnen
46
+3. "Create"
47
+4. Bei "Product" "Racer" eingeben und ersten Vorschlag (ist die einfachste Produktvariante) anklicken. Der Name der zugehörigen Stückliste erscheint in "Bill of Material", und diese legt auch ein Work Order fest, ohne das der ganze Workflow nicht geht (Skript versucht, Work Order zu starten; ohne BOM/Work Order kann kein Materialverbrauch berechnet werden und dann müsste man Dialoge durchklicken, was nicht per API geht)
48
+5. "Confirm"
49
+6. Im SLF-Dashboard zeigen, dass der entsprechende neue Fertigungsauftrag angelegt worden ist mit Status "Ready" (und Auftragsnummer `PO-IND-XXXX` für SQL-Update notieren)
50
+7. Falls vor Ort: Produktion starten und Auftrag durchs Eingangslager ziehen. Falls remote oder wenig Zeit: In pgadmin den SLF-Status eins weiter setzen durch `update production_order set state='Running' where name='PO-IND-XXXX';`
51
+8. Im SLF-Dashboard auf neuen "Status" hinweisen und Seite in Odoo neu laden und auf Zustand "In Progress" hinweisen; ggf. zusätzlich Reiter "Work Orders" öffnen
52
+9. Falls vor Ort: Produktion durch alle Stationen ziehen bis fertig. Falls remote oder wenig Zeit: In pgadmin den SLF-Status eins weiter setzen durch `update production_order set state='Completed' where name='PO-IND-XXXX';`
53
+10. Im SLF-Dashboard auf neuen "Status" hinweisen und Seite in Odoo neu laden und auf Zustand "To Close" hinweisen; runterscrollen um die Einträge von SLF-Odoo-Interface im Log anzuzeigen.
54
+11. Wenn unvermeidbar: Auf "Mark as done" und mit der Fehlermeldung leben
55
+
56
+## b) Make to Order
57
+
58
+1. Kundensicht: Odoo öffnen https://erp-test.oct.re
59
+1. Bestellung aufgeben für billigsten Racer (gemäß Default, also jede Auswahl ganz links lassen)
60
+1. Mitarbeitersicht: Odoo mit Admin-Konto öffnen
61
+1. Den gerade erteilten Auftrag von Max Mustermann öffnen, vergewissern dass prognostizierte verfügbare Menge null ist (rotes Symbol) und bestätigen
62
+2. Modul "Manufacturing" öffnen, dort zeigen unter welchem Namen `WH/MO/...` der zugehörige Fertigungsauftrag angelegt wurde, und hinweisen auf die Quelle "Replenishment Report"
63
+6. Im SLF-Dashboard zeigen, dass der entsprechende neue Fertigungsauftrag angelegt worden ist mit Status "Ready".
64
+7. Falls vor Ort: Produktion starten und Auftrag durchs Eingangslager ziehen. Falls remote oder wenig Zeit: In pgadmin den SLF-Status eins weiter setzen durch `update production_order set state='Running' where name='PO-IND-XXXX';`
65
+8. Im SLF-Dashboard auf neuen "Status" hinweisen ("Paused) und Seite in Odoo neu laden und auf Zustand "In Progress" hinweisen; ggf. zusätzlich Reiter "Work Orders" öffnen
66
+9. Falls vor Ort: Produktion durch alle Stationen ziehen bis fertig (dabei zeigen, dass die richtige Konfiguration übermittelt wurde). Falls remote oder wenig Zeit: In pgadmin den SLF-Status eins weiter setzen durch `update production_order set state='Completed' where name='PO-IND-XXXX';` (die Richtigkeit der Konfiguration kann im MES gezeigt werden)
67
+10. Im SLF-Dashboard auf neuen "Status" hinweisen und in Odoo Seite des MO öffnen bzw. Seite des MO neu laden (Obacht: nicht Listenansicht neu laden, dann verschwindet das wegen "To Do"-Filter) und auf Zustand "Done" hinweisen; runterscrollen um die Einträge von SLF-Odoo-Interface im Log anzuzeigen.
... ...
\ No newline at end of file
industrie_4.0/Odoo:-Accounting-Modul-installieren.md
... ...
@@ -0,0 +1,15 @@
1
+# Kurzfassung
2
+
3
+Das Standard-Accounting-Modul der Community Edition hat einen zu kleinen Funktionsumfang. Odoo selbst will damit einen Anreiz zum Kauf der Enterprise Edition setzen. Es gibt aber ein von der Community geschriebenes Accounting-Modul für Odoo CE mit ausreichendem Funktionsumfang.
4
+
5
+# Installation
6
+
7
+Ausgangspunkt: https://apps.odoo.com/apps/modules/16.0/om_account_accountant/
8
+Damit das Modul richtig geladen wird mussten (Stand August 2023) die heruntergeladenen Module (es handelt sich um ein ganzes Rudel, von denen das Hauptmodul abhängt) so in die Verzeichnis-Struktur von Odoo bewegt werden, dass diese Addons sowie das Hauptmodul tatsächlich von Odoo gefunden werden.
9
+
10
+1. https://apps.odoo.com/apps/modules/16.0/om_account_accountant/ öffnen
11
+2. "Download for v 16.0" anklicken
12
+3. Das heruntergeladene zip-Verzeichnis entpacken
13
+4. Alle Ordner innerhalb des Verzeichnisses (also "accounting_pdf_reports" bis "om_recurring_payments") in ein Addons-Verzeichnis dieser Odoo-Instanz verschieben (die Verzeichnisse sind in der `odoo.conf` angegeben). Alternative: Das entpackte zip-Verzeichnis als weiteren Addons-Path in der `odoo.conf` angeben bzw. in Entwicklungs-Umgebung als Kommandozeilen-Parameter mitgeben. Jedenfalls müssen die einzelnen Module direkte Kinder eines Addons-Verzeichnisses sein, und nicht in einem Ordner innerhalb eines Addons-Verzeichnisses rumliegen. Falls man sich in einer Entwicklungs-Umgebung nicht sicher ist, wo Odoo nach Addons guckt: `odoo --stop` startet und stoppt Odoo, wobei es ein mal die aktuellen Einstellungen ausgibt.
14
+5. In Odoo: Entwickler-Modus aktivieren (z. B. ?debug=1 in die URL hauen) und dann erscheint im "Apps"-Menü der Punkt "App-Liste aktualisieren". Den anklicken.
15
+6. Nun ist das Modul "om_account_accountant" auffindbar. Aktivieren!
... ...
\ No newline at end of file
industrie_4.0/Odoo:-Installation,-Einrichtung,-Subdomains-hinzuf\303\274gen.md
... ...
@@ -0,0 +1,117 @@
1
+# Installation
2
+Auf unserem Server `tuedfed-tat40web.srv.mwn.de` wurde Odoo nach der [offiziellen Anleitung](https://www.odoo.com/documentation/16.0/administration/install/install.html) von Odoo unter Ubuntu installiert.
3
+
4
+Odoo verwendet als Datenbank Postgres. Das muss also zuerst installiert werden:
5
+```bash
6
+sudo apt install postgresql -y
7
+```
8
+
9
+Odoo richtet bei der Installation über die Paketquellen (siehe unten) automatisch einen Benutzer `odoo` in Linux und Postgres ein. Für Zugriff auf Postgres siehe auch die Seite zu [Postgres Zugriff](https://gitlab.lrz.de/teachtum40/industrie4.0/-/wikis/Postgres:-lokaler-und-remote-Zugriff).
10
+
11
+Eine weitere Abhängigkeit, die man von Hand vorher installieren muss ist `wkhtmltopdf`. Nachdem die Installation über die Standard Ubuntu Paketquellen nicht funktioniert hat, wurde es manuell installiert.
12
+```bash
13
+wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
14
+apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb
15
+# Test:
16
+#wkhtmltopdf
17
+```
18
+
19
+Odoo selbst ist nicht Teil von den Ubuntu Paketquellen. Daher muss man es zuerst als Repo Quelle hinzufügen und kann es dann aber gewohnt mit apt installieren.
20
+```bash
21
+# Odoo hat ein eigenes Paket Repo. Dazu muss man den deren Key als vertrauenswürdig hinzufügen
22
+wget -q -O - https://nightly.odoo.com/odoo.key | sudo gpg --dearmor -o /usr/share/keyrings/odoo-archive-keyring.gpg
23
+# Dann das Repo hinzufügen
24
+echo 'deb [signed-by=/usr/share/keyrings/odoo-archive-keyring.gpg] https://nightly.odoo.com/16.0/nightly/deb/ ./' | sudo tee /etc/apt/sources.list.d/odoo.list
25
+# Und abschließend Paketlisten aktualisieren und Odoo installieren
26
+sudo apt-get update && sudo apt-get install odoo
27
+```
28
+
29
+# Konfiguration
30
+Details zur Standard-Konfiguration von Odoo finden sich in der [Dokumentation von Odoo](https://www.odoo.com/documentation/16.0/administration/install/deploy.html). Unsere Installation unterscheidet sich dahingehend von Standard-Installationen, dass wir verschiedene Datenbanken über verschiedene Subdomains erreichbar machen, damit verschiedene Nutzer(-gruppen) unabhängig voneinander arbeiten können. Folgende Änderungen gegenüber den Standards sind dafür nötig:
31
+- *dbfilter* ist eine Funktion, wie eine Odoo Instanz mit getrennten Datenbanken von mehrere "Kunden" unabhängig verwendet werden kann. Der aktuelle Filter `^%d.*$` bewirkt, dass über eine gegebene Subdomain nur Datenbanken erreichbar sind, deren Name mit dem Namen der Subdomain beginnt (oder einfach übereinstimmt). Beispielsweise sind die Datenbanken `startzustand-ohne-webshop` und `startzustand-mit-webshop` über [startzustand.usw](https://starzustand.erp.digit40.edu.sot.tum.de) erreichbar und `dobhan` über [dobhan.usw](https://dobhan.erp.digit40.edu.sot.tum.de).
32
+- *db_maxconn* ist ein Parameter, mit dem die Anzahl der Verbindungen von Odoo zu Postgres begrenzt werden kann. Bei einem Multi-Datenbank-Setup muss man diesen Parameter so einstellen, dass die Parameter `db_maxconn`, `workers` und `max_cron_threads` aus `odoo.conf` und der Parameter `max_connections` aus `postgresql.conf` folgende Ungleichung erfüllen: `(1 + workers + max_cron_threads) * db_maxconn < max_connections` ([Quelle](https://odoo-development.readthedocs.io/en/latest/admin/db_maxconn.html)).
33
+- *PostgreSQL* kann man weitestgehend so lassen wie es ist, nachdem Odoo und Postgres auf dem gleichen Server laufen. Wenn sie auf getrennten Maschinen laufen müsste man eine Verbindung über einen SSH-Tunnel herstellen oder externe IPs erlauben. Um obige Ungleichung zur Vermeidung zu vieler Clients zu erfüllen, muss der Wert von `max_connections` in `/etc/postgresql/12/main/postgresql.conf` entsprechend gewählt werden. In unserem Fall ist `max_connections = 300` statt der ursprünglichen 100 gesetzt, sodass noch etwas Puffer oberhalb der (1+6+1)*32=256 Clients vorhanden ist, die Odoo maximal in Anspruch nimmt.
34
+
35
+Im Fall unserer Installation findet sich die Hauptkonfiguration von Odoo in `/etc/odoo/odoo.conf` statt `/etc/odoo.conf`, wie es in der Dokumentation steht. Die aktuelle Config ist relativ kurz (falls sich nicht geändert hat):
36
+```
37
+; See https://www.odoo.com/documentation/16.0/administration/install/deploy.html
38
+
39
+[options]
40
+; This is the password that allows database operations:
41
+admin_passwd = ...
42
+db_host = False
43
+db_port = False
44
+db_user = odoo
45
+db_password = False
46
+dbfilter = ^%d.*$
47
+addons_path = /usr/lib/python3/dist-packages/odoo/addons,/opt/odoo-addons,/var/sftp/andre_schulz_addons,/home/joachim/indust>
48
+default_productivity_apps = True
49
+
50
+; Proxy mode for Nginx
51
+proxy_mode = True
52
+xmlrpc_interface = 127.0.0.1
53
+netrpc_interface = 127.0.0.1
54
+
55
+; Performance settings
56
+limit_memory_hard = 1677721600
57
+limit_memory_soft = 629145600
58
+limit_request = 8192
59
+limit_time_cpu = 450
60
+limit_time_real = 900
61
+max_cron_threads = 1
62
+workers = 6
63
+db_maxconn = 32
64
+```
65
+
66
+Ein zufälliges 16 stelliges Passwort lässt sich mit Linux Befehl `< /dev/urandom tr -dc A-Za-z0-9 | head -c${1:-16};echo;` generieren.
67
+
68
+
69
+# Nginx
70
+Für HTTPS läuft Odoo hinter einem Nginx Proxy, der in `/etc/nginx/sites-enabled/odoo.conf` konfiguriert ist.
71
+Das Template dazu steht auch in der oben verlinkten Dokumentation. Die Subdomains kommen jeweils in die `server`-Blöcke, d. h.
72
+```
73
+server {
74
+ listen 80;
75
+ listen [::]:80;
76
+ server_name dobhan.erp.digit40.edu.sot.tum.de;
77
+ server_name repoli.erp.digit40.edu.sot.tum.de;
78
+ ...
79
+ rewrite ^(.*) https://$host$1 permanent;
80
+}
81
+
82
+server {
83
+ listen 443 ssl;
84
+ listen [::]:443 ssl;
85
+ server_name dobhan.erp.digit40.edu.sot.tum.de;
86
+ server_name repoli.erp.digit40.edu.sot.tum.de;
87
+ ...
88
+
89
+```
90
+# Subdomain hinzufügen
91
+
92
+Um eine neue Subdomain von Hand hinzuzufügen:
93
+```
94
+sudo nano /etc/nginx/sites-enabled/odoo.conf # An beiden Stellen wo "server_name" vorkommt eine neue Zeile hinzufügen
95
+sudo certbot --expand -d neueSubdomain.erp.digit40.edu.sot.tum.de -d dobhan.erp.digit40.edu.sot.tum.de ... # Hier alle Domains auflisten (bei der Frage zum redirect die "1: no redirect" auswählen)
96
+sudo systemctl restart nginx
97
+```
98
+
99
+Dann kann man unter der neuen Subdomain in Odoo eine neue Datenbank einrichten. Wir starten derzeit üblicherweise mit einer Kopie [derjenigen Datenbank](https://erp-test.oct.re/web/database/manager), an der der Lehrstuhl WiPäd rumspielt. Das geht bequem über den Endpunkt /web/database/manager, also erst auf https://quelle.erp.digit40.edu.sot.tum.de/web/database/manager ein Backup erstellen (Master-Passwort siehe oben `odoo.conf`) und dieses zip-Archiv dann via "restore" in https://ziel.erp.digit40.edu.sot.tum.de/web/database/manager hochladen (dabei "this database is a copy" wählen).
100
+
101
+Eine Skripting-Lösung ist in Arbeit (#39), wird aber gerade durch den Domain-Umzug von erp-test.oct.re zu erp.digit40.edu.sot.tum.de gebremst. Der nervigste Schritt in Handarbeit, nämlich der Certbot-Aufruf mit `-d subdomain.erp.digit40.edu.sot.tum.de` für jede Subdomain, lässt sich mit
102
+```
103
+DOMAINS=$(grep -E 'server_name' /etc/nginx/sites-enabled/odoo.conf | sort | uniq -d | sed 's/server_name //' | sed 's/;//')
104
+CERTBOTPARAM=$(echo $DOMAINS | sed 's/ / -d /g')
105
+sudo certbot --expand --no-redirect -d $CERTBOTPARAM
106
+```
107
+erledigen.
108
+
109
+# Update
110
+Updates (zumindest innerhalb einer Version, z.B. Version 16) gehen einfach mit `apt update && apt upgrade`. Upgrades (z.B. 16->17, sobald verfügbar) sind noch nicht getestet.
111
+Falls es nach dem Update zu Fehlermeldungen kommt, die sowas wie `web.assets_backend.min.js` enthalten, hilft es vermutlich [Asset Bundles](https://www.odoo.com/documentation/16.0/developer/reference/frontend/assets.html) neu zu generieren. Dazu öffnet man die Instanz mit `?debug=assets`, und klickt dann oben rechts auf das "Bug" Symbol und dort auf "Regenerate Assets Bundles":
112
+
113
+![image](uploads/5462160aebd3cb1d55b355c407353fdf/image.png)
114
+
115
+# SFTP-Zugriff für André Schulz
116
+
117
+Solange keine Containerisierung umgesetzt ist, brauchen fortgeschrittene Benutzer wie André Schulz (Masterand WiPäd), die eigene Addons schreiben, eine Möglichkeit, ihren Code auf den Server zu bringen. Provisorisch ist das entsprechend https://www.digitalocean.com/community/tutorials/how-to-enable-sftp-without-shell-access-on-ubuntu-20-04 mit einem Benutzer `andresftp` gelöst, der nur per SFTP und nur auf den Ordner `/var/sftp/andre_schulz_addons` zugreifen kann. Letzterer ist in `/etc/odoo/odoo.conf` als Addons-Pfad hinzugefügt, sodass André (und jeder andere der neugierig ist) die dortigen Addons installieren kann.
... ...
\ No newline at end of file
industrie_4.0/Odoo:-MRP-Einrichtung.md
... ...
@@ -0,0 +1,116 @@
1
+Diese Anleitung beschreibt, wie man Odoo für die Fertigung im Industrie Space einrichtet. Die ersten Schritte beziehen sich auf Odoo noch ohne das Addon für die Fertigung. Erst wenn alles in Odoo eingerichtet ist, kommt das Addon dran, damit klar ist, was vom Addon hinzugefügt wurde.
2
+
3
+Die Anleitung bezieht sich auf die Interfacesprache Englisch, weil im Internet mehr Dokumentation zur englischen Version verfügbar ist.
4
+
5
+# Odoo Einrichtung
6
+
7
+## Erster Schritte: Module aktivieren
8
+
9
+1. Apps -\> Manufacturing -\> Activate
10
+2. Apps -\> Sales -\> Activate
11
+3. Apps -\> Filter: Installed ... und dann unnötige deinstallieren (gebraucht wird: Sales, Inventory und Manufacturing)
12
+4. Optional:\
13
+ Settings -\> Activate the developer mode\
14
+ Settings -\> Users (oben) -\> ..user auswählen -\> Preferences -\> Home Action auf "Manufacturing Orders" (muss man etwas ausprobieren welches der Möglichkeiten das ist, das funktioniert).\
15
+ Auf diese Art zeigt Odoo standardmäßig die Fertigungsaufträge anstelle von "Discuss" an.
16
+
17
+## Inventory
18
+
19
+- Settings -\> Inventory ... und dann aktivieren:
20
+ - Products -\> Variants
21
+ - Warehouse -\> Storage Locations
22
+ - Warehouse -\> Multi-Step Routes
23
+ - Save
24
+- Inventory -\> Configuration -\> Locations
25
+ - WH/Stock z.B. in WH/Lager umbenennen, damit es auf den Logistik Bildschirmen auch als "Lager" steht
26
+ - Neu hinzufügen: WH/Station A IN, WH/Station A DESK, WH/Station A OUT, ... (Es reicht Location Name und Parent location (WH) auszufüllen, der Rest kann so bleiben)
27
+ - Hinweis: Unter Configuration -\> Warehouses -\> Warehouse auswählen -\> Technical Information kann man einstellen, was das Standard Lager ist (Location Stock). Das wird vom MRP Modul dann auch als Startort für neue Aufträge verwendet
28
+
29
+## Produkte
30
+
31
+- Inventory -\> Configuration -\> Attributes:
32
+ - Neue Attribute einrichten:
33
+ - Motor (193 kW, 245 kW, 615 kW)
34
+ - Hülle (keine, blau, schwarz)
35
+ - Batterie (keine, 2000 mAh, 3000 mAh)
36
+ - Vorderrad links (schwarz, weiß, blau)
37
+ - Vorderrad rechts (schwarz, weiß, blau)
38
+ - Hinterrad links (schwarz, weiß, blau)
39
+ - Hinterrad rechts (schwarz, weiß, blau)
40
+ - Stoßdämpfer vorne (innen, außen)
41
+ - Stoßdämpfer hinten (innen, außen)
42
+ - Heckspoiler (keiner, blau, schwarz)
43
+ - Display Type: Radio für alles außer die vier Räder, Hülle und Heckspoiler, dort Color
44
+ - Variants Creation Mode: dynamically _\<-- hier stattdessen static?_
45
+- Inventory -\> Products -\> Products -\> New:
46
+ - Racer:
47
+ - Can be Sold: aktiviert
48
+ - Can be Purchased: deaktiviert
49
+ - Sales Price: zB 150€
50
+ - Attributes & Variants: Alle vorher erstellten Attribute und alle Werte dazu eingeben
51
+ - Inventory -\> Routes -\> Manufacture: aktivieren
52
+ - Optional: Bild einrichten
53
+ - Save
54
+ - Komponenten auch jeweils als Produkte hinzufügen, aber Can be Sold deaktiviert, und Can be Purchased aktiviert
55
+ - 193 kW Motor
56
+ - 245 kW Motor
57
+ - 615 kW Motor
58
+ - 2000 mAh Batterie
59
+ - 3000 mAh Batterie
60
+ - Hinterrad blau
61
+ - Hinterrad schwarz
62
+ - Hinterrad weiß
63
+ - Vorderrad blau
64
+ - Vorderrad schwarz
65
+ - Vorderrad weiß
66
+ - Hülle blau
67
+ - Hülle schwarz
68
+ - Heckspoiler blau
69
+ - Heckspoiler schwarz
70
+ - Je Komponente:
71
+ - Nach dem Speichern: Update Quantity -\> New
72
+ - Counted Quantity eingeben: 100.000 (solange der Materialbestand nicht Schulungsthema ist)
73
+ - Apply
74
+
75
+## Manufacturing
76
+
77
+- Manufacturing -\> Configuration -\> Settings:
78
+ - Work Orders und dann auch Work Order Dependencies aktivieren
79
+- Arbeitszeiten einrichten (Workorders können nicht außerhalb der Arbeitszeiten geplant werden. Die Arbeitszeiten werden aber nicht außerhalb von Odoo angezeigt, daher kann man die einfach auf 24/7 einrichten und hat keine unerwarteten Effekte):
80
+ - Settings -\> Activate the developer mode
81
+ - Settings -\> Technical -\> Working Times (ganz unten)
82
+ - New, und einrichten wie dargestellt: ![image](uploads/4ba6bf1e10c6f77d28056d836dfd364f/image.png)
83
+- Manufacturing -\> Configuration -\> Work Centers:
84
+ - Station A-D einrichten (Es reicht den Namen im Feld "Work Center Name" einzugeben und die Arbeitszeiten auf 24/7 zu stellen)
85
+- Manufacturing -\> Products -\> Bills of Materials -\> New:
86
+ - Product: Racer
87
+ - Miscellaneous: Operation Dependencies? aktivieren
88
+ - _Save_
89
+ - Operations:
90
+ - "Ein-/Aus Schalter befestigen" (Work Center: Station A)
91
+ - "Motor einbauen" (Work Center: Station A)
92
+ - "Hinterräder befestigen" (Work Center: Station B)
93
+ - "Vorderräder befestigen" (Work Center: Station C)
94
+ - "Motor und Batterie anschließen" (Work Center: Station D)
95
+ - "Heckspoiler und Hülle einbauen" (Work Center: Station D)
96
+ - _Bei allen außer dem ersten: Jeweils Blocked By das vorherige auswählen_
97
+ - Components: Alle oben erstellten Komponenten hinzufügen
98
+ - Die Vorder-/Hinterräder jeweils zwei mal (li/re). Falls li/re nicht unterschiedlich konfigurierbar sind stattdessen die Quantity auf 2
99
+ - Apply on Variants, Consumed in Operation aktivieren: ![1045313ec9ba4c5d8bd1b03619fb05f8](uploads/f0b5df08601037b3ecb266e8c9e0d71c/1045313ec9ba4c5d8bd1b03619fb05f8.png)
100
+ - Jeweils passend zuweisen: ![545851678a4947ff874d74cac0249e1a](uploads/86c636b34ae5bff823c03f3a2c205f0d/545851678a4947ff874d74cac0249e1a.png)
101
+
102
+# Addon Einrichtung
103
+
104
+- Installation: Apps öffnen und oben rechts den Filter für "Apps" entfernen. Das Plugin findet sich in der Kategorie "Manufacturing"
105
+- Manufacturing -\> Configuration -\> Work Centers:
106
+ - Je Station: *Input Location* und *Output Location* eintragen (Bei Station A z.B. "WH/Station A IN" und "WH/Station A OUT")
107
+- Manufacturing -\> Configuration -\> Operations:
108
+ - Über das neue Feld "Display attributes" lassen sich die Attribute auswählen, die zu diesem Arbeitsschritt auf den Stationsmonitoren angezeigt werden sollen (z.B. welcher Motor eingebaut werden soll beim zugehörigen Arbeitsschritt)
109
+ - Bei Worksheet gibt es die Optionen "URL (PDF/MP4/...)" und "URL (Website)". Der Unterschied ist nicht groß, nur dass bei ersterem noch URL-Parameter angehängt werden, damit PDFs ohne Toolbar etc. angezeigt werden (ursprünglich wurde ersteres als `<embed>` und zweiteres als `<iframe>` eingebunden, aber am Ende war es einfacher den URL immer als `<iframe>` einzubinden).
110
+ - Im Feld URL kann man relative URLs zum Verzeichnis `web` im lokalen Server (Meister-PC) angeben, z.B. `pdf/Station-A.pdf` bzw. `station-a.html` (Falls HTML Seiten in einem Unterordner liegen, sollten sie Dateien besser mit einem Slash am Anfang einbinden, z.B. `/mp4/video.mp4`). Absolute URLs sind auch möglich, allerdings müssen diese dann CORS für `tuedfed-dl01.fritz.box` erlauben.
111
+
112
+Nicht für die Einrichtung relevant, aber auch vom Plugin hinzugefügt werden:
113
+- Bei Manufacturing Orders die Felder "RFID" (read-only) und "Current location". Außerdem gibt es noch das zusätzliche Template "Production Order mit Konfiguration" bei "Print" für den Papierdurchlauf.
114
+- Bei Work Orders der Zustand "Waiting for transfer", wenn der vorige WO abgeschlossen ist, aber die aktuelle Position des MO noch nicht da ist, wo die Station des neuen WO die "Input location" hat. Work Orders können zu Demozwecken aber den Transfer zur "IN" location überspringen und direkt an der Station gescannt und gestartet werden.
115
+- Production Cycles (oben im Menü): Zur Erfassung von Statistiken braucht es einen Referenzzeitraum, den man mit Produktionszyklen festlegen kann. Es kann immer nur maximal ein Produktionszyklen gleichzeitig laufen.
116
+- Ein verstecktes Detail ist noch der Blockiergrund "Break"/Pause, wenn man einen Work Order (und damit für Odoo die ganze Station) blockiert. Das passiert im Hintergrund, wenn man bei einer Station auf "Pause" klickt, um die Berechnung der Availability zuverlässiger zu machen.
... ...
\ No newline at end of file
industrie_4.0/Odoo:-Workflow-von-Webshop-Bestellung-zu-Fertigungsauftrag.md
... ...
@@ -0,0 +1,27 @@
1
+## Kurzfassung
2
+
3
+Eine Bestellung des Modellautos im Webshop soll zu einem Fertigungs-Auftrag innerhalb von Odoo führen.
4
+
5
+## Einrichtung
6
+
7
+Der Racer muss mit der Produktart "Lagerfähiges Produkt" angelegt werden, und "Fertigung" muss als "Route" zu seiner Beschaffung ausgewählt worden sein. Das Addon-Modul `tum_product_variant_automation` ([Quellcode](https://gitlab.lrz.de/teachtum40/industrie4.0/-/tree/main/tum_odoo_addons/tum_product_variant_automation?ref_type=heads)) muss installiert sein. Das ist Stand 26.10.2023 in der DB `odoo-mrp` geschehen, um den Workflow von der Bestellung bis zur Fertigung im DigiLLab demonstrieren zu können.
8
+Im "Verkauf"-Modul muss der Filter "Meine Angebote" entfernt worden sein (s.u.).
9
+
10
+## Nutzung
11
+
12
+Der Workflow von Bestellung zu Fertigungsauftrag geht nun so:
13
+1. Jemand bestellt im Webshop einen Racer.
14
+2. Im "Verkauf"-Modul von Odoo erscheint nun diese Bestellung.
15
+3. Im "Fertigung"-Modul von Odoo ist nun automatisch ein Fertigungsauftrag für diese Variante angelegt worden.
16
+
17
+### "My Quotations"-Filter deaktivieren
18
+
19
+Damit man alle Aufträge - einschließlich der bisher keinem Mitarbeiter zugewiesenen - sieht, muss der "My Quotations"-Filter weg. Der ist derzeit wie folgt deaktiviert (ob das der sinnvolle Weg ist, bleibt zu klären): Im Developer-Modus auf der Startseite des Sales-Modul das Debug-Menü -> Edit Action und dann unter Filters -> Context Value den Eintrag von
20
+```
21
+{'search_default_my_quotation': 1}
22
+```
23
+zu
24
+```
25
+{'search_default_my_quotation': 0}
26
+```
27
+abgeändert.
... ...
\ No newline at end of file
industrie_4.0/Postgres-Notify,-Python-Listen.md
... ...
@@ -0,0 +1,75 @@
1
+## Kurzfassung
2
+
3
+Um Änderungen in einer Postgres-DB ein externes Skript auslösen zu lassen, kann man den `trigger`-Mechanismus sowie `notify` in Postgres nutzen und ein externes Skript ein entsprechendes `listen` auf der selben Datenbank durchführen lassen.
4
+Damit kann man z. B. bewerkstelligen, dass ein neuer Fertigungsauftrag aus Odoo einen `curl` an den SLF-Configurator auslöst.
5
+
6
+
7
+## Postgres: notify mit trigger auslösen
8
+
9
+### a) von Odoo an SLF
10
+
11
+Beispiel: Um bei Einfügung eines neuen Fertigungsauftrags in die Tabelle `mrp_production` ein `notify` an den Kanal `joachim_production_insert` auszulösen, muss zuerst eine Funktion definiert werden, die einen `trigger` als Rückgabewert hat und die das `notify` aufruft:
12
+```
13
+create or replace function joachim_production_insert() returns trigger as $joachim_production_insert_trigger$
14
+begin
15
+ perform pg_notify('joachim_production_insert',row_to_json(NEW)::text);
16
+ return new;
17
+end;
18
+$joachim_production_insert_trigger$ language plpgsql;
19
+```
20
+Jetzt muss noch festgelegt werden, dass ein `insert` in diese Tabelle obige Funktion triggert:
21
+```
22
+create trigger joachim_production_insert_trigger after insert on mrp_production
23
+for each row execute function joachim_production_insert();
24
+```
25
+Bemerkungen:
26
+- Die Namen von Kanal, Funktion und Trigger sind logisch unabhängig; hier sind sie nur gleich bzw. ähnlich um einigermaßen selbsterklärend zu sein wenn man aus anderem Kontext darüber stolpert
27
+- Für mehrzeilige SQL-Eingabe kann man zum Beispiel pgadmin nutzen. (Aber nicht versuchen, die Trigger mit den dafür vorgesehenen Dialogen in pgadmin zu definieren; da habe ich mich im Kreis gedreht)
28
+- `notify` lässt standardmäßig eine Payload von bis zu 8000 Byte Länge zu. Wenn nicht sicher ist dass man damit hinkommt, dann bloß Primärschlüssel übergeben und das Python-Skript die Daten aus der Tabelle lesen lassen statt via notify-Payload zu schicken. Oder neue Zeile in dedizierte Tabelle kopieren, die dem Python-Skript als abzuarbeitende Queue dient.
29
+
30
+### b) von SLF an Odoo
31
+
32
+In "SLF"-DB auf Workstation (Achtung: Posgres läuft auf Host, nicht auf VM, und zwar mit Benutzer `DigiLLab`):
33
+```
34
+creat function notify_update_for_odoo() returns trigger as $production_order_update_trigger$
35
+begin
36
+ perform pg_notify('update_for_odoo',row_to_json(NEW)::text);
37
+ return new;
38
+end;
39
+$production_order_update_trigger$ language plpgsql;
40
+```
41
+```
42
+create trigger production_order_update_trigger after update of state on production_order
43
+for each row execute function notify_update_for_odoo();
44
+````
45
+
46
+
47
+## Python: mit listen auf notify reagieren
48
+
49
+Um nun mit einem Python-Skript auf ein `notify` im fraglichen Kanal zu reagieren, sollte zunächst ein dedizierter Benutzer dafür angelegt werden (zumindest ging es mit dem einzigen Admin erstmal nicht).
50
+```
51
+import asyncio
52
+import psycopg2
53
+
54
+conn = psycopg2.connect(host="localhost",dbname="my_first_database",user="python_test",password="1234")
55
+conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
56
+
57
+cursor = conn.cursor()
58
+cursor.execute('LISTEN joachim_production_trigger')
59
+
60
+def handle_notify():
61
+ conn.poll()
62
+ for notify in conn.notifies:
63
+ print(notify.payload)
64
+ conn.notifies.clear()
65
+
66
+
67
+loop = asyncio.get_event_loop()
68
+loop.add_reader(conn, handle_notify)
69
+loop.run_forever()
70
+```
71
+Für eine Lösung ohne `asyncio` siehe [hier](https://www.depesz.com/2012/06/13/how-to-send-mail-from-database/). Das `ISOLATION_LEVEL_AUTOCOMMIT` ist nötig, damit jede Datenbankanfrage durch psycopg2 automatisch committed wird anstatt auf einen commit zu warten (gemäß irgendeinem in diesem Punkt nicht besonders sinnvollen Standard; finde die Diskussion auf Stackexchange gerade nicht wieder).
72
+
73
+## Auf Workstation (SLF-VM auf Workstation)
74
+
75
+Lieber Powershell als Powershell ISE, denn erstere macht den `print` wie man ihn von Unix kennt einfach auf die Konsole selbst. Mit Powershell ISE landet diese Ausgabe irgendwo anders.
... ...
\ No newline at end of file
industrie_4.0/Postgres-SLF:-Remote-Zugriff.md
... ...
@@ -0,0 +1,38 @@
1
+Die SLF Postgres Datenbank kann im MWN über `10.162.111.159` Port `5432` mit Passwort geöffnet werden. Zur Sicherheit ist allerdings nur eine Verbindung über SSL möglich.
2
+
3
+# Einrichtung
4
+SSL Support auf dem Server ist nach der [offiziellen Anleitung](https://www.postgresql.org/docs/13/ssl-tcp.html) (Siehe "Basic Setup" und "Creating Certificates") eingerichtet. Dazu kommentiert man in `C:\Program Files\PostgreSQL\13\data\postgresql.conf` in der VM die Zeile `ssl = on` aus (Siehe [Dokumentation der Konfigurationsdatei](https://www.postgresql.org/docs/13/runtime-config-connection.html#RUNTIME-CONFIG-CONNECTION-SSL)) und lädt in den gleichen Ordner die Dateien `server.crt` und `server.key` hoch.
5
+
6
+Die Zertifikatsdateien sind alle im Repo und nach Anleitung (lokal auf dem Laptop) generiert:
7
+```bash
8
+# Root Certificate Signing Request (CSR) erstellen
9
+openssl req -new -nodes -text -out root.csr -keyout root.key -subj "/CN=root.industry40.digillab"
10
+chmod og-rwx root.key
11
+# Root CSR selbst signieren
12
+openssl x509 -req -in root.csr -text -days 3650 -extfile /etc/ssl/openssl.cnf -extensions v3_ca -signkey root.key -out root.crt
13
+# Server CSR erstellen und selbst signieren
14
+openssl req -new -nodes -text -out server.csr -keyout server.key -subj "/CN=db.industry40.digillab"
15
+chmod og-rwx server.key
16
+openssl x509 -req -in server.csr -text -days 3650 -CA root.crt -CAkey root.key -CAcreateserial -out server.crt
17
+```
18
+
19
+Danach startet man Postgresql neu (in der VM: Eingebeaufforderung als Admin starten, dann `services.msc<ENTER>` und bei postgres 13 ber Rechtsklick neustarten. Falls eine Fehlermeldung kommt, ist evtl etwas in der Konfiguration falsch).
20
+
21
+# Clients hinzufügen
22
+Damit nur berechtigte Clients aus dem MWN zugreifen können, müssen die Client IPs einzeln in `C:\Program Files\PostgreSQL\13\data\pg_hba.conf` eingetragen werden. Diese Zeile erlaubt zum Beispiel den tuedfed-tat40web Server mit IP `138.246.225.122`:
23
+```
24
+hostssl all all 138.246.225.122/32 md5
25
+```
26
+
27
+# Verbindung mit psycopg
28
+Mit psycopg kann man entweder ohne Verifzierung des Server Zertifikates (nur Transportverschlüsselung) sich verbinden:
29
+```
30
+conn = psycopg.connect(..., password="...", sslmode='require')
31
+```
32
+oder mit Verifizierung:
33
+```
34
+conn = psycopg.connect(..., password="...", sslmode='verify-ca', sslrootcert='root.crt')
35
+```
36
+In letzterem Fall braucht man die Datei `root.crt`.
37
+
38
+Falls der Client noch nicht in `pg_hba.conf` hinzugefügt wurde (siehe oben), erhält man die IP praktischerweise in der Fehlermeldung.
... ...
\ No newline at end of file
industrie_4.0/Postgres:-lokaler-und-remote-Zugriff.md
... ...
@@ -0,0 +1,68 @@
1
+Auf dem teachtum40 Server ist für Odoo Postgres standard über die Ubuntu Paketquellen installiert:
2
+```
3
+sudo apt install postgresql -y
4
+```
5
+
6
+Die primäre Konfiguration zu Postgres findet sich in
7
+- `/etc/postgresql/12/main/postgresql.conf`: Grundsätzliche Server Konfiguration
8
+- `/etc/postgresql/12/main/pg_hba.conf`: Anmeldemethoden je nach Quelle (lokal/remote) und User / DB
9
+
10
+# Lokaler Zugriff
11
+Für die Anmeldemethode `peer` ([Peer Authentication](https://www.postgresql.org/docs/current/auth-peer.html)):
12
+```bash
13
+# Grundlegendes Kommando
14
+#sudo -u USER psql DB
15
+sudo -u postgres psql postgres
16
+sudo -u odoo psql odoo_test
17
+```
18
+
19
+Für die Anmeldemethode `md5` ([Password Authentication](https://www.postgresql.org/docs/current/auth-password.html)):
20
+```bash
21
+# Grundlegendes Kommando
22
+#psql -U USER [-d DB]
23
+psql -U postgres
24
+psql -U odoo -d odoo_test
25
+```
26
+
27
+Falls man für den User `postgres` Password Auth eingerichtet hat, kann man trotzdem das obige Kommando mit Peer Auth verwenden, wenn man eine `.pgpass` Datei erstellt. Dann muss man das Passwort nicht immer eintippen.
28
+```bash
29
+# Als root, also nach
30
+#sudo su
31
+echo "localhost:*:*:postgres:PASSWORD" > ~postgres/.pgpass
32
+chown postgres:postgres ~postgres/.pgpass
33
+chmod 0600 ~postgres/.pgpass
34
+```
35
+
36
+# Remote Zugriff
37
+Mit SSH Port Tunneling
38
+```bash
39
+ssh -L 5432:localhost:5432 user@tuedfed-tat40web.srv.mwn.de
40
+```
41
+## Beekeeper Studio
42
+Nach dem öffnen von [Beekeeper Studio](https://www.beekeeperstudio.io/) ([Downloads für die Community Version](https://github.com/beekeeper-studio/beekeeper-studio/releases)) kann man dann direkt zugreifen im Falle von Password Auth:
43
+
44
+![image](uploads/c6102eda69727bc12f431da6e1fbd89d/image.png)
45
+
46
+## pgAdmin
47
+
48
+Für einen Benutzer/Passwort-Login via pgAdmin kann man einen dedizierten Benutzer anlegen, z. B.
49
+erst lokal mit
50
+```
51
+sudo -u postgres psql postgres
52
+```
53
+anmelden und Nutzer mit Passwort anlegen
54
+```
55
+CREATE USER pgAdmin WITH PASSWORD '1234' SUPERUSER
56
+```
57
+
58
+Oder aber als bestehender Benutzer via Kommandozeile einloggen und ein (postgres-spezifisches) Passwort festlegen. Gehört zum Beispiel der System-Benutzer `joachim` zu den postgres-Superusern, braucht aber noch ein Passwort damit pgAdmin sich so ausweisen kann, dann
59
+```
60
+sudo -u joachim psql postgres
61
+postgres-# \password joachim
62
+```
63
+und Passwort festlegen. (Man kann auch bloß '\password' aufrufen, das ändert das Passwort für den aktuell via 'psql' eingeloggten Benutzer.) Übrigens kann man mit '\dg' in der postgres-Shell die vorhandenen Benutzer auflisten lassen, falls da Unklarheiten bestehen.
64
+
65
+Für lokalen Zugriff dann mit diesem Benutzer/Passwort-Paar in pgAdmin anmelden.
66
+
67
+Für Remote-Zugriff dann SSH Port Tunneling wie oben und schließlich in pgAdmin mit diesem Benutzer an localhost angemeldet (Port Tunneling besorgt die remote Verbindung).
68
+
industrie_4.0/RDP-Zugriff-auf-Work-Station-innerhalb-MWN.md
... ...
@@ -0,0 +1,54 @@
1
+## Kurzfassung
2
+
3
+Um Arbeit auf der Workstation auch aus dem Home Office zu ermöglichen, ist diese innerhalb des MWN (insbesondere also nach Verbindung mit dem TUM-VPN) über Microsoft Remote Desktop unter der IP `10.162.111.159` erreichbar, solange sie eingeschaltet ist.
4
+
5
+## Benutzerkonten
6
+
7
+### Für Login auf Workstation aus dem MWN
8
+
9
+| PC name | Benutzer | Wer hat das Passwort? | Bemerkung |
10
+| ------ | ------ | ------ | ------ |
11
+| 10.162.111.159 | DigiLLab | Bert, Joachim, Arne | Administrator |
12
+| 10.162.111.159 | Joachim | Joachim| Administrator |
13
+
14
+Beides sind lokale Konten auf der Workstation (tbc: die Workstation ist gar nicht mit dem Active Directory verbunden).
15
+
16
+### Für Login auf der SLF-VM von der Workstation aus
17
+
18
+Falls mit Benutzer `DigiLLab` eingeloggt: HyperV-Manager öffnen und Doppelklick auf die VM.
19
+Falls mit Benutzer `Amelie` eingeloggt: Remote Desktop Anwendung öffnen und dann
20
+
21
+| PC name | Benutzer | Wer hat das Passwort? | Bemerkung |
22
+| ------ | ------ | ------ | ------ |
23
+| SLF-LAB-SERVER | Amelie | Joachim, Amelie | gleiches Passwort wie oben |
24
+
25
+Benutzer ```Amelie``` ist als lokaler Benutzer innerhalb der VM angelegt und dort der Gruppe der Benutzer hinzugefügt, die Remote-Zugriff auf die VM haben (heißt in dem Fall: rdp-Zugriff auf die VM von der Workstation aus). Dieser Benutzer ist logisch unabhängig von ```Amelie``` auf Ebene der Workstation (=> etwaige Passwortänderungen auf beiden Ebenen vornehmen!)
26
+
27
+## Konfiguration
28
+
29
+Die Workstation hängt aktuell an der Fritz Box, die als Internet-Router (und nicht IP-Client) eingestellt ist, wodurch sie einen eigenen IP-Adressbereich erstellt der nicht direkt aus dem MWN erreichbar ist.
30
+Um einen Zugriff mit Microsoft Remote Desktop zu ermöglichen, ist daher auf der Fritz Box der Port `3389` (Standard-Port für remote desktop protocol) der Work Station freigegeben.
31
+Die beteiligten IP-Adressen `10.162.111.159` der Fritz Box im MWN und `192.168.188.41` der Work Station im Netz der Fritz Box sind nicht fest, werden aber auch bei Neuanmeldung im jeweiligen Netzwerk normalerweise wieder so zugewiesen (vgl. System -> Ereignisse auf der Fritz Box).
32
+
33
+## Sicherheit
34
+
35
+Den Empfehlungen einer Mini-Serie auf heise.de folgend (insb. Teil 3 [RDP: Testen und angreifen](https://www.heise.de/hintergrund/Remote-Desktop-via-RDP-Testen-und-angreifen-3-4-4702968.html) und Teil 4 [RDP: Best Practices](https://www.heise.de/hintergrund/Remote-Desktop-via-RDP-Best-Practices-4-4-4711807.html)), ist der Zugriff nur aus dem MWN und nicht aus dem Internet möglich.
36
+Zusätzlich liefert der in Teil 3 beschriebene Test
37
+```
38
+nmap -P0 -p 3389 --script rdp-enum-encryption 10.162.111.159
39
+```
40
+das gewünschte Ergebnis:
41
+```
42
+Starting Nmap 7.80 ( https://nmap.org ) at 2022-03-02 20:36 CET
43
+Nmap scan report for 10.162.111.159
44
+Host is up (0.0020s latency).
45
+
46
+PORT STATE SERVICE
47
+3389/tcp open ms-wbt-server
48
+| rdp-enum-encryption:
49
+| Security layer
50
+| CredSSP (NLA): SUCCESS
51
+| CredSSP with Early User Auth: SUCCESS
52
+|_ RDSTLS: SUCCESS
53
+```
54
+d. h. ein Downgrade auf unsichere RDP-Verbindungen kann dank der aktuellen Version auf der Work Station nicht erzwungen werden.
industrie_4.0/SLF-Configurator.md
... ...
@@ -0,0 +1,33 @@
1
+## Kurzfassung
2
+
3
+Der "Configurator" ist ein Endpunkt der SLF, der zur programmatischen Eingabe von Fertigungsaufträgen benutzt werden kann. Er liefert daher einen ersten Ansatzpunkt für die Odoo-SLF-Integration.
4
+
5
+## Einrichtung
6
+
7
+Im Netzwerk des Industrial Space (SSID `FRITZ!Box 4040 CI`) ist unter `192.168.188.27:8080/slf/configurator` der Configurator erreichbar, über den Aufträge eingegeben werden können. Der Port ist auf dem Router freigegeben, also ist der Configurator MWN-weit unter [10.162.111.159:8080/slf/configurator](http://10.162.111.159:8080/slf/configurator) erreichbar.
8
+
9
+## Gebrauch
10
+
11
+Voraussetzung: Im der SLF-Steuerung (`192.168.188.28:8080`) muss eine Produktion vorbereitet worden sein, sonst ist `plant_state:idle` und keine Aufträge werden angenommen. Für Entwicklungszwecke ist es egal, ob die Stationen erreichbar sind. (Die Stationen können dank Funksteckdosen vom `sturzkamera`-Raspi im Smart Home aus über 433MHz eingeschaltet werden; das muss noch dokumentiert und ggf. durch WLAN-Steckdosen im Industrie-WLAN verbessert werden).
12
+
13
+Mit
14
+```
15
+curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d 'configuration_elements=10&command=submit&name=yesWeCURL&motor=MM&battery=NO&chassis=CB&shock_absorbers_front=O&shock_absorbers_back=O&front_left=W&front_right=S&back_left=S&back_right=S' http://10.162.111.159:8080/slf/configurator
16
+```
17
+lässt sich aus dem MWN ein Auftrag eingeben (oder natürlich im Browser). Die Bedeutung der Parameter wird ersichtlich, wenn man im Browser das Formular abschickt und den POST Request anschaut.
18
+
19
+## Einschränkungen
20
+
21
+### Configurator ist Mischung aus Konfigurations-/Auftrags-Eingabe
22
+
23
+Dieses ganze Vorgehen – das von Inoyad als "Schnittstelle" für die Auftragseingabe vorgeschlagen wurde - ist eigentlich eine Zweckentfremdung des Configurators, der wohl mal als Eingabemöglichkeit einer Konfiguration (von den insgesamt ca. 25000 möglichen Konfigurationen des Autos, Spoiler nicht mal mitgezählt) gedacht war und nicht so sehr als Eingabemöglichkeit einer Einzelbestellung. Dementsprechend zeigt
24
+```
25
+select * from product_configuration where name like 'WHM%'
26
+```
27
+dass die Fertigungsaufträge, die wir aus Odoo über den Configurator einspeisen, nicht bloß in `production_order` (mit `product_configuration_id` als Fremdschlüssel) abgelegt werden, sondern auch in `product_configuration` verewigt werden.
28
+
29
+Das ist zwar von der Modellierung her nicht sauber, fällt aber in der Praxis nicht weite rauf.
30
+
31
+### Heckspoiler nicht konfigurierbar
32
+
33
+Der Configurator bietet keine Auswahl für den Heckspoiler. TO DO: Mal mit Matthias kläre, wie der Heckspoiler eigentlich in den Beispielaufträgen vorkommt. Eventuell werden wir Inoyad ohnehin mal beauftragen, den Configurator in der Hinsicht zu erweitern, wenn wir nämlich 3D-gedruckte individuelle Spoiler-Designs implementieren (vgl. Ticket #18 )
industrie_4.0/Subdomains-von-erp-test.oct.re-mit-eigenen-Odoo-DBs-einrichten.md
... ...
@@ -0,0 +1,9 @@
1
+Der DB-Filter ist so, dass die Datenbank der zugehörigen Subdomain verwendet wird. Das heißt die erp-test.oct.re verwendet die DB erp-test (ich hab dazu WiPaed über ein Backup/Restore kopiert und in erp-test umbenannt), und z.B. odoo-mrp.erp-test.oct.re verwendet die DB odoo-mrp. Um eine neue DB einzurichen muss man sie aber noch Nginx hinzufügen und das Zertifikat erstellen:
2
+
3
+```
4
+sudo nano /etc/nginx/sites-enabled/odoo.conf # An beiden Stellen wo "server_name" vorkommt eine neue Zeile hinzufügen
5
+sudo certbot --expand -d erp-test.oct.re -d odoo-mrp.erp-test.oct.re -d 2.erp-test.oct.re # Hier alle Domains auflisten (bei der Frage zum redirect die "1: no redirect" auswählen)
6
+sudo systemctl restart nginx
7
+```
8
+
9
+Dann kann man unter der neuen Subdomain in Odoo eine neue Datenbank einrichten, wo der DB-Name mit der Subdomain beginnen muss, z. B. auf startzustand.erp-test.oct.re: startzustand-ohne-webshop, startzustand-mit-webshop, startzustand-mit-webshop-und-fertigung usw.
industrie_4.0/pgAdmin-auf-SLF-Workstation.md
... ...
@@ -0,0 +1,2 @@
1
+SLF-VM hochfahren. Danach pgAdmin als Benutzer `DigiLLab` auf dem Host-System (!) öffnen, nicht innerhalb der SLF-VM. Master-Passwort für pgAdmin siehe Joachims Schlüsselbund; Passwörter für einzelne DBs siehe Passwortliste die Inoyad bereitgestellt hat (oder Joachims Schlüsselbund).
2
+
industrie_4.0/uploads/1c1401b67421c46b7586affee397ab8b/Firewall.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/1c1401b67421c46b7586affee397ab8b/Firewall.png differ
industrie_4.0/uploads/29bb2b7bb5b1132aba349fc841f3604a/grafik.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/29bb2b7bb5b1132aba349fc841f3604a/grafik.png differ
industrie_4.0/uploads/4ba6bf1e10c6f77d28056d836dfd364f/image.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/4ba6bf1e10c6f77d28056d836dfd364f/image.png differ
industrie_4.0/uploads/5462160aebd3cb1d55b355c407353fdf/image.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/5462160aebd3cb1d55b355c407353fdf/image.png differ
industrie_4.0/uploads/86c636b34ae5bff823c03f3a2c205f0d/545851678a4947ff874d74cac0249e1a.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/86c636b34ae5bff823c03f3a2c205f0d/545851678a4947ff874d74cac0249e1a.png differ
industrie_4.0/uploads/92ac8da2a4033bec8077285472dbb0f9/grafik.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/92ac8da2a4033bec8077285472dbb0f9/grafik.png differ
industrie_4.0/uploads/aa16915388cbefedbd97f21deab1f2ee/image.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/aa16915388cbefedbd97f21deab1f2ee/image.png differ
industrie_4.0/uploads/b2252f7e6e4e208ab3de2cc02c820d70/grafik.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/b2252f7e6e4e208ab3de2cc02c820d70/grafik.png differ
industrie_4.0/uploads/c6102eda69727bc12f431da6e1fbd89d/image.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/c6102eda69727bc12f431da6e1fbd89d/image.png differ
industrie_4.0/uploads/f0b5df08601037b3ecb266e8c9e0d71c/1045313ec9ba4c5d8bd1b03619fb05f8.png
... ...
Binary files /dev/null and b/industrie_4.0/uploads/f0b5df08601037b3ecb266e8c9e0d71c/1045313ec9ba4c5d8bd1b03619fb05f8.png differ
smart_home/Ansible.md
... ...
@@ -0,0 +1,39 @@
1
+Mit Ansible lässt sich das Einrichten und Verwalten der Geräte (Raspis) im Smart Home teilweise automatisieren. Der Aufwand kann zu Beginn vielleicht etwas größer sein, um Ansible einzurichten, dafür ist es später dann schneller und einfacher. Voraussetzung hierfür ist, dass die Raspis (oder andere Geräte) ein frisch installiertes Raspbian (aktuell: Bullseye) haben. Die Installation ist in [Einrichtung der Raspis](Einrichtung der Raspis) beschrieben.
2
+
3
+# Erste Schritte
4
+Die folgenden Schritte sind alle für eine Linux-artige Kommandozeile (BASH) geschrieben. Unter Windows kann man dazu das Windows Subsystem for Linux verwenden, siehe: [Installation unter Windows mit WSL](https://www.purrucker.de/2019/01/14/installation-von-ansible-auf-einem-windows-system/). Unter Mac OS sollte das [eingebaute Terminal](https://support.apple.com/de-li/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac) auch funktionieren.
5
+
6
+## 1. SSH Keys einrichten
7
+Ansible lässt sich mit SSH Keys am einfachsten verwenden. Falls man noch keine hat, kann man sich SSH Keys erstellen mit:
8
+```bash
9
+ssh-keygen -t ed25519 -b 4096
10
+```
11
+und dann den Schritten folgen. Die Standardwerte sind in der Regel passend. Hat man das abgeschlossen, kann man den öffentlichen Teil des Keys auslesen:
12
+```bash
13
+cat ~/.ssh/id_ed25519.pub
14
+```
15
+Den Inhalt der Datei muss man jetzt auf dem Smart Home Server in die Datei `/home/pi/.ssh/authorized_keys` einfügen. Falls der Ordner oder die Datei noch nicht existiert, muss man sie noch erstellen (`mkdir ~/.ssh` und `nano ~/.ssh/authorized_keys`). Danach kann man wie gewohnt sich per SSH verbinden, muss aber kein Passwort mehr eintippen:
16
+```bash
17
+ssh pi@192.168.xx.yy
18
+```
19
+
20
+## 2. Installation
21
+Die offzielle Dokumentation findet sich hier:
22
+[Installing Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)
23
+
24
+Voraussetzung für die Installation ist Python, über das man Ansible einfach mit pip installieren kann:
25
+```bash
26
+python3 -m pip install --user ansible
27
+```
28
+(Die Installation erfolgt nur auf dem lokalen Computer. Auf den Raspis muss man nichts installieren.)
29
+
30
+## 3. Ausführen von Ansible Befehlen
31
+Zur Verwendung von Ansible muss man im Ordner `ansible` im Smart Home Repo sein:
32
+```bash
33
+cd ansible
34
+```
35
+
36
+Dort lassen sich mit folgendem Bezehl zum Beispiel alle Kühlschrank Raspi Zeros neustarten:
37
+```bash
38
+ansible-playbook zeros.yml --tags "reboot"
39
+```
... ...
\ No newline at end of file
smart_home/Aufbau.md
... ...
@@ -0,0 +1,27 @@
1
+# Überblick
2
+
3
+Das Smart Home ist um eine Art "Smart Home Zentrale" herum gebaut (dem _smart-home-control_ Server), der auf einem Raspberry Pi läuft. Alle weiteren Geräte und Softwarekomponenten lassen sich aufteilen in Geräte, Gerätesteuerungen und Interfaces/Apps.
4
+
5
+**Geräte** sind meistens kommerzielle Produkte, die im Smart Home verbaut sind. Manche sind speziell für Smart Homes gedacht (z.B. die smarten Steckdosen oder der SensFloor), andere eher Elektronik "Bastelprodukte" für den Raspberry Pi (z.B. die Kameras oder der Fenstersensor).
6
+
7
+Die **Gerätesteuerungen** verbinden die häufig gerätespezifischen Interfaces mit der Smart Home Zentrale. Auf die Art kann es im Smart Home eine einheitliche API geben (fertige Smart Home Software bringt für sowas in der Regel eigene Bibliotheken an unterstützten Geräten mit). Vor allem bei den Kameras läuft die Gerätesteuerung aufgrund der Entfernung auf einem eigenen Raspberry Pi.
8
+
9
+**Interfaces oder Apps** verbinden sich auf ähnliche Weise mit der Smart Home Zentrale, verwenden aber andere Funktionen der API. Sie können Daten in Echtzeit auslesen und Ereignisse auslösen, die dann an die Gerätesteuerungen geschickt werden. Für manche spezielle Funktionen (z.B. Push-Benachrichtigungen für die App) gibt es zusätzliche "Plugins" in der Smart Home Zentrale.
10
+
11
+![schema-2](uploads/0499de98dc50912c4788d24b5fa08658/schema-2.png)
12
+
13
+# Architektur
14
+
15
+Anders als typische Softwareprogramme besteht das Smart Home eher aus vielen einzelnen, verteilten Programmen/Komponenten. Das hat den Vorteil, dass es einen deutlich geringeren Unterschied macht, auf welchem Gerät die Programme laufen. Zum Beispiel ist das Mikron zwar gerade an den zentralen Raspberry Pi angeschlossen, und hat dort auch seine Gerätesteuerung laufen. Man könnte es aber genauso gut wo anders hinstellen und (bei nicht ausreichendem Kabel) an einen anderen Raspberry Pi dort anschließen. Außerdem ist es leichter sicherzustellen, dass das Smart Home robust gegenüber ausgefallenen Geräten ist.
16
+
17
+Der Nachteil ist allerdings, dass die Organisation von Daten und Gerätestatus komlexer wird. Aus diesem Grund spielt die Socket.IO (SIO) API zwischen den Gerätesteuerungen bzw. Interfaces/Apps und der Smart Home Zentral eine wesentliche Rolle.
18
+
19
+# Details
20
+
21
+Die meisten Gerätesteuerungen laufen als Systemd Service (eine Art Hintergrunddienst, der automatisch neustartet), daher die Namen mit `.service`.
22
+
23
+![schema-2-extended](uploads/b1298abf4c88d5cb88fbcd05505ce442/schema-2-extended.png)
24
+
25
+Dokumentation zu den einzelnen Komponenten:
26
+
27
+[smart-home-control](Smart%20Home%20Control%20%E2%80%93%20Server)
... ...
\ No newline at end of file
smart_home/Beteiligte-Computer-und-wichtigste-Services.md
... ...
@@ -0,0 +1,84 @@
1
+# Beteiligte Computer
2
+
3
+Die folgenden Computer sind am Smart Home beteiligt:
4
+
5
+| Typ | Name im Netzwerk | Ort | Äußere Merkmale | Erforderlich für |
6
+| ------ | ------ | ------ | ------ | ------ |
7
+| Raspberry Pi 4 | smart-home-server | Weißes Regel, unteres geschlossenes Fach | Transparentes Acrylgehäuse | Alles |
8
+| Raspberry Pi 3 | aa000024 | Auf dem weißen Regal | an Rückseite linker Monitor montiert | SensFloor |
9
+| Raspberry Pi 3 | c8a000ae | Boden nebem dem Schreibtisch | Schwarzes Plastikgehäuse | SensFloor |
10
+| Raspberry Pi | camera | An der Decke | Kamera | Sturzkamera |
11
+| Raspberry Pi Zero | kuehlschrank-1 | Kühlschrank innen oben | Mit Öffnungssensor verkabelt | Kühlschrank-Fotos (alle) |
12
+| Raspberry Pi Zero | kuehlschrank-2 | Kühlschrank Tür oben | | Zweites Kühlschrank-Foto|
13
+| Raspberry Pi Zero | kuehlschrank-3 | Kühlschrank Tür unten | | Drittes Kühlschrank-Foto|
14
+
15
+Überprüfung im Netzwerk (SSID `Smart Home`, Passwort `05808161781375379960`): Im Browser die Adresse `192.168.178.1` öffnen und in die Fritz Box einloggen mit Passwort `soft0734`. Dann sollten unter dem Seitenreiter "Netzwerk" obige Geräte mit folgenden IPs sichtbar sein:
16
+
17
+| Name im Netzwerk | IP | lokale Domain |
18
+| ------ | ------ | ------ |
19
+| smart-home-server | 192.168.178.24 | smart-home-server.fritz.box |
20
+| c8a000ae | 192.168.178.22 | c8a000ae.fritz.box |
21
+| aa000024 | 192.168.178.27 | aa000024.fritz.box |
22
+| camera | 192.168.178.25 | camera.fritz.box |
23
+| kuehlschrank-1 | ... | kuehlschrank-1.fritz.box |
24
+| kuehlschrank-2 | ... | kuehlschrank-2.fritz.box |
25
+| kuehlschrank-3 | ... | kuehlschrank-3.fritz.box |
26
+
27
+# Smart Home Control Server starten
28
+Der Server vom Smart Home Control sollte automatisch starten. Falls etwas nicht funktioniert hat, oder der Server neugestartet werden soll, geht das über den Systemd Service:
29
+
30
+```
31
+sudo systemctl restart smart-home
32
+```
33
+
34
+Neben `restart` gibt es auch `start`, `stop` und `status`. Die Service-Konfiguration liegt in `/etc/systemd/system/smart-home.service`. Der Server selbst in `/home/pi/smart-home/smart-home-control`.
35
+
36
+Die Smart Home Control Oberfläche ist dann erreichbar unter `https://smart-home-server.fritz.box:3030/#home` (Achtung: Selbst-signiertes Zertifikat).
37
+
38
+# SensFloor sichtbar machen
39
+
40
+Den linken Monitor an der Fensterbank einschalten; dort ist das SensFloor "Stationsterminal" (aa000024) angeschlossen, das automatisch den SensFloor visualisieren sollte. Falls nicht: Diesen Computer (Rückseite vom Monitor) neu starten. Falls immer noch nicht: Einen anderen Computer ins "Smart Home" WLAN einloggen (Passwort s. o.) und im Browser die Adresse
41
+```192.168.178.22:8000```
42
+eingeben. Dort sollte der SensFloor visualisiert werden.
43
+
44
+# Sprachsteuerung einschalten
45
+
46
+## Spracherkennung starten
47
+
48
+Die Spracherkennung läuft über das Skript in `/home/pi/smart-home/spracherkennung/`. Das kann man entweder von Hand starten:
49
+```
50
+python3 /home/pi/smart-home/spracherkennung/spracherkennung.py -r 48000 --model /home/pi/vosk-api/python/example/model/ -s https://localhost:3030
51
+```
52
+Oder den user-level service starten (und später mit `stop` statt `start` stoppen), dann läuft der im Hintergrund:
53
+```
54
+systemctl --user start spracherkennung
55
+```
56
+
57
+Das geht per SSH, oder wenn man den rechten Monitor einschaltet, an den smart-home-server Tastatur und Maus anschließt, ein neues Terminal-Fenster öffnet (oben links in der Menüleiste auf dem Desktop) und einen der obigen Befehle eingibt.
58
+
59
+Was das Mikrofon aufnimmt ist auf der Smart Home Control Oberfläche unter `Details anzeigen` bei Mikrofon, wenn das Mikrofon an ist.
60
+
61
+## Lichtsteuerung starten
62
+
63
+Auf smart-home-server neues Terminalfenster öffnen und
64
+```
65
+node /home/pi/Desktop/nodejs-server/server.js
66
+```
67
+eingeben. Sollte einen Prozess starten, der unter anderem die Anzeige "Sprachsteuerung hat PID … " ausgibt.
68
+
69
+## Sprachsteuerung benutzen
70
+
71
+Die Sprachsteuerung sollte unter anderem auf die Befehle "mach das Küchenlicht an", "mach das Küchenlicht aus", "mach die Stehlampe an", "mach die Stehlampe aus" reagieren. Hinweis: Den Befehl "mach das Licht an" versteht sie derzeit nicht; man muss angeben, welches Licht.
72
+
73
+# Kamera einschalten
74
+Wenn der Raspi für die Kamera an ist, sollte das zugehörige Skript automatisch starten und sich mit dem Smart Home Control verbinden. Dazu gibt es einen Service in `/etc/systemd/system/camera.service`.
75
+
76
+Von Hand kann man die Kamera starten/stoppen/etc. mit:
77
+```
78
+# (Neu)starten
79
+sudo systemctl restart camera
80
+# Stoppen
81
+sudo systemctl stop camera
82
+# Status anzeigen
83
+sudo systemctl status camera
84
+```
... ...
\ No newline at end of file
smart_home/Einrichtung-der-Raspis.md
... ...
@@ -0,0 +1,23 @@
1
+Die Einrichtung der ganzen Dienste und Software auf den Raspis geht einfach mit Ansible (siehe [Ansible](Ansible)). Hier geht es darum, wie man die Raspis dazu erstmals vorbereitet, dass man im weiteren mit Ansible arbeiten kann.
2
+
3
+Das Aufspielen vom Betriebssystem geht ganz einfach mit dem Tool [Raspi Imager](https://www.raspberrypi.com/software/) (Paket: `rpi-imager`):
4
+
5
+![5463902fb12c4e2fa4b6b63ee3a9c1aa](uploads/dfc7beadddca131c8329ef5bbc98e485/5463902fb12c4e2fa4b6b63ee3a9c1aa.png)
6
+
7
+**1. Betriebssystem auswählen:**
8
+
9
+![a2b3652d429e48ec83f3fda1f9572b76](uploads/08be79f221f554d655028be8504210c4/a2b3652d429e48ec83f3fda1f9572b76.png)
10
+
11
+**2. SD Karte auswählen:**
12
+
13
+![eb352ae021eb435b92c0e83017cdb867](uploads/23bf2cf0f7966faba193bfc325f27abf/eb352ae021eb435b92c0e83017cdb867.png)
14
+
15
+**3. Erweiterte Einstellungen öffen:** (Zahnradsymbol)
16
+
17
+![image](uploads/76ab6798e5251320e963f967ad2db6ec/image.png)
18
+
19
+Hier gibt es eventuell anzupassen:
20
+- Den Hostname (Wird über Ansible evtl. nochmal geändert, aber es hilft schon mal, den Raspi im lokalen Netz erkennen zu können),
21
+- Passwort oder SSH-Key. Man kann auch erstmal die Anmeldung mit Passwort einrichten, und dann später den SSH Key draufspielen. Spätestens für Ansible braucht man dann aber ein SSH Key. Wichtig ist dabei, dass es am Schluss einen User *pi* gibt, der root Rechte hat.
22
+
23
+**4. Image aufspielen** mit Klick auf `Write`.
... ...
\ No newline at end of file
smart_home/Fenstersensor.md
... ...
@@ -0,0 +1,20 @@
1
+# Installation
2
+Der Sensor ist ein Reed Schalter, das heißt es gibt einem Magneten, der am Fenster befestigt wird, und ein Sensor, der an der Wand / am Fensterrand fest gemacht wird. Man kann den Schalter im Prinzip direkt an den Raspberry Pi anschließen, aber zur Sicherheit ist aktuell noch ein 2,2kOhm widerstand dazwischen, um einen Kurzschluss zu vermeiden, falls man mal aus Versehen den entsprechenden Pin als Output setzen würde.
3
+
4
+# Auslesen
5
+Angeschlossen ist die eine Seite auf GND, die andere an [BCM Pin 26 (Physischer Pin 37)](https://pinout.xyz/pinout/pin37_gpio26). Der Pin wird als Pull-Up konfiguriert, das heißt wenn der Kontakt offen ist (Fenster offen), ließt man eine 1, und wenn der Kontakt zu ist eine 0. Der Code dazu, der das an den `smart-home-server` überträgt liegt in `sensors/window` und ist auf dem Raspi als User-level Service eingerichtet. Das heißt man kann ihn starten/stoppen mit:
6
+
7
+```bash
8
+systemctl --user start/stop window-sensor
9
+```
10
+
11
+Die Service Datei liegt in `~/.config/systemd/user/window-sensor.service`.
12
+
13
+# Daten
14
+Der Sensor schreibt in den Kanal `fenster` folgendes Objekt:
15
+```js
16
+{
17
+ offen: true / false / null
18
+}
19
+```
20
+`null` bedeutet, dass noch nicht bekannt ist, ob des Fenster offen, oder der Kontakt einfach nicht am Raspi verbunden ist. Nur wenn der Kontakt zu ist, kann man sicher davon ausgehen, dass was verbunden ist. Das heißt falls man den `window-sensor` service neustartet, während das Fenster offen ist, muss man es einmal schließen, damit da `true` oder `false` steht.
... ...
\ No newline at end of file
smart_home/Fernzugriff-der-API.md
... ...
@@ -0,0 +1,108 @@
1
+Der smart-home-control Server ist aus Sicherheitsgründen nur sehr eingeschränkt von außen zu erreichen. Trotzdem sollen bestimmte Funktionlitäten, wie zum Beispiel Push-Benachrichtigungen oder Alexa Anbindung möglich sein. Außerdem muss intern auch HTTPS verfügbar sein (idealerweise nicht selbst-signiert, weil das auf allen Geräten eingerichtet werden müsste). Die Seite hier beschreibt, wie das funktioniert und eingerichtet wird.
2
+
3
+# 0. Allgemeine Funktionsweise
4
+Die beteiligten Server sind:
5
+- Der smart-home-control Raspi, der nur aus dem Smart-Home LAN vollständig erreichbar ist. Aus dem MWN kann man sich (via Portfreigabe auf der FritzBox) per SSH verbinden. Von ganz außen geht keine Verbindung.
6
+- Der teachtum40 Server, der aus bestimmten MWN Adressen SSH Verbindungen erlaubt, von ganz außen aber nur HTTP(S).
7
+
8
+Verbindungen von außen nimmt also der teachtum40 Server per HTTPS entgegen. Jeder Client, der sich darüber per Socket.io verbindet, muss ganz am Anfang ein Token schicken (`sio.emit("login", "<token>")`), damit er Zugriff auf die smart-home-control API bekommt. Je nach Token lässt sich konfigurieren, welche spezifischen Zugriffe erlaubt sind.
9
+
10
+Das Token bekommt der Client entweder aus dem internen Netz (dazu ruft er `https://smart-home-internal.teachtum40.../token` ab (tbd)), oder er hat es woanders her. Zum Beispiel könnte man es in URLs / scannbare QR-Codes einbetten.
11
+
12
+# 1. Zertifikat-Forwarding
13
+Damit der Smart-Home-Server Let's Encrypt Zertifikate erhalten kann, obwohl er nicht von außerhalb des MWN ereichbar ist, werden die Zertifikate vom teachtum40 Server generiert, und mithilfe eines Post-Hooks per SCP an den smart-home-server übertragen.
14
+
15
+## Einrichtung der SCP-Übertragung
16
+Damit wirklich _nur_ die Übertragung des Zertifikats möglich ist, wird für den teachtum40 Server ein eigenes SSH Keypair generiert (auf dem teachtum40 Server):
17
+
18
+```bash
19
+ssh-keygen -t ed25519 -b 4096 -C "certificate-forwarder@digillab" -f id_ed25519_cert_forwarder
20
+```
21
+
22
+Das neue Keypair wird als `id_ed25519_cert_forwarder(.pub)` gespeichert.
23
+
24
+Auf dem Smart Home Server kann man jetzt einen Zielordner erstellen, an den der teachtum40 Server hinkopieren kann:
25
+```bash
26
+sudo mkdir /srv/from-teachtum40
27
+sudo chown pi:pi /srv/from-teachtum40
28
+```
29
+
30
+Dann fügt man den Public Key von Forwarder (`id_ed25519_cert_forwarder.pub`) auf dem Pi hinzu:
31
+```bash
32
+echo 'from="138.246.225.122,2001:4ca0:800::8af6:e17a",restrict,command="scp -r -v -t /srv/from-teachtum40/" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICCHnczUZaDTfj/2muKX4A32fsGsq8LH3DzC7Du4UfFz certificate-forwarder@digillab' >> ~/.ssh/authorized_keys
33
+```
34
+(Public Key und IP Adressen ggf. ändern)
35
+
36
+Durch Angabe der IPs kann der Key nur für Verbindung von der gegebenen IP Adresse verwendet werden.
37
+
38
+Mit dieser Konfiguration kann der teachtum40 Server jetzt Dateien in das oben erstellte Verzeichnis kopieren:
39
+```bash
40
+scp -i /pfad/zu/id_ed25519_cert_forwarder -o StrictHostKeyChecking=no lokale-datei-zum-kopieren.txt pi@10.162.111.146:
41
+```
42
+(IP Adresse ggf. ändern)
43
+
44
+Falls ein Fehler kommt, dass die Berechtigungen für den private Key zu locker sind, kann man das einschränken mit:
45
+```bash
46
+chmod u=rw,g=,o= id_ed25519_cert_forwarder*
47
+```
48
+
49
+## Certbot Post-Hook
50
+Zum Schluss richtet man noch den Post-Hook ein. Dazu gibt man das neue Zertifikat den root user, unter dem der renewal läuft (in `/etc/cron.d/certbot`):
51
+```bash
52
+sudo cp id_ed25519_cert_forwarder* /root/
53
+```
54
+
55
+Und erstellt eine Datei `/etc/letsencrypt/renewal-hooks/deploy/forward_certificate.sh` mit dem Inhalt:
56
+```bash
57
+#!/bin/bash
58
+scp -q -r -i /root/id_ed25519_cert_forwarder -o StrictHostKeyChecking=no /etc/letsencrypt/live/<die-domain>.de pi@10.162.111.146: > /dev/null 2>&1
59
+```
60
+(Domain und IP ggf. ändern)
61
+
62
+Bei der Ersteinrichtung des Zertifikats muss man das Skript einmal von Hand laufen lassen:
63
+```bash
64
+sudo /etc/letsencrypt/renewal-hooks/deploy/forward_certificate.sh
65
+```
66
+
67
+# 2. Port-Forwarding (für den Socket.io Server)
68
+Auf die gleiche Art wie das Zertifikat-Forwarding, lässt sich ein Port-Forwarding einrichten, bei dem sichergestellt wird, dass das nur für den teachtum40 Server möglich ist. Deswegen hier etwas abgekürzt:
69
+
70
+Auf teachtum40:
71
+```bash
72
+ssh-keygen -t ed25519 -b 4096 -C "port-forwarder@digillab" -f id_ed25519_port_forwarder
73
+sudo cp id_ed25519_port_forwarder* /root/
74
+
75
+# Public Key lesen und kopieren:
76
+cat id_ed25519_port_forwarder.pub
77
+```
78
+
79
+Auf dem smart-home-control:
80
+```bash
81
+echo 'from="138.246.225.122,2001:4ca0:800::8af6:e17a",restrict,port-forwarding,permitopen="localhost:3030",command="sleep infinity" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINgFE3nxYE/GEtwltRsa81/DuWDbeUXM7Y9Q+S0vFjaT port-forwarder@digillab' >> ~/.ssh/authorized_keys
82
+```
83
+
84
+Zum Schluss den Service dazu auf teachtum40 einrichten:
85
+```bash
86
+sudo vim /etc/systemd/system/smart-home-forwarder.service
87
+```
88
+und befüllen mit:
89
+```ini
90
+[Unit]
91
+Description=Port forwarding SSH script
92
+After=network.target
93
+StartLimitIntervalSec=0
94
+
95
+[Service]
96
+Type=simple
97
+Restart=always
98
+RestartSec=1
99
+ExecStart=/usr/bin/ssh -v -i /root/id_ed25519_port_forwarder -o StrictHostKeyChecking=no -L 3031:localhost:3030 pi@10.162.111.146 dummy-cmd
100
+
101
+[Install]
102
+WantedBy=multi-user.target
103
+```
104
+Und dann:
105
+```bash
106
+sudo systemctl enable smart-home-forwarder
107
+sudo systemctl start smart-home-forwarder
108
+```
... ...
\ No newline at end of file
smart_home/Fernzugriff-innerhalb-MWN.md
... ...
@@ -0,0 +1,28 @@
1
+## Kurzfassung
2
+
3
+Der Raspberry Pi `smart-home-server` ist per ssh und vnc unter `10.162.111.146` erreichbar. Für ssh-Zugriff muss der Zugreifende im MWN sein und seine öffentlichen Schlüssel auf `smart-home-server` hinterlegt haben. Für vnc-Zugriff muss der Zugreifende per TUM-VPN verbunden sein und sich per Passwort anmelden (Passwort hat JS). Dabei muss der VNC Viewer von RealVNC verwendet werden.
4
+
5
+## Konfiguration Router
6
+
7
+Auf der Fritz Box im Smart Home werden die Ports 22 (ssh) und 5900 (vnc) an `smart-home-server` weitergeleitet. Dieser hat bei der Fritz Box die feste IP `192.168.178.24`; die Fritz Box allerdings hat keine feste IP im MWN. Sie bekommt für gewöhnlich `10.162.111.146`.
8
+
9
+## Konfiguration `smart-home-server`
10
+
11
+### ssh
12
+
13
+ssh-Zugriffe sind nur über hinterlegten public key erlaubt, nicht über Passwort.
14
+
15
+### vnc
16
+
17
+VNC akzeptiert nur verschlüsselte Verbindungen (schwächt man in den Optionen des RealVNC Servers auf dem Raspberry Pi unter "Sicherheit" die Einstellung "Verschlüsselung: immer aktiviert" ab, so kann man auch andere als den RealVNC Viewer verwenden). Der IP-Range akzeptierter eingehender Verbindungen ist auf [TUM-VPN](https://doku.lrz.de/display/PUBLIC/VPN-Technik#VPNTechnik-VPN:IP-AdressenundSubdomains:neueBereicheseit2020-03!) beschränkt; auch innerhalb des MWN muss man daher das VPN verwenden. Falls es mal scheitert: Adress-Tabellen überprüfen. (Stand 2022-03: Aus Faulheit sind nur die IP Ranges freigegeben, die auch auf `tuedfed-tat40web.srv.mwn.de` vom LRZ eingestellt wurden, und nicht alle in der LRZ Doku aufgelisteten Ranges)
18
+
19
+### X2Go
20
+
21
+Nachdem VNC manchmal etwas langsam aus der Ferne ist, lauft aktuell auch [X2Go](https://wiki.x2go.org/doku.php) auf dem smart-home-control. X2Go verbindet sich über SSH. Damit ist keine weitere Portfreigabe nötig. Anders als VNC erstellt man mit X2Go aber eine neue LXDE Desktop Sitzung (zu konfigurieren in X2Go Client), und sieht damit nicht, was auf dem Bildschirm vor Ort zu sehen ist. Somit stört man zwar das lokale Display nicht, verursacht aber möglicherweise extra Last auf dem Raspi. Damit eher besser vermeiden, wenn das Smart Home gerade aktiv verwendet wird.
22
+
23
+Ein eigenen Chrome kann man starten mit:
24
+
25
+```bash
26
+#mkdir /tmp/chrome2
27
+chromium-browser --user-data-dir=/tmp/chrome2/
28
+```
... ...
\ No newline at end of file
smart_home/Funksteckdose-\303\274ber-433MHz-von-Raspi-ansteuern.md
... ...
@@ -0,0 +1,56 @@
1
+# Hardware
2
+
3
+## Funksteckdose
4
+
5
+Kleinen Deckel aufschrauben, anhand der ersten fünf Ziffern einen Hauscode einstellen (Bsp: 25, d. h. 2 und 5 nach oben, 1, 3, 4 nach unten) und dann genau einen Buchstaben auswählen (Bsp: A nach oben, Rest nach unten)
6
+
7
+## 433MHz-Sender auf Raspberry Pi
8
+
9
+Sender braucht 5,5V auf VCC (mittlerer Kontakt), Erde auf Ground und einen GPIO auf Data. Am Einfachsten verbindet man Data mit dem physischen Pin Nr. 11 auf dem Raspi 4, was aus Gründen GPIO Nr. 17 ist (siehe https://cdn.mos.cms.futurecdn.net/kSo96fYwdrfQKSvALMKqzc.png) und jedenfalls dem Default
10
+```
11
+int pin = 0;
12
+```
13
+in Z. 49 von raspberry-remote/send.cpp entspricht. Falls der physische Pin 11 belegt sein sollte, muss diese Zeile entsprechend der Wiring Pi Nummerierung verändert werden, siehe hierzu http://wiringpi.com/pins/
14
+
15
+# Software
16
+
17
+## Wiring Pi
18
+
19
+Wiring Pi ist auf Raspian schon vorinstalliert, siehe http://wiringpi.com/download-and-install/
20
+Aber update nötig (http://wiringpi.com/wiringpi-updated-to-2-52-for-the-raspberry-pi-4b/):
21
+
22
+```
23
+cd /tmp
24
+wget https://project-downloads.drogon.net/wiringpi-latest.deb
25
+sudo dpkg -i wiringpi-latest.deb
26
+```
27
+
28
+Prüfen mit:
29
+```
30
+gpio -v
31
+```
32
+sollte 2.52 sein
33
+
34
+Übrigens: WiringPi-Entwickler hat keinen Bock mehr, also letzte Version. (http://wiringpi.com/wiringpi-deprecated/)
35
+
36
+## Raspberry Remote
37
+
38
+```
39
+cd ~
40
+sudo git clone git://github.com/xkonni/raspberry-remote.git
41
+cd raspberry-remote
42
+sudo make send
43
+```
44
+
45
+# Benutzung
46
+
47
+Nun ist obige Funksteckdose (mit der Schalterstellung 25A) einschaltbar durch
48
+```
49
+cd ~/raspberry-remote
50
+sudo ./send 01001 1 1
51
+```
52
+und ausschaltbar durch
53
+```
54
+sudo ./send 01001 1 0
55
+```
56
+Syntax: .send [Hauscode, d. h. 0 für nicht gewählte Ziffer und 1 für gewählte Ziffer] [1 für A, 2 für B…] [1 für an, 0 für aus]
... ...
\ No newline at end of file
smart_home/Ger\303\244te-im-Smart-Home.md
... ...
@@ -0,0 +1,93 @@
1
+# Übersicht
2
+
3
+<table>
4
+<tr>
5
+<th>Sensor</th>
6
+<th>Bild</th>
7
+<th>Beschreibung</th>
8
+</tr>
9
+<tr>
10
+<td>Sensorboden (SensFloor)</td>
11
+<td>
12
+
13
+</td>
14
+<td>
15
+
16
+Der Sensorboden erkennt, wo sich Personen befinden, und ob sie gestürzt sein könnten. Das Prinzip dahinter ist genau das gleiche wie bei einem Touchscreen auf dem Handy, nur in groß.<br>Die Kacheln erkennen mittels Kapazitätssensoren, ob sich etwas leitfähiges in der Nähe befindet. Holzmöbel stellen somit kein Problem dar. Für statische, metallische Gegenstände kann eine Kalibration durchgeführt werden, sodass am Schluss im Idealfall nur Menschen oder ein rutschiger Boden (Wasser) erkannt werden.
17
+</td>
18
+</tr>
19
+
20
+<tr>
21
+<td>Sturzkamera</td>
22
+<td>
23
+
24
+![image](uploads/cf4bfc2f1bffda8ea9e9b9aa031eff4b/image.png)
25
+</td>
26
+<td>Die Sturzkamera kann ein Foto machen, wenn ein Sturz erkannt wurde. Damit können Angehörige wissen, ob tatsächlich etwas passiert ist, oder es ein Fehlalarm war.</td>
27
+</tr>
28
+
29
+<tr>
30
+<td>Mikrofon</td>
31
+<td>
32
+
33
+</td>
34
+<td>Das Mikrofon erlaubt es, auf einfache Sprachbefehle zu reagieren. Zum Beispiel kann so das Küchenlicht ein- und ausgeschaltet werden. Die Verarbeitung der Sprache passiert dabei ausschließlich lokal.</td>
35
+</tr>
36
+<tr>
37
+<td>Fenstersensor</td>
38
+<td>
39
+
40
+![image](uploads/0f3924fb24e4d769a8e3f55a7f1bac19/image.png)
41
+</td>
42
+<td>
43
+
44
+Der Fenstersensor besteht aus einem einfachen Magnetsensor, der erkennen kann, ob das passende, am Fenster befestigte, Gegenstück da ist (Fenster zu) oder nicht (Fenster offen).
45
+
46
+Öffnet man das Fenster, schaltet die Heizung automatisch runter, um keine Energie zu verschwenden. Schließt man es wieder stellt sich das Thermostat wieder auf den vorigen Wert.
47
+</td>
48
+</tr>
49
+<tr>
50
+<td>smartes Thermostat</td>
51
+<td>
52
+
53
+</td>
54
+<td>Das smarte Thermostat (Modell Shelly TRV) ist aktuell an einem 3D-gedruckten Fake-Ventil befestigt (sonst funktioniert es nicht). Es kann sowohl selbst auf eine gewünschte Temperatur regeln (automatischer Modus), oder auf einen bestimmten prozentualen Öffnungswert (manueller Modus).</td>
55
+</tr>
56
+<tr>
57
+<td>Kühlschrank</td>
58
+<td>
59
+
60
+![image](uploads/22ae7016c123bd3a037837b13624837b/image.png)
61
+</td>
62
+<td>Der Kühlschrank hat drei kleine Kameras und einen Abstandssensor eingebaut, der den Öffnungswinkel misst. Kurz bevor man den Kühlschrank schließt, machen die Kameras ein Foto vom Inneren, sodass z.B. die Familie oder eine Haushaltshilfe von unterwegs nachsehen kann, was noch da ist.</td>
63
+</tr>
64
+<tr>
65
+<td>Umgebungssensor</td>
66
+<td>
67
+
68
+</td>
69
+<td>
70
+
71
+Der Umgebungssensor (Modell Aeotec Multi Sensor 6) kann Temperatur, Feuchtigkeit, Helligkeit, UV-Index, Erschütterungen und Bewegung messen. Die Messwerte für die ersten vier Funktionen werden auf dem Dashboard gezeigt.<br>Erschütterungsmessungen sollen (laut Hersteller) dazu helfen, zu erkennen, ob der Sensor absichtlich oder unabsichtlich entfernt wurde oder heruntergefallen ist.
72
+</td>
73
+</tr>
74
+<tr>
75
+<td>smarte Steckdosen ("Shellies")</td>
76
+<td>
77
+
78
+![image](uploads/0307b9b8fd0d2bf7a016bc53d1276c35/image.png)
79
+</td>
80
+<td>Die smarten Steckdosen können über das lokale Netzwerk geschalten werden, und je nach verbautem Modell auch den Stromverbrauch messen. Auf diese Art wird zum Beispiel das Küchenlicht geschalten.</td>
81
+</tr>
82
+<tr>
83
+<td>Wärmekamera</td>
84
+<td>
85
+
86
+</td>
87
+<td>Die Wärmekamera bietet eine möglichkeit die Anwesenheit von Personen und eventuelle Stürze zu erkennen, ohne so sehr in die Privatsphäre einzugreifen wie eine normale Kamera. Die Auflösung ist auf 32x24 Pixel begrenzt.</td>
88
+</tr>
89
+</table>
90
+
91
+Beispielfoto der Sturzkamera:
92
+
93
+![image](uploads/fc29cdef4a1c8bf52f749b525dd139ee/image.png)
... ...
\ No newline at end of file
smart_home/Ger\303\244testeuerungen.md
... ...
@@ -0,0 +1,148 @@
1
+Um bestimmte Prozesse wie die Anmeldung, die bei allen Gerätesteuerungen gleich sind, zu vereinfachen, gibt es eine Art kleine JavaScript und Python 'Bibliothek'. So wird es etwas einfacher, eine Gerätesteuerung für ein neues Gerät zu schreiben. In diesem Artikel werden die Bibliotheken beschrieben. Die JS und Python Versionen sind ähnlich aufgebaut, werden aber etwas unterschiedlich verwendet.
2
+
3
+#### Init
4
+
5
+Besonders für die Gerätesteuerungen ist, dass sie sich mit einem Gerätenamen anmelden. Pro Gerätename kann sich nur ein laufendes Skript anmelden, um sich bei den Daten in den Kanälen nicht in die Quere zu kommen. Das ist ein Problem beim Kühlschrank, da dort mehrere Skripte (mehrere Raspis) laufen, die aber alle den Kühlschrank Kanal verwenden. Aus diesem Grund kann der Gerätename z.B. als `kuehlschrank.kameras.innen` angegeben werden. Dann wird der Kanal `kuehlschrank` verwedet, aber Daten werden immer geschrieben in:
6
+
7
+```javascript
8
+{ // Kanal `kuehlschrank`
9
+ "kameras": {
10
+ "innen": { /* Daten hier */ }
11
+ }
12
+}
13
+```
14
+
15
+# Python
16
+
17
+```python
18
+# Threads sind nicht zwingend notwendig, aber praktisch falls es sich
19
+# um ein Skript mit Main-Loop handelt.
20
+from threading import Event, Thread
21
+exit_event = Event()
22
+
23
+# Import: Die Datei liegt in `geraete/interface.py` und kann so von Gerätesteuerungen
24
+# in einem Unterordner davon importiert werden
25
+import sys
26
+sys.path.append("..")
27
+import interface as smart_home
28
+
29
+@smart_home.init("fenster")
30
+def init(_config):
31
+ # ... Initialisierung alle Variablen anhand der Config, die
32
+ # hier mitgegeben wird. Diese Funktion muss als einziges immer
33
+ # vorhanden sein.
34
+
35
+
36
+@smart_home.on_quit
37
+def on_quit():
38
+ # ... Code, der ausgeführt werden soll oder muss, wenn das Skript
39
+ # beendet werden soll (z.B. beim Reset). Zum Beispiel kann hier
40
+ # ein Event ausgelöst werden, das einen parallelen Thread stoppt:
41
+ exit_event.set()
42
+
43
+
44
+@smart_home.on("shellies")
45
+def shellies(data):
46
+ # ... Diese Funktion wird aufgerufen, wenn Daten im Kanal `shellies`
47
+ # geupdated wurden. Der Kanal wird automatisch abboniert.
48
+
49
+
50
+@smart_home.on("fenster:mein-event")
51
+def handler(arg1, arg2):
52
+ # ... Handler für das Event `fenster:mein-event`. Der Kanal wird
53
+ # automatisch abboniert sofern notwendig.
54
+
55
+ # Sollte der Handler zum Beispiel neue Daten schreiben wollen,
56
+ # geht das mit der Funktion `update_data()`. Das JS Object im
57
+ # Argument wird mit dem im Ziel gemerged. Z.B. vorher/nachher:
58
+ # "fenster": {"offen": False, "fehler": False}
59
+ smart_home.update_data({"offen": True})
60
+ # "fenster": {"offen": True, "fehler": False}
61
+
62
+ # Bilder oder andere Dateien können über `update_cache()` in den
63
+ # Server cache geladen werden:
64
+ update_cache(fname, url, callback)
65
+
66
+
67
+@smart_home.on_activate
68
+def on_activate():
69
+ # ... Wird aufgeführt, wenn das Gerät aktiviert werden soll.
70
+ # Es gibt gleichermaßen wie Funktion `on_deactivate`.
71
+ # Bei deaktivierten Geräten wird automatisch das Empfangen von
72
+ # Events deaktiviert, das heißt darum muss sich das Skript nicht
73
+ # selbst kümmern.
74
+ # Falls ein Gerät nicht wie sonst standardmäßig aktiviert ist,
75
+ # wird `on_deactivate` direkt nach `init` aufgerufen.
76
+
77
+ # Falls die Statusänderung nicht sofort ist, kann der Status
78
+ # auf pending gesetzt werden (und dann später wieder normal):
79
+ update_device_status(True) # pending=True
80
+
81
+
82
+def main():
83
+ pass
84
+
85
+
86
+t = Thread(target=main, daemon=True)
87
+t.start()
88
+
89
+# Baut die Socket.IO Verbindung auf
90
+smart_home.connect()
91
+
92
+# Beendet das Programm, wenn der Thread sich beendet
93
+t.join()
94
+smart_home.disconnect()
95
+```
96
+
97
+# JS
98
+
99
+```javascript
100
+// Import (relativ aus einem Unterordner in `geraete`)
101
+const smartHome = require("../interface.js");
102
+
103
+var config;
104
+
105
+
106
+smartHome.init("sensfloor", (_config) => {
107
+ // ... Initialisierung alle Variablen anhand der Config, die
108
+ // hier mitgegeben wird. Diese Funktion muss als einziges immer
109
+ // vorhanden sein.
110
+ config = _config;
111
+
112
+ // `updateData()` schreibt Daten in den Kanal des Geräts.
113
+ // Damit kann zum Beispiel hier direkt beim Init schon was
114
+ // geschrieben werden.
115
+ smartHome.updateData({"verbunden": null});
116
+});
117
+
118
+// Anm.: In der JS Version braucht es kein onQuit, das Hilfsskript kann
119
+// sich selbst um das Beenden kümmern.
120
+
121
+smartHome.on("sensfloor", (data) => {
122
+ // ... Wird aufgerufen, wenn Daten im Kanal `sensfloor` geupdated werden.
123
+ // Der Kanal wird, falls nötig, automatisch abboniert.
124
+})
125
+smartHome.on("sensfloor:mein-event", (arg1, arg2) => {
126
+ // ... Genauso wie Datenupdates können auch Handler für eigene Events
127
+ // registriert werden. Der Kanal wird automatisch abboniert.
128
+
129
+ // Falls Bilder oder andere Dateien in den Cache geladeb werden sollen,
130
+ // geht das mit `updateCache()`:
131
+ updateCache(fname, url, callback);
132
+});
133
+
134
+// Auf diese Art kann benutzerdefinierter Code ausgeführt werden, wenn
135
+// das Gerät aktiviert wird. Bei deaktivieren Geräten werden automatisch
136
+// keine Events mehr empfangen. Geräte sind standarmäßig aktiviert, das
137
+// kann über die Config aber geändert werden. In dem Fall wird direkt
138
+// nach dem Aufruf von `init()` hier `onDeactivate()` aufgerufen.
139
+smartHome.onActivate(() => {
140
+ // Falls eine Statusänderung nicht sofort ist, kann der Status
141
+ // auf pending (und später wieder auf normal) gesetzt werden:
142
+ updateDeviceStatus(true); // pending=true
143
+});
144
+smartHome.onDeactivate(sensFloorOff); // Fürs Deaktivieren gleichermaßen
145
+
146
+// Anders als in der Python Version, wird in der JS Version mit dem Aufruf von `init`
147
+// direkt die Verbindung aufgebaut.
148
+```
... ...
\ No newline at end of file
smart_home/Grundlagen-der-API.md
... ...
@@ -0,0 +1,304 @@
1
+Die API des smart-home-control Servers wird von allen Gerätesteuerungen und Interfaces/Apps verwendet, die im Smart Home angebunden sind. Sie basiert auf [Socket.IO](https://socket.io/), das selbst wiederum auf WebSockets aufbaut. Damit können, anders als bei HTTP, asynchron in beide Richtungen jederzeit Nachrichten geschickt werden.
2
+
3
+Alle Nachrichten in Socket.IO werden mit `socket.emit()` verschickt. Das erste Argument ist die Art von Event/Nachricht, die geschickt werden soll. Danach folgen alle zugehörigen Argumente. Als letztes kann optional ein Callback gegeben werden, über den der Empfänger direkt auf den Sender antworten kann. Zum Beispiel:
4
+
5
+```python
6
+socket.emit("cache:update", fname, url, callback) // JS
7
+socket.emit("cache:update", (fname, url), callback=callback) # Python
8
+```
9
+
10
+Nachrichten gehen immer vom Client zum _smart-home-control_ Server oder umgekehrt, nie direkt zwischen den Clients. Nachrichten vom Client zum Server können vom Server aber an einen oder mehrere Clients weitergeleitet werden.
11
+
12
+# Kanäle
13
+
14
+Zur Trennung der Funktionen im Smart Home, ist ein wesentlicher Teil des _smart-home-control_ Servers die Bereitstellung von Kanälen. Es gibt spezielle Kanäle des Server (z.B. `status` oder `rollen`), gerätespezifische Kanäle (z.B. `mikrofon`) und Plugin-Kanäle (z.B. `sturzalarm`).
15
+
16
+An sich kann jeder Client Daten in einem Kanal lesen und schreiben, oder Event darin senden und empfangen. In der Praxis hat aber jeder Kanal einen (bzw. in Ausnahmefällen mehrere, z.B. beim Kühlschrank) Verantwortlichen. Das kann der Server selbst, eine Gerätesteuerung, oder ein Plugin sein. Der Verantwortliche schreibt bzw. updatet Daten im Kanal und stellt Events bereit. Alle anderen Clients lesen die Daten aus einem Kanal und lösen Events aus.
17
+
18
+Konkret schaut das zum Beispiel so aus (als exemplarisches Beispiel):
19
+
20
+<table>
21
+<tr>
22
+<td>
23
+
24
+Client 1:
25
+
26
+```javascript
27
+// Der erste Client ist zum Beispiel eine
28
+// Gerätesteuerung, die, wenn ein Event ausgelöst
29
+// wird, eine Messung durchführt und dann die
30
+// Daten in einen Kanal schreibt.
31
+const { io } = require("socket.io-client");
32
+var socket = io("<server address>");
33
+
34
+// Kanäle müssen nicht registriert werden, aber
35
+// um auf dem Kanal Events zu empfangen, müssen
36
+// wir ihn abbonieren:
37
+socket.emit("sub", "mein-kanal");
38
+
39
+// Wir können bei Socket.IO ein Handler für
40
+// das Ereignis "aktualisieren" im Kanal
41
+// "mein-kanal" registrieren.
42
+socket.on("mein-kanal:aktualisieren", () => {
43
+ var messwert = messungDurchfuehren();
44
+ socket.emit("put", "mein-kanal", {
45
+ "messwert": messwert
46
+ });
47
+});
48
+```
49
+</td>
50
+<td>
51
+
52
+Client 2:
53
+
54
+```javascript
55
+// Der zweite Client ist ein Display, das die
56
+// Daten anzeigt, und wenn man auf "aktualisieren"
57
+// klickt, eine neue Messung auslöst.
58
+
59
+const { io } = require("socket.io-client");
60
+var socket = io("<server address>");
61
+
62
+// Auch der andere Client muss den Kanal abbonieren,
63
+// allerdings nur um Datenupdates mitzubekommen,
64
+// nicht um Events verschicken zu können:
65
+socket.emit("sub", "mein-kanal");
66
+
67
+// Beim Client gibt es einen Handler für neue Daten:
68
+socket.on("mein-kanal", (daten) => {
69
+ console.log(
70
+ "Der neue Messwert ist: ",
71
+ daten.messwert
72
+ );
73
+});
74
+
75
+// Sollten beim Start von Client 2 schon Daten im
76
+// Kanal sein, wird mit "sub" bereits einmal der
77
+// aktuelle Stand geschickt.
78
+
79
+// Abschließend können wir die Aktualisierung mit
80
+// dem Event von Client 1 auslösen:
81
+function onClickOnUpdate() {
82
+ socket.emit("mein-kanal:aktualisieren");
83
+}
84
+```
85
+</td>
86
+</tr>
87
+</table>
88
+
89
+## Dokumentation
90
+
91
+Die Dokumentation der API und Kanäle ist in zwei Teile aufgeteilt:
92
+
93
+* [smart-home-control](smart-home-control): Server API und spezielle Kanäle
94
+* [smart-home-control APIs](smart-home-control%20APIs): APIs der Gerätesteuerungen und Plugins
95
+
96
+# Beispiele
97
+
98
+## Steckdosen mit Sprachsteuerung umschalten
99
+
100
+Ein häufiger Vorhang im Smart Home ist das Ein-/Ausschalten von Steckdosen. Gesteuert werden die Steckdosen von der Gerätesteuerung für alle Shelly Geräte. Um aber Priorierung zu ermöglichen (z.B.: Die Sprachsteuerung kann das automatische Ausschalten des Küchenlichts überschreiben, wenn man die Küche verlässt), gibt es ein eigenes Plugin, das die Steckdosen nochmal zusätzlich abstrahiert.
101
+
102
+In diesem Beispiel geht es erstmal nur darum, wie die Sprachsteuerung das Küchenlicht über die zugehörige Steckdose einschalten kann. Der relevante Kanal zum Mikrofon ist `mikrofon`. Spricht man ins Mikrofon, wird der aktuell erkannte Text in Echtzeit in diesem Kanal geupdated:
103
+
104
+```javascript
105
+{
106
+ "text": "Schalte das", // Text wird kontinierlich während des Sprechens geupdated
107
+ "ausgefuehrt": false,
108
+ // ... Weitere Felder, die uns hier nicht interessieren
109
+}
110
+```
111
+
112
+Updates erfolgen mithilfe der API Funktion `put`, also:
113
+
114
+```javascript
115
+socket.emit("put", "mikrofon", {"text": "Schalte das", ...})
116
+```
117
+
118
+Bei jedem Update werden alle Clients benachrichtigt, die diesen Kanal abboniert haben. Zum Abbonieren gibt es die API Funktion `sub`:
119
+
120
+```javascript
121
+socket.emit("sub", "mikrofon");
122
+socket.on("mikrofon", (data) => { /* Handler für geupdatete Mikrofondaten */ });
123
+```
124
+
125
+Im konrekten Beispiel ist ein Handler in der Konfiguration (`config.js`) gegeben. Einfache Wenn-Dann Verhalten können darin etwas einfacher deklariert werden. Zum Beispiel muss man sich dort nicht um das Abbonieren kümmern. Der Handler wird also bei jeder Änderung der Daten im Kanal `mikrofon` ausgeführt. Jedes mal überprüft er den Text auf Stichwörter. Kommen die Wörter "Küche" und "an" oder "ein" vor, wird das Küchenlicht angeschalten.
126
+
127
+Dazu wird über die API das Event `steckdosen:anschalten` ausgelöst. Das Event ist wie eine Art Funktion des Steckdosen Plugins. Als Argumente werden die genaue Steckdose, sowie die Priorität angegeben (hier: Sprachsteuerung):
128
+
129
+```javascript
130
+socket.emit("steckdosen:anschalten", "kueche-s1", "sprachsteuerung");
131
+```
132
+
133
+Der Server empfängt das Event, und leitet es an alle Clients, die den Kanal `steckdosen` abboniert haben, weiter. Dazu gehört das Steckdosen Plugin, das wie ein Client an das Smart Home angebunden ist. Es reagiert (als einziges) auf das Event, und schaltet über die Gerätesteuerung der Shellies die Steckdose an.
134
+
135
+Gleichzeitig zum `steckdosen:anschalten` Event wird im obigen Handler aus der Konfigurationsdatei das Event `mikrofon:ausgefuehrtSetzen` ausgelöst, das zurück an die Gerätesteuerung des Mikrofons geht:
136
+
137
+```javascript
138
+socket.emit("mikrofon:ausgefuehrtSetzen", data.satz_id) // Die Satz-ID ist in den Daten gegeben
139
+```
140
+
141
+Daraufhin bleibt das Feld `ausgefuehrt` im Kanal `mikrofon` solange auf **true**, bis von der Sprachsteuerung der nächste Satz erkannt wurde. So wird sichergestellt, dass kein Sprachbefehl zweimal ausgeführt wird.
142
+
143
+## Sturzalarm auslösen
144
+
145
+Als etwas umfangreicheres Beispiel, wie ein Ablauf im Smart Home aussieht und wie die Kommunikation über die API abläuft: Das Auslösen eines Sturzalarms. Das Beispiel soll verschiedene Arten von Vorgängen zeigen, die im Smart Home möglich sind. Es hat deshalb so viele Schritte, da mehrere Komponenten beteiligt sind, die miteinander nur über die API kommunizieren. Auf diese Art können einzelne Komponenten (wie z.B. die Push-API) auch in anderen Vorgängen wiederverwendet werden.
146
+
147
+Verwendet werden drei Kanäle mit Daten: `sensfloor` und `sturzkamera` von den jeweiligen Gerätesteuerungen, und `sturzalarm` vom Sturzalarm Plugin. Zu Beginn sind folgende Daten für die Kanäle hinterlegt:
148
+
149
+- Kanal `sensfloor`:
150
+
151
+ ```js
152
+ {
153
+ "an": true,
154
+ "aktivitaet": false,
155
+ "sturzalarm": false, // Dieses Feld interessiert uns, der Rest ist hier nicht relevant
156
+ "bereiche": {
157
+ "irgendwo": false,
158
+ "kueche": false
159
+ },
160
+ "verbundenCareApi": true,
161
+ "verbundenRoomApi": true
162
+ }
163
+ ```
164
+- Kanal `sturzkamera`:
165
+
166
+ ```js
167
+ {
168
+ "bild": "/cache/sturzkamera.jpg?1664182443968", // Dieses Feld interessiert uns hier
169
+ "letzter_timestamp": 1664182443847,
170
+ "modus": "standby",
171
+ "fehler": false
172
+ }
173
+ ```
174
+- Kanal `sturzalarm`:
175
+
176
+ ```js
177
+ {
178
+ "alarm": false,
179
+ "bild": null
180
+ }
181
+ ```
182
+
183
+**Ablauf:**
184
+
185
+1. Der SensFloor erkennt einen Sturzalarm. Über seine eigene API schickt er ein Event an die Gerätesteuerung des SensFloors, die als Node.JS Skript auf dem zentralen Raspberry Pi läuft.
186
+2. Die Gerätesteuerung setzt das Feld `sturzalarm` im Kanal `sensfloor` auf **true**: `socket.emit("put", "sensfloor", {"sturzalarm": true})`
187
+3. In der Smart Home Konfiguration (`config.js`) ist ein sehr einfacher Ereignishandler für den Fall, dass sich Daten im Kanal `sensfloor` verändern. Wird dort `sturzalarm` auf **true** gesetzt, wird das Event `sturzalarm:ausloesen` an den Server geschickt:\
188
+ `socket.emit("sturzalarm:ausloesen")`
189
+4. Der Server schickt das Event weiter an alle Clients, die im Kanal `sturzalarm` sind (anhand des Prefix `sturzalarm:`), unter anderem das Sturzalarm Plugin und die Sturzkamera.
190
+5. (A) Das Sturzalarm Plugin macht zwei Sachen:
191
+ 1. Es updated seine Daten im `sturzalarm` Kanal ¹: `socket.emit("put", "sturzalarm", {"alarm": true})`
192
+ 2. Es löst eine Push-Benachrichtigung aus, indem es das Event `push-api:senden` mit den Details als Argumenten auslöst.\
193
+ `socket.emit("push-api:senden", msg)`\
194
+ Dieses Event wird vom PushAPI Plugin abgefangen, das dann die Benachrichtigungen sendet.
195
+6. (B) Gleichzeitig macht die Sturzkamera ein Bild, was einen kurzen Moment dauert.
196
+ 1. Sobald das Bild gemacht wurde, wird es mit einer speziellen Funktion des Servers auf diesen übertragen. Der Schritt ist notwendig, damit die App von extern auch darauf zugreifen kann, ohne Zugriff auf das interne Smart Home Netzwerk zu haben. Außerdem könnte die direkte Verbindung zur Sturzkamera manchmal zu langsam sein:\
197
+ `socket.emit("cache:update", fname, url, callback)`
198
+ 2. Über den Callback benachrichtigt der Server die Sturzkamera, dass die Übertragung abgeschlossen wurde. Die Sturzkamera updated dann ihre Daten im Kanal mit einem Pfad, wo das Bild abgerufen werden kann:\
199
+ `socket.emit("put", "sturzkamera", {"bild": "<pfad>", ...})`
200
+7. Das Sturzalarm Plugin bekommt das neue Bild mit, weil es den Kanal von der Sturzkamera abboniert hat (`socket.emit("sub", "sturzkamera"); socket.on("sturzkamera", () => {...});`). Es updated das Feld bild in seinem eigenen Kanal, sodass auch die App das Bild erhalten kann.
201
+
202
+¹ Der Grund warum die Information zum Sturzalarm doppelt im `sensfloor` und `sturzalarm` Kanal ist, ist dass man so die Zugriffsrechte besser einschränken kann. Die App braucht so nur Zugriff auf den `sturzalarm` Kanal. Das gleiche gilt auch für den `sturzkamera` Kanal.
203
+
204
+# Spezielle Abläufe
205
+
206
+## Sessions
207
+
208
+Ein wesentliches Element, um die Komplexität etwas zu reduzieren, sind Sessions/Sitzungen. Damit können Client erkennen, wenn der _smart-home-control_ Server neustartet, und sich dann selbst auch neustarten. Zum einen macht es das einfacher, das Smart Home zurückzusetzen. Zum anderen vereinfacht sich so das Synchronisierungsproblem beim Neustart eines Clients oder des Servers. So kann der Client davon ausgehen, dass nur zu seinem allerersten Verbindungsaufbau alle Daten zum Server synchronisiert werden müssen.
209
+
210
+In der API ist das über `session` Nachrichten des Servers umgesetzt.
211
+
212
+```mermaid
213
+sequenceDiagram
214
+ participant Server
215
+ participant Client
216
+ activate Server
217
+ activate Client
218
+ Note over Server, Client: Verbindungsaufbau
219
+ Note left of Server: Bei jedem Verbindungsaufbau <br/> schickt der Server eine zufällige <br/> ID, die gleich bleibt solange der <br/> Server läuft.
220
+ Server-)Client: "session", "123"
221
+ Note right of Client: Client speichert die Session ID, <br/> um Neustarts des Server zu erkennen
222
+ loop Nachrichten-<br>austausch
223
+ Client->>Server:
224
+ Server->>Client:
225
+ end
226
+ deactivate Client
227
+ rect rgb(230, 230, 255)
228
+ Note right of Client: Client startet neu
229
+ activate Client
230
+ Note over Server, Client: Neuer Verbindungsaufbau
231
+ Server-)Client: "session", "123"
232
+ end
233
+ loop Nachrichten-<br>austausch
234
+ Client->>Server:
235
+ Server->>Client:
236
+ end
237
+
238
+ deactivate Server
239
+ rect rgb(230, 230, 255)
240
+ Note left of Server: Server startet neu,<br> generiert neue ID
241
+ activate Server
242
+ Note over Server, Client: Neuer Verbindungsaufbau
243
+ Server-)Client: "session", "456"
244
+ deactivate Client
245
+ Note right of Client: Client erkennt neue Session ID <br> und startet neu
246
+ activate Client
247
+ Note over Server, Client: Neuer Verbindungsaufbau
248
+ Server-)Client: "session", "456"
249
+ Note right of Client: Client speichert neue Session ID
250
+ end
251
+ loop Nachrichten-<br>austausch
252
+ Client->>Server:
253
+ Server->>Client:
254
+ end
255
+ deactivate Client
256
+ deactivate Server
257
+```
258
+
259
+## Gerätesteuerungen
260
+
261
+Einen zusätzlichen Schritt gegenüber anderen Clients beim Verbindungsaufbau haben die Gerätesteuerungen. Sie melden sich mit ihrer Geräte-ID beim Server an. Sie erhalten auf diese Art ihre Konfiguration (die zentral beim Server in einer Datei liegt), und außerdem weiß der Server so, dass sie verbunden sind (was im Gerätestatus angezeigt wird). Pro Geräte-ID kann nur eine Gerätesteuerung verbunden sein.
262
+
263
+```mermaid
264
+sequenceDiagram
265
+ participant Client2 as Gerätesteuerung 2
266
+ participant Server
267
+ participant Client as Gerätesteuerung 1
268
+
269
+ activate Server
270
+ activate Client
271
+ Note over Server, Client: Verbindungsaufbau
272
+ Server-)Client: "session", "123"
273
+ rect rgb(230, 230, 255)
274
+ Client->>Server: "status:anmelden", "kamera"
275
+ Note over Server: Server updated im Gerätestatus,<br> dass das Gerät verbunden ist
276
+ Server-->>Client: callback("erfolgreich", config)
277
+ end
278
+ loop Nachrichten-<br>austausch
279
+ Client->>Server:
280
+ Server->>Client:
281
+ end
282
+
283
+ activate Client2
284
+ Note over Server, Client2: Verbindungsaufbau
285
+ Server-)Client2: "session", "123"
286
+ rect rgb(230, 230, 255)
287
+ Client2->>Server: "status:anmelden", "kamera"
288
+ Note over Server: Gerät mit dieser ID <br> schon verbunden!
289
+ Server-->>Client2: callback("Fehler")
290
+ end
291
+ deactivate Client2
292
+
293
+ loop Nachrichten-<br>austausch
294
+ Client->>Server:
295
+ Server->>Client:
296
+ end
297
+
298
+ Note over Server, Client: Verbindungsabbruch
299
+ deactivate Client
300
+ Note over Server: Server updated im Gerätestatus,<br> dass das Gerät nicht mehr <br> verbunden ist
301
+
302
+ deactivate Server
303
+
304
+```
... ...
\ No newline at end of file
smart_home/Home.md
... ...
@@ -0,0 +1,58 @@
1
+Dies ist die Dokumentation zum Smart Home Space und verwandten Technologien.
2
+
3
+## Für Anwender
4
+
5
+Um zu verstehen, was das Smart Home kann, und wie man es benutzt, gibt es den Bereich für Anwender.
6
+
7
+[Smart Home benutzen](Smart%20Home%20benutzen)
8
+
9
+## Für Admins
10
+
11
+Der Admin Bereich beschreibt, wie man die Geräte im Smart Home einrichtet, neustartet etc.
12
+
13
+[Einrichtung der Raspis](Einrichtung%20der%20Raspis)
14
+
15
+[Geräte im Smart Home](Ger%C3%A4te%20im%20Smart%20Home)
16
+
17
+[Ansible](Ansible)
18
+
19
+## Für Entwickler
20
+
21
+### Smart Home Space
22
+
23
+Die technischen Details im Smart Home können manchmal etwas detailliert und umfangreich sein. In diesen Abschnitt wird hoffentlich möglichst viel davon zu dokumentieren. Die Grundlagen sind in den Artikeln zum Aufbau und der API beschrieben:
24
+
25
+* [Aufbau](Aufbau)
26
+* [Grundlagen der API](Grundlagen%20der%20API)
27
+
28
+Details zur API sind zweigeteilt, einmal die spezifische API des Servers, und die der Gerätesteuerungen etc. Dazu gibt es noch eine Art Bibliothek, die das Entwickeln von Gerätesteuerungen vereinfacht.
29
+
30
+* [smart-home-control (Server-API)](smart-home-control)
31
+* [smart-home-control APIs (Gerätesteuerungen etc.)](smart-home-control%20APIs)
32
+* [Gerätesteuerungen](Gerätesteuerungen)
33
+
34
+Darüber hinaus gibt es noch zu einzelnen Geräten eigene Artikel:
35
+
36
+* [Shelly Steckdosen](Shelly%20Steckdosen)
37
+* [SensFloor](SensFloor)
38
+* [Kühlschrankkamera](K%C3%BChlschrankkamera)
39
+* [Fenstersensor](Fenstersensor)
40
+* [Lichtsteuerung durch Spracherkennung auf Raspi](Lichtsteuerung%20durch%20Spracherkennung%20auf%20Raspi)
41
+
42
+### Fernzugriff
43
+
44
+[Fernzugriff](Fernzugriff%20innerhalb%20MWN)
45
+
46
+[Fernzugriff der API](Fernzugriff%20der%20API)
47
+
48
+### Alte Artikel
49
+
50
+[Funksteckdose über 433MHz von Raspi ansteuern](Funksteckdose%20%C3%BCber%20433MHz%20von%20Raspi%20ansteuern)
51
+
52
+[Server](Server)
53
+
54
+### Verwandte Technologien
55
+
56
+[Vosk: Transkript via Kommandozeile](Vosk%20Transkript%20via%20Kommandozeile)
57
+
58
+[MQTT](MQTT)
... ...
\ No newline at end of file
smart_home/K\303\274hlschrankkamera.md
... ...
@@ -0,0 +1,74 @@
1
+# User Stories
2
+
3
+Bewohner: Ich kann ein Foto meines aktuellen Kühlschrankinhalts auf dem Handy abrufen, wenn ich beim Einkaufen nicht mehr sicher bin, was ich noch zu Hause habe.
4
+
5
+Hauswirtschaftskraft: Ich kann ein Foto des Kühlschrankinhalts abrufen und so die Einkäufe planen, ohne vorher zum Klienten zu müssen. Ich kann anhand von Fotos nachsehen, wann was aus dem Kühlschrank genommen wurde, und so Aufschluss über die Ernährungsgewohnheiten des Klienten erhalten.
6
+
7
+
8
+# Computer, Kamera und Stromversorgung
9
+
10
+Für diese Aufgabe reicht ein Raspberry Pi Zero. Als Kamera empfiehlt sich die Zero Cam mit 120° Blickwinkel, um möglichst viel vom Kühlschrank in den Blick zu kriegen. Da die Kosten gering sind, kann dies auch mehrfach verbaut werden, z. B. zwei mal in die Tür, um den Hauptraum aufzunehmen, und einmal oben in den Hauptraum, um die Inhalte der Tür aufzunehmen.
11
+Die Stromversorgung wird während der Entwicklungs- und Testphase über Power Banks gewährleistet. Bewährt sich der Kühlschrank mit diesen Kameras, so kann über einen Anschluss an die Stromversorgung des Kühlschranks nachgedacht werden, wobei zu prüfen ist, was das für die Brandsicherheit und für den Versicherungsschutz im Schadensfalls bedeuten würde.
12
+
13
+# Sensoren
14
+
15
+Grundsätzlich gibt es viele Möglichkeiten, das Öffnen des Kühlschranks zu erfassen. Hier die bisherigen Erfahrungen:
16
+
17
+## Bewegungssensor
18
+
19
+Den Versuch mit dem analogen PIR-Sensor HC-SR501 war noch nicht erfolgreich (meldet immer Bewegung; Ursache unbekannt).
20
+
21
+## Helligkeitssensor
22
+
23
+Mit dem digitalen Helligkeitssensor BH1750 sind die Erfahrungen gut. Verkabelung: (hier noch Bild/Skizze einfügen). I2C muss als Interface aktiviert sein (Raspi-Config). Test, dass der Sensor angesprochen werden kann:
24
+```
25
+i2cdetect -y 1
26
+```
27
+sollte etwas in dieser Art ausgeben:
28
+```
29
+ 0 1 2 3 4 5 6 7 8 9 a b c d e f
30
+
31
+00: -- -- -- -- -- -- -- -- -- -- -- -- --
32
+10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
33
+20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- --
34
+30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
35
+40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
36
+50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
37
+60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
38
+70: -- -- -- -- -- -- -- --
39
+```
40
+Falls der Sensor einen Wackelkontakt hat, kann man ihn mit einem Gummiband in der Position fixieren, in der er Kontakt hat.
41
+
42
+Da es bei geschlossenem Kühlschrank zappenduster ist (höchstens bis auf das Leuchten einer kleinen LED am Raspi), kann anhand der Helligkeit zuverlässig festgestellt werden, ob der Kühlschrank offen ist. Herumprobieren muss man allerdings damit, wann man Fotos aufnimmt, um ein Bild zu kriegen, das weder verwackelt ist noch die Hand des Bewohners mit aufnimmt und so einen Teil des Regals verbirgt. Das wäre vielleicht mit einem Bewegungs- oder Abstandssensor genauer möglich.
43
+
44
+## Abstandssensor
45
+Der Abstandssensor hat den Vorteil, dass man auch den (ungefähren) Öffnungswinkel der Kühlschranktür ermitteln kann. Konkret verwenden wir diesen Sensor: https://www.pololu.com/product/3416 angesteuert mit einer modifizierten Version von https://github.com/ned14/VL53L3CX_rasppi.
46
+Die Modifikation war vor allem deswegen nötig, weil das Beispiel-Skript vom Hersteller Probleme macht, falls man es im falschen Moment stoppt und dann wieder startet.
47
+
48
+Der Sensor liefert drei Werte:
49
+- `D`: Der Abstand in mm.
50
+- `ambient`: Ein grober Helligkeitswert, ähnlich wie der Helligkeitssensor oben.
51
+- `signal`: Die reflektierte Signalstärke.
52
+
53
+Messkurve (Achtung, sehr grob geschätzte Winkel!):
54
+
55
+![kalibrationskurve](uploads/2cfafbf7aeab00b220715018611d0470/kalibrationskurve.png)
56
+
57
+Nachdem die Kurve leider nicht linear ist, ist die Auswertung der Messdaten etwas komplizierter und fehleranfällig, vor allem im Bereich um die 20°. Hier kann man nur mit der Helligkeit zwischen links und rechts dem Tiefpunkt unterscheiden. Aber die Helligkeit hängt stark von der Umgebung ab, das heißt die kann man nicht vorkalibrieren. Aktuell wird versucht beim Öffnen dynamisch ein Wert zu ermitteln, was so mittelmäßig klappt (Es hängt davon ab, wie schnell man die Tür öffnet). Im wirklich wichtigen Bereich von 20-90° funktioniert die Erkennung aber ganz gut.
58
+
59
+# Kamera
60
+Die Kameras werden mit dem 'neuen' libcamera Stack angesteuert (nicht dem alten raspi-vid etc.). Die größte Schwierigkeit liegt darin, den besten Zeitpunkt für ein Foto zu erwischen. Weil Einzelbildaufnahmen zu ungenau getimed werden können, wird ab dem Öffnen ein Video aufgezeichnet. Sobald die Zür zu gemacht wird, wird anhand einer Score das beste Frame ermittelt und aus dem Video extrahiert. Weil die Pi Zeros sehr leistungsschwach für Video- und Bildverarbeitung sind, dauert das ggf. ein paar Sekunden. Die Score wird aus dem Winkel, der Winkelgeschwindigkeit (als Ableitung des Winkels über die Zeit), und dem Zeitpunkt relativ zum Schließen der Tür berechnet.
61
+
62
+## Bilderkennung
63
+Mit einfacher Bilderkennung wäre es möglich, bestimmte Objekte automatisch im Kühlschrank zu erkennnen (und zählen) zu können. Das könnte zum Beispiel in Form einer Liste in einer (Web)App erscheinen.
64
+
65
+Nach ein wenig experimentieren hat sich bisher gezeigt, als wäre "klassische" Bilderkennung unter Berücksichtigung der Rechenleistung des Raspi Zero noch am besten, um Objekte zu lokalisieren und zu zählen. Beispiel:
66
+
67
+| mit Konturerkennung basierend auf Saturation & Value | mit einem [neuronalen Netz](https://tfhub.dev/google/object_detection/mobile_object_localizer_v1/1) |
68
+| ------ | ------ |
69
+| ![out-0](uploads/1a0fefa95ee518c26b14bd15864c364e/out-0.png) | ![cam1-1b-detect](uploads/899228324ce3d96a7e7d6539b642f3e4/cam1-1b-detect.png) |
70
+| ![out-2](uploads/9bc19e0e436940d3222ce8149a382170/out-2.png) | ![carrots-192-detect-2](uploads/4e9b78cbcfe7aafba204be5f69ed88b4/carrots-192-detect-2.png) |
71
+| Laufzeit <1ms am Laptop | Laufzeit 41ms am Laptop |
72
+
73
+
74
+Die Erkennung selbst funktioniert aber mit neuronalen Netzen bereits ganz gut.
... ...
\ No newline at end of file
smart_home/Lichtsteuerung-durch-Spracherkennung-auf-Raspi.md
... ...
@@ -0,0 +1,86 @@
1
+# Hardware
2
+
3
+Mikrofon und USB-Soundkarte. (Alternativen wären Hat-Soundkarte wie z. B. HiFiBerry DAC ADC Pro; ist gekauft aber noch nicht eingerichtet; auch Sound-Eingabe von Netzwerk-Mikro der Medientechnik könnte interessant sein.)
4
+
5
+
6
+# Software
7
+
8
+## Mikro konfigurieren
9
+
10
+USB-Mikro sollte eigentlich Plug and Play sein, also gleich nach Anschließen (ggf. Neustart) durch
11
+```
12
+arecord -l
13
+```
14
+als verfügbares Aufzeichnungsgerät gefunden und genutzt werden können. Falls nicht (nochmal mit frischer SD-Karte zu prüfen): in der Konfigurationsdatei
15
+```
16
+sudo nano /home/pi/.asoundrc
17
+```
18
+herumpfuschen; aktuell funktionierende Konfiguration ist
19
+```
20
+pcm.!default {
21
+ type asym
22
+ playback.pcm {
23
+ type plug
24
+ slave.pcm "output"
25
+ }
26
+ capture.pcm {
27
+ type plug
28
+ slave.pcm "input"
29
+ }
30
+}
31
+pcm.output {
32
+ type hw
33
+ card 0
34
+}
35
+pcm.input {
36
+ type plug
37
+ slave {
38
+ pcm "hw:2:0"
39
+ }
40
+}
41
+ctl.!default {
42
+ type hw
43
+ card 0
44
+}
45
+```
46
+wobei der `slave` im `pcm.input` auf `pcm "hw:2:0"` eingestellt ist weil alsa die USB-Karte in dem Fall als Karte 2, Subgerät 0 registriert hatte.
47
+
48
+### PulseAudio
49
+PulseAudio (das Standard Audio System bei vielen Linux Distributionen) kann auch etwas Rauschentfernung und Echo-Cancellation machen, was die Spracherkennung bei größerem Abstand verbessern sollte.
50
+
51
+Dazu in `/etc/pulse/default.pa` am Ende die Zeilen hinzufügen:
52
+```
53
+# Denoise
54
+load-module module-echo-cancel source_name=denoised aec_method=webrtc aec_args="analog_gain_control=0 digital_gain_control=1"
55
+
56
+set-default-source denoised
57
+
58
+# 65536 is 100%
59
+set-source-volume denoised 98304
60
+```
61
+
62
+Und dann PulseAudio neustarten mit `pulseaudio -k` (Falls es da einen Fehler gibt, dass der Prozess nicht gefunden wurde: `pulseaudio -D`). Per default sollte dann das Audio mit Rauschentfernung verwendet werden.
63
+
64
+[Hauptquelle](https://askubuntu.com/questions/18958/realtime-noise-removal-with-pulseaudio) und
65
+[Quelle zur Lautstärkeneinstellung](https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/224) (Auf der Hauptquelle verlinkt).
66
+
67
+## Spracherkennung
68
+
69
+### Installation
70
+
71
+Vosk installieren wie auf https://alphacephei.com/vosk/ dokumentiert
72
+
73
+### Funksteckdose steuern
74
+
75
+Die Sprachsteuerung für die Funksteckdose am Licht wird auf dem Raspi mit
76
+```
77
+cd /home/pi/vosk-api/python/example/
78
+python3 test_microphone-modJS.py -r 48000
79
+```
80
+aktiviert. Ohne die Option `-r 48000` verwendet das Python-Modul soundmodule die falsche Bitrate und macht die Aufzeichnung für Mensch und Maschine unverständlich. Will man den Befehl aus einem anderen Verzeichnis heraus ausführen, muss man den Pfad zum Sprachmodell spezifieren:
81
+
82
+```
83
+python3 /home/pi/vosk-api/python/example/test_microphone-modJS.py -r 48000 --model /home/pi/vosk-api/python/example/model/
84
+```
85
+
86
+Im Terminal-Fenster, in dem die Sprachsteuerung gestartet wurde, wird angezeigt, was sie erkennt. Enthält die erkannte Äußerung die Folge "licht an" oder "licht ein", so wird eingeschaltet; enthält sie "licht aus", so wird ausgeschaltet (mehr ist in `test_microphone-modJS.py` gegenüber dem Original `test_microphone.py` nicht geändert).
... ...
\ No newline at end of file
smart_home/MQTT.md
... ...
@@ -0,0 +1,50 @@
1
+MQTT ist ein einfaches und weit verbreitetes Protokoll für IoT / Smart Home. Es besteht aus einem Server (oder "Broker"), und Clients.
2
+
3
+Es gibt Kanäle ("Topics"), auf denen man abbonieren und Nachrichten empfangen kann, und Nachrichten senden kann.
4
+
5
+# Server
6
+Als Server läuft auf dem smart-home-server die Open Source Software [Mosquitto](https://github.com/eclipse/mosquitto).
7
+
8
+### Installation
9
+Bei Raspis ganz einfach mit:
10
+```bash
11
+sudo apt install mosquitto
12
+```
13
+
14
+Standarmäßig läuft der Server dann auf Port 1883.
15
+
16
+User mit Passwort lassen sich mit [mosquitto_passwd](https://mosquitto.org/man/mosquitto_passwd-1.html) einrichten:
17
+```bash
18
+sudo mosquitto_passwd -c /etc/mosquitto/passwd <user>
19
+```
20
+und dann das Passwort zweimal eintippen. Ein User kann von mehreren Geräten verwendet werden.
21
+
22
+### Logging
23
+Detaillierte Logs kann man in der Konfiguration in `/etc/mosquitto/mosquitto.conf` mit
24
+```
25
+log_type all
26
+```
27
+aktivieren (standardmäßig aus, damit die Logs nicht zu groß werden).
28
+
29
+Den Log kann man dann in Echtzeit mitverfolgen mit:
30
+```bash
31
+sudo tail -f /var/log/mosquitto/mosquitto.log
32
+```
33
+
34
+# Clients
35
+## CLI
36
+Es gibt einen CLI client, den man auf Raspis installieren kann mit:
37
+```bash
38
+sudo apt install mosquitto-clients
39
+```
40
+
41
+Neue Nachrichten auf einem Topic empfangen mit:
42
+```bash
43
+mosquitto_sub -t "name/des/topic" -v
44
+```
45
+(Die Slash scheinen nur eine Schreibweise zu sein, aber haben scheinbar keine weitere Bedeutung)
46
+
47
+Und Nachrichten senden mit:
48
+```bash
49
+mosquitto_pub -t "name/des/topic" -m "nachricht"
50
+```
... ...
\ No newline at end of file
smart_home/Referendarbefragung.md
... ...
@@ -0,0 +1,28 @@
1
+## Ideensammlung: Gespräch mit Simons ex-Mitreferendaren, die jetzt an Schulen sind ##
2
+
3
+### 1. Kurzvorstellung TAT4.0 Smart Home ###
4
+
5
+Was bisher im Smart Home Space aufgebaut wurde und wie es genutzt wurde:
6
+- Technische Ausstattung
7
+- Zielgruppe: Studierende berufliches Lehramt aller Fachrichtungen
8
+- Lernziele: Mündigkeit in Zeiten der digitalen Transformation, durch Begriffswissen und Handlungskompetenz; berufsfeldübergreifende Zusammenarbeit
9
+- Unterrichtsmethode: Rollenspiel
10
+- Lehrplanverortung: a) technische Aspekte, b) Lernziele unserer Rollenspiele
11
+Bereit halten für Nachfragen: Industrie 4.0 Space
12
+
13
+### 2. Was passiert an der Schule, was fürs Projekt interessant sein könnte? ###
14
+
15
+Frage nach Lernfeld cyber-physische Systeme
16
+Zusammenarbeit mit anderen Fachbereichen?
17
+Erfahrung mit Rollenspielen als Unterrichtsmethode?
18
+
19
+
20
+
21
+### 3. Was passiert bei uns im Projekt, was für die Schule interessant sein könnte? ###
22
+
23
+Übertragbarkeit vom Smart Home Rollenspiel?
24
+
25
+### 4. Mögliche Zusammenarbeit ###
26
+
27
+z. B. 90min Lerneinheit: Technische Voraussetzungen schaffen, Unterrichtsvorbereitung durch Rollenkarten unterstützen, Unterricht beobachten
28
+
smart_home/SensFloor.md
... ...
@@ -0,0 +1,63 @@
1
+# Care API (Gesamtsteuerung)
2
+Zur Care API gibt es eine kleines PDF, das die Grundlagen von dessen Socket.io API dokumentiert. Das heißt hier sind erstmal nur nicht dort dokumentierte Funktionen. Zum Debugging kann man in einem Browser, der WebSockets debuggen kann (z.B. Chrome), schauen was passiert, wenn man Aktionen auf der Care API Weboberfläche ausführt.
3
+
4
+Achtung: Der SensFloor verwendet eine alte Version von Socket.io (Versionen 2.x), die nur mit Clients mit passender Version kompatibel sind.
5
+
6
+### `rooms-state`
7
+Über dieses Event kann man wohl regelmäßig den Raum-Status empfangen. Die Daten schauen zum Beispiel so aus:
8
+```js
9
+[
10
+ {
11
+ activeAlarms: [],
12
+ address: "192.168.178.22:8000",
13
+ autoEnableTimeLeft: 3586,
14
+ connected: true,
15
+ enabled: true,
16
+ falls: 0,
17
+ floor: 1,
18
+ hostname: "c8a000ae",
19
+ lastActivity: 1652447893968,
20
+ lastFall: 1652434557773,
21
+ moving: 1, // Anzahl sich bewegender Personen
22
+ name: "Room 1",
23
+ on: true,
24
+ pastAlarms: [{index: 0, alarmNumber: 1, type: "fall", activationTime: 1652434557715, unattended: true}],
25
+ recalibrating: false,
26
+ room: 1,
27
+ sensfloor: true,
28
+ static: 0, // Anzahl sich nicht bewegender Personen
29
+ unattendedFall: true,
30
+ updateView: true,
31
+ }
32
+]
33
+```
34
+
35
+### `state-new`
36
+Über dieses Event kann man Statusänderungen für Räume empfangen. Man erhält zum Beispiel folgende Daten:
37
+```js
38
+{
39
+ activity: true, // Ob sich Personen auf dem SensFloor befinden
40
+ alarm: false,
41
+ connected: true,
42
+ enabled: true, // Ob der SensFloor an sich an ist (ist auch true falls nur temporär disabled)
43
+ recalibrating: false, // Ob der SensFloor gerade rekalibriert
44
+ roomName: "Room 1",
45
+ roomNumber: 1,
46
+ sensfloor: true,
47
+ tempDisabled: false, // Ob der SensFloor gerade temporär aus ist (schaltet sich nach einiger Zeit selbst wieder ein)
48
+}
49
+```
50
+
51
+Schaltet man den SensFloor ein, läuft am Anfang kurz eine Rekalibrierung, währenddessen ist `enabled` allerdings schon auf *true*. `tempDisabled` (falls davor gesetzt) bleibt aber *true*, bis die Kalibrierung vorbei ist.
52
+
53
+### `enable`
54
+Ein Event, um den SensFloor temporär auszuschalten, oder wieder einzuschalten. Für den einzigen Raum bei uns geht das so:
55
+```
56
+client.emit("enable", "1", "1", true/false)
57
+```
58
+
59
+### `state`
60
+Ein Event, um den SensFloor dauerhaft ein-/auszuschalten. Für den einzigen Raum bei uns geht das so:
61
+```
62
+client.emit("state", "1", "1", true/false)
63
+```
... ...
\ No newline at end of file
smart_home/Server.md
... ...
@@ -0,0 +1,75 @@
1
+# Voraussetzungen
2
+
3
+## Hardware
4
+
5
+Funkschaltung so eingerichtet wie in [Doku](Funksteckdose über 433MHz von Raspi ansteuern) beschrieben
6
+
7
+## Software
8
+
9
+### Node.js Grunlagen
10
+
11
+Node.js installieren (s. https://nodejs.org). An gewünschter Stelle (aktuell `/home/pi/Desktop/nodejs-server`) intialisieren:
12
+```
13
+npm init
14
+```
15
+und als nötige Pakete
16
+```
17
+npm install express
18
+npm install child_process
19
+npm install process
20
+```
21
+hinzufügen. Grundstruktur des node.js-Servers (aktuell `home/pi/Desktop/nodejs-server/server.js`) mit zwei einfachen Tests:
22
+```
23
+const express = require('express');
24
+const {exec} = require('child_process');
25
+const {stderr} = require('process')
26
+
27
+const app=express();
28
+const port=3000;
29
+
30
+app.get('/helloserver',(req,res,next)=>{
31
+ res.send("hello world!");
32
+})
33
+
34
+app.get('/helloshell', (req,res,next)=>{
35
+ exec('touch /home/pi/Desktop/ShellTestSuccess.txt');
36
+ res.send('yay!')
37
+})
38
+
39
+
40
+app.listen(port);
41
+```
42
+Server einschalten:
43
+```
44
+node /home/pi/Desktop/nodejs-server/server.js
45
+```
46
+Zum ausschalten `ctrl + C`.
47
+
48
+
49
+Tests: Ein Gerät im lokalen Netzwerk sollte durch GET-Anfrage an `[IP des Raspi]:3000/helloserver` die Antwort "hello world!" erhalten. Durch GET-Anfrage an `[IP des Raspi]:3000/helloshell` sollte auf dem Desktop des Raspi eine leere Text-Datei namens `ShellTestSuccess.txt` angelegt werden und an das anfragende Gerät die Antwort "yay!" geschickt werden.
50
+
51
+### Lichtsteuerung
52
+Der Server stellt wie folgt Endpunkte bereit, die das An-/Ausschalten des Lichts auslösen:
53
+```
54
+app.get('/lichtan', (req,res,next)=>{
55
+ exec('/usr/local/bin/send 01001 1 1');
56
+ res.send('yay!')
57
+})
58
+
59
+app.get('/lichtaus', (req,res,next)=>{
60
+ exec('/usr/local/bin/send 01001 1 0');
61
+ res.send('yay!')
62
+})
63
+
64
+```
65
+Durch GET-Anfrage an `[IP des Raspi]:3000/lichtan` wird das Licht mit dem Identifikator 01001 1 (vgl. [Doku](Funksteckdose über 433MHz von Raspi ansteuern)) eingschaltet; entsprechend zum Ausschalten und durch Veränderung des Identifikators für andere Funksteckdosen.
66
+
67
+### Foto von Kamera holen
68
+Der folgende Endpunkt setzt das Verzeichnis `/home/pi/Desktop/nodejs-server/photos` voraus.
69
+```
70
+app.get('/photo', (req,res,next)=>{
71
+ exec('raspistill -o /home/pi/Desktop/nodejs-server/photos/test.jpg');
72
+ res.sendFile('/home/pi/Desktop/nodejs-server/photos/test.jps');
73
+})
74
+```
75
+Durch GET-Anfrage an `[IP des Raspi]:3000/photo` wird die Aufnahme eines Fotos auf dem Raspi ausgelöst, das dieser in dem o.g. Pfad ablegt (to do: Zeitstempel, damit die Bilder behalten statt überschrieben werden) und als Antwort an das anfragende Gerät zurückschickt.
smart_home/Shelly-Steckdosen.md
... ...
@@ -0,0 +1,45 @@
1
+# Varianten
2
+- Shelly 1: Verbauter Stecker mit An-/Ausschalt-Funktion
3
+- Shelle 1 PM: Verbauter Stecker mit An-/Ausschalt-Funktion und Leistungsmessung
4
+- Shelly Plug S: "Zwischenstecker" mit An-/Ausschalt-Funktion und Leistungsmesung
5
+
6
+# Einrichtung
7
+### Ersteinrichtung
8
+Die Shellies machen zuerst von sich aus ein Hotspot auf, über den man die anfängliche Einrichtung machen kann (WLAN einrichten). Danach starten sie neu, melden sich im lokalen WLAN an und sind dann jeweils über ihre IP erreichbar.
9
+
10
+### MQTT
11
+Auf dem smart-home-server läuft ein MQTT Server/Broker ([Mosquitto](https://github.com/eclipse/mosquitto)), über den die Shellies ausgelesen und gesteuert werden. Die Einrichtung geht im Shelly Webinterface unter "Internet & Security" -> "Advanced - developer settings" -> "Enable action execution via MQTT".
12
+
13
+Username: `shelly`
14
+Password: `smartshelly`
15
+Server: `192.168.178.20:1883`
16
+
17
+Den Rest bei den Standardeinstellungen lassen.
18
+
19
+# API (MQTT)
20
+[Dokumentation](https://shelly-api-docs.shelly.cloud/gen1/#shelly1-1pm-mqtt)
21
+
22
+Beim Starten melden sich die Shellies bei `shellies/announce` mit ihrer jeweiligen Device ID, unter der sie in MQTT erreichbar sind (Die Device ID steht auch im jeweiligen Shelly Webinterface unter "Settings" -> "Device Info"). Man kann auch ein announce anfordern mit der message `announce` an `shellies/command`:
23
+
24
+```bash
25
+mosquitto_pub -t "shellies/command" -m "announce"
26
+```
27
+(Befehle auf dem smart-home-server)
28
+
29
+Sobald man die Device ID hat, kann man ganz einfach ein-/ausschalten. Z.B. für das Küchenlich:
30
+```bash
31
+mosquitto_pub -t "shellies/shelly1-C45BBE57AB9A/relay/0/command" -m "on"
32
+```
33
+
34
+Die aktuelle Leistung kann dann auch abgerufen werden für die Geräte mit Messgerät. Z.B. für die Küchenmaschine:
35
+```bash
36
+mosquitto_sub -t "shellies/shellies/shelly1pm-98CDAC2FF800/relay/0/power" -v
37
+```
38
+
39
+# API (HTTP)
40
+Die Shellies haben auch eine HTTP API, über die die Shellies auch eingerichtet werden könnten.
41
+Die einfachste Funktion ist die Statusabfrage als JSON unter:
42
+
43
+```
44
+http://<IP>/status
45
+```
... ...
\ No newline at end of file
smart_home/Smart-Home-Control-\342\200\223-Server.md
... ...
@@ -0,0 +1,202 @@
1
+_Diese Seite beschreibt die allgemeine socket.io API, für die Geräte-spezifische siehe:_ [_smart-home-control APIs_](smart-home-control%20APIs)_._
2
+
3
+Der smart-home-control Socket.IO Server ist eine Art zentrales Hub für die Verknüpfungen und Kommunikation im Smart Home. Die Geräte kommunizieren nicht untereinander, sondern immer nur über den smart-home-control Server.
4
+
5
+Im wesentlichen bietet der Server zwei Funktionen:
6
+
7
+1. Der Server bietet "Kanäle", wobei es je Gerät ein Kanal gibt. In diesen Kanäle können Geräte Daten hinterlegen. Immer wenn die Daten aktualisiert werden, werden alle anderen Clients in Echtzeit benachrichtigt.
8
+2. Über die Kanäle gibt es auch ein System, um Events (vergleichbar mit Funktionsaufrufen) an Geräte zu schicken. Events erkennt man am ":" im Namen.
9
+
10
+Darüber hinaus gibt es noch ein paar spezielle Funktionen, die vom Server bereitgestellt werden:
11
+
12
+* Für die Simulation von Rollenspielen gibt es ein Rollen-Management. Damit können die Endgeräte von Personen im Rollenspiel Zugriff auf bestimmte Daten bekommen oder entzogen werden.
13
+* Für Webclients und Kamerabilder gibt es ein Server für statische Dateien. Bei den Kamerabildern geht es vor allem auch um das Cachen/Zwischenspeichern der Bilder, damit diese nicht von den Kameras direkt abgerufen werden müssen. Das ist notwendig für Clients, die von außerhalb auf das Smart Home LAN zugreifen. Darum kümmert sich ein Proxy Server.
14
+* Der Server hat auch ein paar zusätzliche Funktionen für Gerätesteuerungen, um diesen ihre Konfiguration zu schicken und deren Status zu erfassen bzw. Geräte zu (de)aktivieren.
15
+* Für das gesamt Smart Home gibt es auch noch Funktionen zum Zurücksetzen, Neustarten und Herunterfahren.
16
+
17
+Zu Kanälen und Events stehen mehr Details und Beispiele in den [Grundlagen der API](Grundlagen%20der%20API). Zu den anderen Funktionen sind im Folgenden ein paar Beschreibungen.
18
+
19
+[[_TOC_]]
20
+
21
+### Rollen-Management
22
+
23
+Als spezielle Funktion, damit man Rollen einfach konfigurieren kann, gibt es die Möglichkeit, Rollen statt Kanäle zu abbonieren. Rollen haben standardmäßig Zugriff auf bestimmte Kanäle, aber es ist möglich (z.B. von der Steuerungs-App aus), zu ändern, welche Kanäle eine Rolle abboniert hat. Also im Prinzip auf welche Informationen die Rolle Zugriff hat, nur dass das Feature keine Sicherheitsmechanismen hat, sondern nur dem Rollenspiel dient.
24
+
25
+Wird Zugriff auf einen Kanal aktiviert, bekommt der Client den aktuellen Zustand. Wird der Zugriff deaktiviert, wird als Zustand `null` gesendet. Außerdem werden keine Events mehr ausgelöst, wenn der Eventname mit dem zugehörigen Kanalname beginnt.
26
+
27
+Außerdem kann die Rollen-Konfiguration über den speziellen Kanal `rollen` abgefragt werden:
28
+
29
+```js
30
+{
31
+ "nachbar": {
32
+ "name": "Max",
33
+ "rolle": "Nachbar",
34
+ "zugriffe": {
35
+ "sturzalarm": true,
36
+ "kuehlschrank": false,
37
+ }
38
+ },
39
+ // ...
40
+}
41
+```
42
+
43
+### Statische Dateien & Cache
44
+
45
+Läuft der Server unter Port 3030, werden auf drei Pfaden statische Dateien bereitgestellt:
46
+
47
+* [localhost:3030/](http://localhost:3030/) -> Dateien im Ordner `clients`
48
+* [localhost:3030/extern](http://localhost:3030/extern) -> Dateien im Ordner `clients-extern`
49
+* [localhost:3030/cache](http://localhost:3030/cache) -> Dateien im Ordner `cache`
50
+
51
+Der Pfad `/extern` dient dem Proxy Server für Clients, die nicht im Smart Home LAN sind. Dateien in `/cache` können dynamisch hinzugefügt werden. Dazu gibt es die Funktion/das Event `cache:update` (siehe unten).
52
+
53
+### Gerätesteuerungen & -status
54
+
55
+Um die Konfiguration im Smart Home einfacher updaten zu können, liegt die gesamte Konfiguration beim smart-home-control Server. Meldet sich ein Gerät in dem in [Grundlagen der API](Grundlagen%20der%20API) beschrieben Prozess an, erhält es seine Konfiguration. Außerdem updatet der Server im Kanal `status` automatisch, wenn sich das Gerät verbunden hat, oder die Verbindung beendet.
56
+
57
+Über den Kanal `status` können Gerätesteuerungen auch (de)aktiviert werden. Dazu werden die entsprechenden Events an den zugehörigen Client der Gerätesteuerung weitergeleitet.
58
+
59
+### Zurücksetzen, Neustarten, Herunterfahren
60
+
61
+Diese Funktionen dienen speziell dem möglichst einfachen Umgang mit dem Smart Home für Anwender:innen. Damit können die Funktionen einfach als ein Button im Steuerungstablet eingebaut werden. Die Umsetzung von Neustart und Herunterfahren basiert auf Skripten, die von Ansible generiert werden.
62
+
63
+## Client API
64
+
65
+### `get`: Zustand abfragen
66
+
67
+z.B. `socket.emit("get", "fenster")`
68
+
69
+Fordert den Server auf, einmal den aktuellen Zustand im Kanal `fenster` zu senden. Existiert der Kanal (noch) nicht, wird nichts gesendet.
70
+
71
+Bisher wird die Funktion noch nicht verwendet, evtl. ist es daher sinnvoll sie zu entfernen.
72
+
73
+### `sub`: Kanal abbonieren
74
+
75
+z.B. `socket.emit("sub", "mikrofon")`
76
+
77
+Fordert den Server auf, einmal den aktuellen Zustand im Kanal `mikrofon` zu senden, und bei jeder Änderung erneut. Existiert der Kanal (noch) nicht, wird nichts gesendet.
78
+
79
+Das Abbonieren eines Kanals ist außerdem notwendig, um dort Events zu erhalten. (Das ist deswegen, damit das für Rollen einfacher gehandhabt werden kann).
80
+
81
+### `put`: Zustand ändern
82
+
83
+z.B. `socket.emit("put", "fenster", {"offen": true})`
84
+
85
+Setzt den Zustand des Kanals auf das mitgegebene Objekt. Alle Clients, die den Kanal abboniert haben (außer dem Client, der `put` aufruft), werden benachrichtigt. Dabei werden die Objekte gemerged, das heißt falls ein Key im aktuellen Zustand enthalten ist, im gegebenen Objekt aber nicht, bleibt dieser Key und der Wert dazu unverändert.
86
+
87
+Geschützte Kanäle, wie z.B. `status`, können nicht überschrieben werden.
88
+
89
+### Event abfangen
90
+
91
+z.B. `socket.on("steckdose:anschalten", callback)`
92
+
93
+Ruft `callback` mit den Argumenten des Events auf, falls ein Client `steckdose:anschalten` auslöst. Dazu muss der Kanal `steckdose` abboniert sein (immer das was vor dem ersten `:` steht). Mit `once()` statt `on()` wird das Event nur einmal empfangen, danach nicht mehr.
94
+
95
+Aktuell können Clients ein Event auch selbst empfangen, wenn sie es auslösen. Mal schauen, ob das sinnvoll ist.
96
+
97
+### Event auslösen
98
+
99
+z.B. `socket.emit("steckdose:anschalten", <optionale Argumente>)`
100
+
101
+Löst das Event `steckdose:anschalten` bei allen Clients aus, die einen Handler für das Event haben. Der Eventname muss aus zwei mit `:` getrennten Teilen bestehen (um Events von serverseitigen Daten-Updates zu unterscheiden).
102
+
103
+### Rolle abbonieren
104
+
105
+z.B. `socket.emit("rollen:sub", "nachbar")`
106
+
107
+Abboniert als Client die Rolle `nachbar`. Details zur Rolle erhält der Client dann über das Event `rollen:rolle`:
108
+
109
+```json
110
+{
111
+ "name": "Max",
112
+ "rolle": "Nachbar"
113
+}
114
+```
115
+
116
+### Rolle: Kanäle modifizieren
117
+
118
+z.B. `socket.emit("rollen:set", "nachbar", "sturzalarm", false)`
119
+
120
+Stellt den Zugriff auf `sturzalarm` für die Rolle `nachbar` auf `false`.
121
+
122
+### Cache
123
+
124
+z.B. `socket.emit("cache:update", "kamera.jpg", "http://192.168.178.45:3000/photo", callback)`
125
+
126
+Lädt die Datei unter dem zweiten Argument herunter, und stellt sie in `/cache/<fname>` zur Verfügung, wobei `fname` vom ersten Argument gegeben wird.
127
+
128
+Wenn optional ein callback gegeben ist, wird am Ende das callback aufgerufen mit dem Cache-Pfad als relativen (`/cache/datei.jpg?1234`) URL. In allen Fällen wird auch `cache:updated` mit dem gleichen URL als Argument aufgerufen, damit eventuelle Bridges die Datei auch cachen könnten.
129
+
130
+### `status:anmelden`: Gerätesteuerung anmelden
131
+
132
+z.B. `socket.emit("status:anmelden", "fenster", callback)`
133
+
134
+Meldet die Gerätesteuerung anhand des ersten Arguments an. Zu jedem Gerätenamen kann nur eine Gerätesteuerung verbunden sein, um Fehler zu vermeiden. Es können aber mehrere Gerätesteuerungen den gleichen Kanal verwenden. Das ist der Fall beim Kühlschrank, wo die Gerätesteuerung dann zum Beispiel `kuehlschrank.sensor` als Namen im ersten Argument angibt, und dann aber im Kanal `kuehlschrank` schreibt, aber nur im Feld `sensor`, und die Kameras in `kameras`.
135
+
136
+Das zweite Argument ist ein Callback, der mit dem Ergebnis der Anmeldung aufgerufen wird. Falls die Anmeldung geklappt hat, wird zurückgegeben:
137
+
138
+```javascript
139
+{
140
+ erfolgreich: true,
141
+ aktiviert: true, // Ob das Gerät zu Beginn aktiviert sein soll (default: true)
142
+ config: {...} // Die Konfiguration für das Gerät
143
+}
144
+```
145
+
146
+Ansonsten wird im Falle eines Fehlers zurückgeschickt:
147
+
148
+```javascript
149
+{
150
+ erfolgreich: false
151
+}
152
+```
153
+
154
+Der Prozess der Anmeldung ist auch in [Grundlagen der API](Grundlagen%20der%20API "Grundlagen der API") dargestellt.
155
+
156
+### `status:aktivieren`: Gerät aktivieren
157
+
158
+z.B. `socket.emit("status:aktivieren", "mikrofon")`
159
+
160
+Aktiviert die Gerätesteuerung, die zu dem gegeben Namen (in der Regel Name des Kanals) gehört. Dazu wird das Event an den passenden Client weitergeleitet (Der Client der Gerätesteuerung erhält das Event `status:aktivieren` ohne Argument).
161
+
162
+Nur wenn die Gerätesteuerung aktiv ist, verarbeitet sie Events und updatet Daten. Gerätesteuerungen können außerdem eigene Handler für das (De)Aktivieren haben. So kann zum Beispiel das Mikrofon die Spracherkennung starten oder beenden.
163
+
164
+### `status:deaktivieren`: Gerät deaktivieren
165
+
166
+Genauso wie `status:aktivieren`.
167
+
168
+### `status:update`: Gerätestatus updaten
169
+
170
+z.B. `socket.emit("status:update", "sensfloor", true)`
171
+
172
+Über diese API Funktion kann eine Gerätesteuerung selbst den eigenen Status updaten. Aktuell betrifft das nur das Feld `pending`, dessern Wert über das zweite Argument gegeben wird. Mit `pending` kann angegeben werden, dass eine Statusänderung aussteht, aber noch nicht abgeschlossen ist. Zum Beispiel braucht der SensFloor etwas zum Starten, wenn er deaktiviert war und aktiviert wird. Wird das Feld dann wieder auf false gesetzt, ist die Statusänderung abgeschlossen.
173
+
174
+### `extern:anmelden`: Externen Proxy anmelden
175
+
176
+z.B. `socket.emit("extern:anmelden", "<token>", callback)`
177
+
178
+Passt das Token, sendet der Server über das callback die Konfiguration des externen Proxy. Ein Token gibt es deswegen, weil in der Konfiguration API Keys stehen. Die API ist in Anlehung an `status:anmelden` benannt, es wird vom Server aktuell aber nicht getrackt, ob der externe Proxy verbunden ist.
179
+
180
+### `reset`: Smart Home zurücksetzen (Server neustarten)
181
+
182
+Startet den smart-home-control Server neu, woraufhin eine neue Session ID generiert wird. Daraufhin starten auch alle Clients neu (dargestellt in [Grundlagen der API](Grundlagen%20der%20API "Grundlagen der API")). Beim Neustart werden alle Daten gelöscht.
183
+
184
+### `neustart`: Smart Home neustarten
185
+
186
+Startet über ein Skript, das von Ansible generiert wird, alle Raspis im Smart Home neu.
187
+
188
+### `herunterfahren`: Smart Home herunterfahren
189
+
190
+Fährt über ein Skript, das von Ansible generiert wird, alle Raspis im Smart Home herunter.
191
+
192
+# Plugins
193
+
194
+Mit Plugins können dem Server zusätzliche, Kanal-spezifische (und damit meistens Gerät-spezifische) Funktionen hinzugefügt werden.
195
+
196
+Das kann insbesondere sein, dass man Geräte ein- und ausschalten kann, was naturgemäß ein ausgeschaltetes Gerät nicht selbst machen kann. Aber zum Beispiel die WebPush Benachrichtigungen sind auch über ein Plugin (mit zugehörigem Kanal `push-api`) implementiert.
197
+
198
+Plugins liegen in `smart-home-control/plugins.js`, wo auch ein Template für ein neues Plugin enthalten ist.
199
+
200
+# Verhalten im Falle eine Reconnects
201
+
202
+Falls die Verbindung beim ersten Start geklappt hat, kümmert sich Socket.io selbst darum, verlorene Verbindungen wieder aufzubauen. Wenn das passiert, wird `connect` im Client nochmal ausgelöst. Man muss dann allerdings nur nochmal `sub` an den Server senden, aber nicht nochmal Socket.io Eventhandler (`socket.on()`) initialisieren. Alternativ kann man mit `socket.removeAllListeners("eventname")` zu Beginn jedes `connect` die Handler zurücksetzen.
... ...
\ No newline at end of file
smart_home/Smart-Home-benutzen.md
... ...
@@ -0,0 +1,38 @@
1
+# Vorbereitungen
2
+
3
+| Schritt | Foto |
4
+| ------ | ------ |
5
+| **Smart Home neustarten:** Der Computer auf dem weißen Regal hat immer den Browser geöffnet. Dort den Reiter bwz. Lesezeichen "Smart Home Control" öffnen. Dann Steuerung -> Smart Home neustarten. (Falls der Browser im Vollbildmodus ist, F11 drücken um den Reiter wechseln zu können.) | ![IMG_20240222_180121_525](uploads/ffc117f915bcd14423142a2ae78c42af/IMG_20240222_180121_525.jpg) |
6
+| **Kühlschrank-Kameras einschalten:** Die Powerbanks aus dem weißen Regal, unteres geschlossenes Fach herausnehmen, einschalten, ins oberste Fach der Kühlschranktür legen und dort alle USB-Kabel anschließen sodass die Computer im Kühlschrank Strom haben. | ![IMG_20231017_103333_173](uploads/8318191f7eb3dec3f4444d2245757c0c/IMG_20231017_103333_173.jpg) |
7
+| (Optional) **iPad zur Steuerung:** Ein iPad ins Smart Home WLAN: ssid `Smart Home`, Passwort `05808161781375379960`, und dort die Smart Home Steuerung öffnen: http://smart-home-server:3030#home. Alternativ kann man alles am Monitor auf dem weißen Regal demonstrieren. Für das Rollenspiel ist das iPad aber empfehlenswert, damit man es dem/der Klient/in in die Hand drücken kann. | ![Smart-Home-9](uploads/fd48da57a705bd4de40056bda90eb844/Smart-Home-9.png) |
8
+| **Kühlschrank-Fotos vorbereiten:** Sobald in der Steuerung im Reiter "Was sieht das Smart Home?" das Feld "Kühlschrank-Kamera" verfügbar ist (dauert eventuell kurz bis die Computer im Kühlschrank hochgefahren haben), die Kühlschrank-Kamera mit dem Slider aktivieren. Dann einmal den Kühlschank öffnen, die Tür kurz offen halten als bräuchte man Zeit, etwas raus/reinzutun, Tür wieder schließen. Warten, bis auf dem Dashboard auf dem weißen Regal die Fotos des Kühlschranks angezeigt werden. Das kann eine Minute dauern, weil die Computer im Kühlschrank sparsam und damit langsam sind. Die Fotos erscheinen dann unten rechts im Dashboard. | ![IMG_20231017_103319_809](uploads/ea6696e5e44060b3e1ebbf0ef929ff54/IMG_20231017_103319_809.jpg) |
9
+
10
+
11
+# Rollenspiel oder einfache Demonstration der Funktionen
12
+
13
+Falls das Rollenspiel durchgeführt werden soll:
14
+
15
+- [ ] Beobachtungsfragen (laminierte A5-Blätter im weißen Regal) an die Beobachter verteilen. Es gibt vier verschiedene Fragekarten, jeweils durch farbigen Punkt auf der Rückseite zu erkennen.
16
+- [ ] Rollenkarten (farbige laminierte A4-Blätter im weißen Regal) an die Rollenspieler verteilen.
17
+
18
+Dem Verkäufer (im Fall des Rollenspiels) bzw. Moderator der Demonstration des Smart Homes (in allen anderen Fällen) kommt dann die Aufgabe zu, die einzelnen Funktionen zu demonstrieren. Folgende Punkte haben sich immer gut für Diskussionen geeignet, wobei nicht immer alle vorgetanzt werden müssen:
19
+| Funktion | Demonstration |
20
+| ------ | ------ |
21
+| SensFloor | Verweis auf die blauen Markierungen der Personen im Raum, die immer auf dem Dashboard zu sehen sind |
22
+| Sturzalarm ohne Kamera | Zuerst jemanden (Rollenspiel: Angehörige/r) den QR-Code für Angehörige am Küchenschrank mit dem Handy scannen lassen. Der geöffneten Internetseite sollten Benachrichtigungen erlaubt werden. Sturzkamera noch aus lassen (Steuerung -> Was sieht das Smart Home -> Kamera aus und/oder Steuerung -> Was sehen andere -> Lena (Tochter) -> Sturzkamera aus. Puppe auf den Boden um Sturzalarm auszulösen: SensFloor-Bild im Dashboard wird rot und auf dem Handy kommt eine Nachricht. Puppe wieder aufheben. |
23
+| Sturzalarm mit Kamera | Nun Sturzkamera einschalten (Steuerung -> Was sieht das Smart Home -> Kamera ein und Steuerung -> Was sehen andere -> Lena (Tochter) -> Sturzkamera ein. Puppe auf den Boden um Sturzalarm auszulösen: nun wird auch ein Foto auf dem Handy angezeigt. |
24
+| Warnung bei offenem Fenster | Jemanden (Rollenspiel: Bewohner/in) den QR-Code für den Bewohner scannen lassen. Dann das Fenster kippen und durch die Tür den Raum verlassen. Die Bewohner-App zeigt eine Warnung an. |
25
+| Kühlschrank-Fotos | Jemanden (Rollenspiel: Hauswirtschafter/in) den QR-Code für Hauswirtschaftsdienst scannen lassen. Dann Steuerung -> Was sehen andere -> Herr Schmid -> Kühlschrankkamera aktivieren.
26
+| Sprachsteuerung | Steuerung -> Was sieht das Smart Home -> Mikrofon an. In Richtung des Mikrofons im weißen Regal sagen: "Mach die Stehlampe an". Entsprechend "Mach die Stehlampe aus". Achtung: Das wird unzuverlässig bei großem Abstand zum Mikrofon und bei hohem Geräuschpegel (insb. bei gleichzeitiger Nutzung eines anderen Spaces). |
27
+
28
+# Im Nachgang
29
+
30
+- [ ] Sprachsteuerung aus (Smart Home Contorl -> Was sieht das Smart Home -> Mikrofon aus).
31
+- [ ] Kamera aus (Smart Home Contorl -> Was sieht das Smart Home -> Sturzkamera aus).
32
+- [ ] Powerbanks im Kühlschrank abstecken und im weißen Regal, unteres geschlossenes Fach zum Laden anstecken.
33
+
34
+# Erste Hilfe
35
+
36
+- Das SensFloor-Bild im Dashboard ist eingefroren: Die ganze Browser-Seite neu laden und/oder Rechtsklick in das SensFloor-Bild und zweitletzte Option "Frame neu laden".
37
+- Sonstige Wehwehchen: Smart Home Control -> Steuerung -> Smart Home neu starten.
38
+- Läuft dann immer noch etwas nicht rund: Smart Home Control -> Steuerung -> Smart Home zurücksetzen und dann Smart Home Control -> Steuerung -> Smart Home neu starten.
... ...
\ No newline at end of file
smart_home/Spracherkennung.md
... ...
@@ -0,0 +1,5 @@
1
+Das Smart Home hat ein Mikrofon, über den man z.B. das Licht ein- oder ausschalten kann.
2
+
3
+Dabei gibt es zwei verschiedene 'smarte Assistenten'. Auf der einen Seite ein sehr einfachen Assistenten, der ausschließlich lokal läuft, und keine Daten in die Cloud schickt. Und auf der anderen Seite ist Amazon Alexa integriert.
4
+
5
+Normalerweise hört nur der lokale Assistent zu und reagiert auf Stichwörter. Wenn man aber "Alexa" sagt, wird Alexa aktiviert, und hört statt dem lokalen Assistenten zu.
... ...
\ No newline at end of file
smart_home/Vosk-Transkript-via-Kommandozeile.md
... ...
@@ -0,0 +1,26 @@
1
+# 0. Voraussetzungen
2
+
3
+Diese Doku setzt die Anaconda-Umgebung voraus, die JS für Vosk auf seinem Laptop eingerichtet hat. Bei Interesse einfach fragen.
4
+
5
+# 1. Konversion
6
+
7
+Audio-Datei kann mit ffmpeg den Anforderungen angepasst werden:
8
+`ffmpeg -i original.m4a -c:a pcm_s16le -ar 16k -ab 16k -ac 1 converted.wav`
9
+
10
+# 2. Transkription
11
+Anaconda-Umgebung "vosk" im Terminal starten, dann ins Verzeichnis
12
+`/Users/ge52jep/vosk-api/python/example/`
13
+gehen.
14
+
15
+## 2.1 für mehr als einen Satz
16
+In der Datei test_simple-modJS.py sicherstellen, dass Zeile 29 aktiv und 35 auskommentiert ist, und dann die Datei converted.wav mit dem Befehl
17
+`python3 test_simple-modJS.py tests-deutsch/converted.wav > transkription.txt`
18
+transkribieren lassen.
19
+
20
+## 2.2 für nur einen Satz
21
+In der Datei test_simple-modJS.py sicherstellen, dass Zeile 29 auskommentiert und 35 aktiv ist, und dann die Datei converted.wav mit dem Befehl
22
+`python3 test_simple-modJS.py tests-deutsch/converted.wav > transkription.txt`
23
+transkribieren lassen.
24
+
25
+# Ausblick
26
+Das ist nur ein primitiver Anfang. Die ffmpeg-Konversion lässt sich natürlich auch gleich mit der Transkription verknüpfen, siehe test_ffmpeg.py
... ...
\ No newline at end of file
smart_home/_sidebar.md
... ...
@@ -0,0 +1,58 @@
1
+[Home](Home)
2
+
3
+**Für Anwender**
4
+
5
+[Smart Home benutzen](Smart%20Home%20benutzen)
6
+
7
+
8
+**Für Admins**
9
+
10
+[Einrichtung der Raspis](Einrichtung%20der%20Raspis)
11
+
12
+[Beteiligte Computer](Beteiligte%20Computer%20und%20wichtigste%20Services)
13
+
14
+[Geräte im Smart Home](Ger%C3%A4te%20im%20Smart%20Home)
15
+
16
+[Spracherkennung](Spracherkennung)
17
+
18
+[Ansible](Ansible)
19
+
20
+**Für Entwickler**
21
+
22
+[Aufbau](Aufbau)
23
+
24
+[Grundlagen der API](Grundlagen%20der%20API)
25
+
26
+[smart-home-control](Smart%20Home%20Control%20%E2%80%93%20Server)
27
+
28
+[smart-home-control APIs](smart-home-control%20APIs)
29
+
30
+[Gerätesteuerungen](Gerätesteuerungen)
31
+
32
+[Shelly Steckdosen](Shelly%20Steckdosen)
33
+
34
+[SensFloor](SensFloor)
35
+
36
+[Funksteckdose über 433MHz von Raspi ansteuern](Funksteckdose%20%C3%BCber%20433MHz%20von%20Raspi%20ansteuern)
37
+
38
+[Lichtsteuerung durch Spracherkennung auf Raspi](Lichtsteuerung%20durch%20Spracherkennung%20auf%20Raspi)
39
+
40
+[Server](Server)
41
+
42
+[Kühlschrankkamera](K%C3%BChlschrankkamera)
43
+
44
+[Fenstersensor](Fenstersensor)
45
+
46
+[Fernzugriff](Fernzugriff%20innerhalb%20MWN)
47
+
48
+[Fernzugriff der API](Fernzugriff%20der%20API)
49
+
50
+**Verwandte Technologien**
51
+
52
+[Vosk: Transkript via Kommandozeile](Vosk%20Transkript%20via%20Kommandozeile)
53
+
54
+[MQTT](MQTT)
55
+
56
+**Austausch mit Schulen**
57
+
58
+[Referendarbefragung](Referendarbefragung)
... ...
\ No newline at end of file
smart_home/smart-home-control-APIs.md
... ...
@@ -0,0 +1,203 @@
1
+Diese Seite beschreibt die APIs & Datenformate, mit denen mit den Geräten über den smart-home-control Server kommuniziert werden kann. Für die allgemeine socket.io API siehe [smart-home-control](smart-home-control).
2
+
3
+[[_TOC_]]
4
+
5
+# smart-home-control selbst
6
+Der smart-home-control Server hat ein paar spezielle Funktionen, hauptsächlich um Geräte/Services zu starten/stoppen und deren Status zu erfahren.
7
+
8
+### Daten
9
+Auf dem Kanal `status` wird je Gerät der Gerätestatus ausgegeben, z.B.:
10
+```js
11
+"status": {
12
+ "mikrofon": {
13
+ "verfuegbar": true,
14
+ "status": "an", // "an", "aus", "startet", "stoppt"
15
+ "msg": null, // optional
16
+ },
17
+ // ...
18
+}
19
+```
20
+
21
+### Events / Funktionen
22
+- Geräte, die den Status `false` haben, können mit `status:anschalten` und dem Gerätenamen als Argument gestartet werden.
23
+- Geräte, die den Status `true` haben, können mit `status:ausschalten` und dem Gerätenamen als Argument gestoppt werden.
24
+- Mit `status:update` und dem Gerätenamen sowie neuen Status kann der Status geupdated werden.
25
+- `neustart` (noch nicht implementiert) veranlasst das Neustarten aller zentralen Komponenten im Smart Home
26
+- `herunterfahren` (noch nicht implementiert) fährt alle Geräte im Smart Home (soweit möglich) herunter
27
+
28
+*In dem zu einem Gerät gehörenden Kanal können nur dann Events gesendet oder empfangen werden, wenn das Gerät den Status `true` hat, also eingeschalten ist.*
29
+
30
+# Mikrofon (Sprachsteuerung)
31
+Das Mikrofon läuft als eigener User-Level Service auf dem gleichen Raspi wie das `smart-home-control`.
32
+
33
+### Daten
34
+```js
35
+"mikrofon": {
36
+ // Die Satz-ID zählt die von der Spracherkennung erkannten "Sätze" hoch, um
37
+ // zu erkennen wenn ein neuer Satz begonnen hat.
38
+ "satz_id": 0,
39
+ // Spracherkennungs-Text des aktuellen Satzes
40
+ "text": "",
41
+ // true falls ein Befehl im aktuellen Satz erkannt und ausgeführt wurde.
42
+ // Das dient dazu, dass Dinge nicht mehrfach ausgeführt werden.
43
+ "ausgefuehrt": false,
44
+}
45
+```
46
+
47
+### Events / Funktionen
48
+- `mikrofon:ausgefuehrtSetzen` mit der Satz-ID als Argument setzt den aktuellen Satz auf 'ausgeführt' (falls er überhaupt noch aktiv ist)
49
+
50
+# Shellies (Steckdosen + vllt. mal Thermostat)
51
+Weil die Shellies alle sehr ähnlich über MQTT gesteuert werden, gibt es einfach ein Service, der alle Shelly Geräte bündelt (ob Steckdosen oder Thermostat) und zu Socket.io bridged. Bekannte Geräte können anhand ihrer Hardware-ID/MAC erkannt werden, und haben dann einen praktischeren Namen. Welche das sind, wird in der Shelly Bridge Config festgelegt.
52
+
53
+### Daten
54
+Die Daten zu Steckdosen werden im Kanal `steckdosen` gebündelt:
55
+```js
56
+"steckdosen": {
57
+ "meine-shelly-steckdose": {
58
+ "name": "Steckdose Küche (mit Strommessung)", // Wird in der Bridge Config gesetzt
59
+ "mac": "98CDAC2FF800", // bei unbekannten Geräten wird die MAC als Kanalname genommen
60
+ "ip": "192.168.178.49",
61
+ "bekannt": true, // Falls die MAC bekannt ist
62
+ "verbunden": true,
63
+ "an": false, // Ob Strom an der Steckdose eingeschalten ist
64
+ "leistung": 0, // Falls verfügbar die aktuelle Leistung in Watt
65
+ },
66
+ // weitere Steckdosen
67
+}
68
+```
69
+
70
+Der Status der MQTT Bridge wird im `status` Kanal unter `shellies` zur Verfügung gestellt.
71
+
72
+### Events / Funktionen
73
+- `steckdosen:anschalten` mit der Steckdosen ID als Argument schaltet eine Steckdose ein,
74
+- `steckdosen:ausschalten` mit der Steckdosen ID als Argument schaltet eine Steckdose aus.
75
+
76
+Achtung: Mit `status:anschalten/ausschalten "shellies"` (siehe oben), startet/stoppt man nur die WebSocket/MQTT Bridge zu den Shellies.
77
+
78
+# SensFloor
79
+SensFloor Events werden über einen eigenen User-Level Service auf dem gleichen Raspi wie das `smart-home-control` empfangen und verarbeitet. Außerdem steuert dieser Service den SensFloor über dessen API (ein/ausschalten).
80
+
81
+### Daten
82
+```js
83
+{
84
+ aktivitaet: true, // Ob Personen auf dem SensFloor sind
85
+ sturzalarm: true, // Ob gerade eine gestürzte Person erkannt wird
86
+ // Für verschiedene Bereiche des SensFloor, ob dort eine Person ist / steht
87
+ bereiche: {
88
+ irgendwo: true,
89
+ kueche: false,
90
+ },
91
+ verbunden_care_api: true, // Ob mit der Care API verbunden (eher allgemeine Dinge)
92
+ verbunden_room_api: true, // Ob mit der Room API verbunden (Positionen von Personen, Sturzalarme etc.)
93
+}
94
+```
95
+
96
+Die Bereiche lassen sich über den SensFloor Service konfigurieren.
97
+
98
+### Events / Funktionen
99
+- `sensfloor:service-anschalten` schaltet den SensFloor *Service* (der zuständig für die Events ist) ein,
100
+- `sensfloor:service-ausschalten` schaltet den SensFloor *Service* aus.
101
+- (`sensfloor:anschalten` schaltet den SensFloor selbst über dessen API an,)
102
+- (`sensfloor:ausschalten` schaltet ihn über dessen API aus.)
103
+
104
+Die letzten beiden Events sind in Klammern, weil man die auch über `status:anschalten "sensfloor"` aufrufen kann (was etwas einheitlicher zur restlichen API ist).
105
+
106
+
107
+# Fenstersensor
108
+Um das Fenster kümmert sich ein simples Python Skript, das auch auf dem `smart-home-control` Raspi als Skript läuft.
109
+
110
+### Daten
111
+```js
112
+"fenster": {
113
+ // null heißt, das (noch) nicht bekannt ist, ob das Fenster
114
+ // offen ist, oder ob der Schalter überhaupt angeschlossen
115
+ // wurde. Nur wenn das Fenster zu ist (Schalter geschlossen)
116
+ // kann gleich beim Start erkannt werden, dass der Schalter
117
+ // verbunden ist.
118
+ "offen": null, // sonst: true, false
119
+},
120
+```
121
+
122
+### Events / Funktionen
123
+keine (außer ein/ausschalten über `status:fenster` wie ganz oben beschrieben)
124
+
125
+
126
+# Sturzkamera
127
+Die Sturzkamera läuft auf einem anderen Raspi, der oben an der Decke befestigt ist, aber auch dort als Service. Mithilfe von der KI _PoseNet_ kann die Kamera Personen und deren Pose erkennen.
128
+
129
+### Daten
130
+```js
131
+"sturzkamera": {
132
+ "bild": "/cache/sturzkamera-posenet.jpg", // Der Pfad zum Abrufen des aktuellsten Bilds
133
+ "bildPoseNet": "/cache/sturzkamera-posenet.jpg", // Der Pfad zum Abrufen des aktuellsten Bilds mit überlagerter PoseNet Erkennung
134
+ "letzter_timestamp": null, // (Unix) Timestamp der letzten Aufnahme in Millisekunden
135
+ "fehler": false, // Ob bei der letzten Aufnahme ein Fehler aufgetreten ist
136
+},
137
+```
138
+
139
+### Events / Funktionen
140
+- keine
141
+
142
+# Wärmekamera
143
+Die Wärmekamera läuft aktuell auf dem gleichen Raspi wie die Sturzkamera und filmt aus der gleichen Perspektive (allerdings mit einem anderen Öffnungswinkel).
144
+
145
+### Daten
146
+```js
147
+"waermekamera": {
148
+ "bild": null, // Der Pfad zum Abrufen des aktuellsten Bilds
149
+ "letzter_timestamp": null, // (Unix) Timestamp der letzten Aufnahme
150
+ "T_max": 25.3, // Temperatur des wärmsten Pixels in der letzten Messung
151
+},
152
+```
153
+
154
+### Events / Funktionen
155
+- keine
156
+
157
+# Kühlschrank
158
+Der Kühlschrank ist nochmal ein wenig komplizierter, weil dort gleich drei Raspi Zeros sind. Nur einer davon hat ein Sensor, um den Tür Öffnungswinkel zu messen. Deswegen werden die einzelnen Felder von verschiedenen Skripten unabhängig geschrieben.
159
+
160
+### Daten
161
+```js
162
+"kuehlschrank": {
163
+ // Vom "Winkelsensor"-Skript geschrieben
164
+ "offen": true,
165
+ "winkel": 30, // Geschätzte 30° Öffnungswinkel
166
+ // Von den Kameraskripten geschrieben, die jeweils beobachten wie sich der Winkel ändert
167
+ "bilder": {
168
+ // Jeweils: Pfad zum Abrufen und Unix Timestamp der letzten Aufnahme
169
+ "innen_unten": { pfad: "/cache/kuehlschrank_innen_unten.jpg", timestamp: 16... },
170
+ "innen_oben": { pfad: "/cache/kuehlschrank_innen_oben.jpg", timestamp: 16... },
171
+ "aussen": null,
172
+ },
173
+ // Vom Bilderkennungsskript geschrieben
174
+ "bilderkennung": {} // tbd
175
+}
176
+```
177
+
178
+### Events / Funktionen
179
+/
180
+
181
+# Sturzalarm
182
+Der Sturzalarm ist wie eine Art "virtuelles Gerät", das als Plugin läuft, und sich um das Senden von Sturzalarmen kümmert. Es ist kein Teil vom SensFloor, damit es ein eigener Kanal ist, und um die Logik dahinter etwas zu trennen (Der SensFloor erkennt Sturzalarme, aber dieses Plugin kümmert sich um das Senden).
183
+
184
+### Daten
185
+```js
186
+"sturzalarm": {
187
+ "alarm": false,
188
+}
189
+```
190
+
191
+### Events / Funktionen
192
+- `sturzalarm:ausloesen` ohne Argumente löst ein Sturzalarm aus, falls noch keiner ausgelöst wurde,
193
+- `sturzalarm:beenden` ohne Argumente beendet den aktuellen, falls noch einer aktiv ist.
194
+
195
+# Web-Push
196
+Web-Push ist wie der Sturzalarm auch eine Art "virtuelles Gerät", das als Plugin läuft, und sich um das Senden von Push-Benachrichtigungen kümmert. Aktuell betrifft das nur den Sturzalarm.
197
+
198
+### Daten
199
+Keine
200
+
201
+### Events / Funktionen
202
+- `push-api:senden` sendet eine Web-Push Benachrichtigung an alle bekannten und berechtigten Geräte mit dem Sturzalarm,
203
+- `push-api:aufheben` updated bei Bedarf die Benachrichtigungen, falls der Sturzalarm aufgehoben wurde.
... ...
\ No newline at end of file
smart_home/uploads/0307b9b8fd0d2bf7a016bc53d1276c35/image.png
... ...
Binary files /dev/null and b/smart_home/uploads/0307b9b8fd0d2bf7a016bc53d1276c35/image.png differ
smart_home/uploads/0499de98dc50912c4788d24b5fa08658/schema-2.png
... ...
Binary files /dev/null and b/smart_home/uploads/0499de98dc50912c4788d24b5fa08658/schema-2.png differ
smart_home/uploads/08be79f221f554d655028be8504210c4/a2b3652d429e48ec83f3fda1f9572b76.png
... ...
Binary files /dev/null and b/smart_home/uploads/08be79f221f554d655028be8504210c4/a2b3652d429e48ec83f3fda1f9572b76.png differ
smart_home/uploads/0f3924fb24e4d769a8e3f55a7f1bac19/image.png
... ...
Binary files /dev/null and b/smart_home/uploads/0f3924fb24e4d769a8e3f55a7f1bac19/image.png differ
smart_home/uploads/1a0fefa95ee518c26b14bd15864c364e/out-0.png
... ...
Binary files /dev/null and b/smart_home/uploads/1a0fefa95ee518c26b14bd15864c364e/out-0.png differ
smart_home/uploads/22ae7016c123bd3a037837b13624837b/image.png
... ...
Binary files /dev/null and b/smart_home/uploads/22ae7016c123bd3a037837b13624837b/image.png differ
smart_home/uploads/23bf2cf0f7966faba193bfc325f27abf/eb352ae021eb435b92c0e83017cdb867.png
... ...
Binary files /dev/null and b/smart_home/uploads/23bf2cf0f7966faba193bfc325f27abf/eb352ae021eb435b92c0e83017cdb867.png differ
smart_home/uploads/2cfafbf7aeab00b220715018611d0470/kalibrationskurve.png
... ...
Binary files /dev/null and b/smart_home/uploads/2cfafbf7aeab00b220715018611d0470/kalibrationskurve.png differ
smart_home/uploads/4e9b78cbcfe7aafba204be5f69ed88b4/carrots-192-detect-2.png
... ...
Binary files /dev/null and b/smart_home/uploads/4e9b78cbcfe7aafba204be5f69ed88b4/carrots-192-detect-2.png differ
smart_home/uploads/6c8841f6b812393f1238b70df8b73d13/image.png
... ...
Binary files /dev/null and b/smart_home/uploads/6c8841f6b812393f1238b70df8b73d13/image.png differ
smart_home/uploads/76ab6798e5251320e963f967ad2db6ec/image.png
... ...
Binary files /dev/null and b/smart_home/uploads/76ab6798e5251320e963f967ad2db6ec/image.png differ
smart_home/uploads/8318191f7eb3dec3f4444d2245757c0c/IMG_20231017_103333_173.jpg
... ...
Binary files /dev/null and b/smart_home/uploads/8318191f7eb3dec3f4444d2245757c0c/IMG_20231017_103333_173.jpg differ
smart_home/uploads/899228324ce3d96a7e7d6539b642f3e4/cam1-1b-detect.png
... ...
Binary files /dev/null and b/smart_home/uploads/899228324ce3d96a7e7d6539b642f3e4/cam1-1b-detect.png differ
smart_home/uploads/9bc19e0e436940d3222ce8149a382170/out-2.png
... ...
Binary files /dev/null and b/smart_home/uploads/9bc19e0e436940d3222ce8149a382170/out-2.png differ
smart_home/uploads/b1298abf4c88d5cb88fbcd05505ce442/schema-2-extended.png
... ...
Binary files /dev/null and b/smart_home/uploads/b1298abf4c88d5cb88fbcd05505ce442/schema-2-extended.png differ
smart_home/uploads/cded45f31b257ede2221642d5f887fd7/schema-1.png
... ...
Binary files /dev/null and b/smart_home/uploads/cded45f31b257ede2221642d5f887fd7/schema-1.png differ
smart_home/uploads/cf4bfc2f1bffda8ea9e9b9aa031eff4b/image.png
... ...
Binary files /dev/null and b/smart_home/uploads/cf4bfc2f1bffda8ea9e9b9aa031eff4b/image.png differ
smart_home/uploads/cfe9cbd06218c35e9dd45fb7597d6144/IMG_20231017_103333_173.jpg
... ...
Binary files /dev/null and b/smart_home/uploads/cfe9cbd06218c35e9dd45fb7597d6144/IMG_20231017_103333_173.jpg differ
smart_home/uploads/dfc7beadddca131c8329ef5bbc98e485/5463902fb12c4e2fa4b6b63ee3a9c1aa.png
... ...
Binary files /dev/null and b/smart_home/uploads/dfc7beadddca131c8329ef5bbc98e485/5463902fb12c4e2fa4b6b63ee3a9c1aa.png differ
smart_home/uploads/ea6696e5e44060b3e1ebbf0ef929ff54/IMG_20231017_103319_809.jpg
... ...
Binary files /dev/null and b/smart_home/uploads/ea6696e5e44060b3e1ebbf0ef929ff54/IMG_20231017_103319_809.jpg differ
smart_home/uploads/f0b8ce80222c6854419082898cf948d4/kalibrationskurve.png
... ...
Binary files /dev/null and b/smart_home/uploads/f0b8ce80222c6854419082898cf948d4/kalibrationskurve.png differ
smart_home/uploads/fc29cdef4a1c8bf52f749b525dd139ee/image.png
... ...
Binary files /dev/null and b/smart_home/uploads/fc29cdef4a1c8bf52f749b525dd139ee/image.png differ
smart_home/uploads/fd48da57a705bd4de40056bda90eb844/Smart-Home-9.png
... ...
Binary files /dev/null and b/smart_home/uploads/fd48da57a705bd4de40056bda90eb844/Smart-Home-9.png differ
smart_home/uploads/ffc117f915bcd14423142a2ae78c42af/IMG_20240222_180121_525.jpg
... ...
Binary files /dev/null and b/smart_home/uploads/ffc117f915bcd14423142a2ae78c42af/IMG_20240222_180121_525.jpg differ