Sensor Aggregation in Netzwerken und Applikation (1) (PD Stefan Bosse) [12.2023] |
In dieser Übung soll ein erster Prototyp eines Sensor Monitors programmiert werden der über einen Web Service verfügt (Aggregation und Applikation).
terminal> lvm luaos
Linux: Optional ./lvm
in dem Verzeichnis ausführen wo lvm gespeichert wurde da es schon ein Systemprogramm lvm gibt!
LuaOS im Web Browser und in der nativen Plattform sind nahezu identisch in der API.
Wichtig. Das Notebook muss entweder via http (nicht https) oder lokal vom Dateisystem in der Web Browser geladen werden, sonst funktioniert die verbinung zur lvm Instanz nicht. Immer die aktuelle Version von lvm und LuaOS verwenden.
▸
◼
|
Die Konsolenausgaben der externen Ausführung von Code sind hier zur besseren Unterscheidbarkeit rot umrandet.
Der erste wichtige Sensor ist die georäunmliche Position. Diese kann mittels GPS Sensorik (< 10 m Genauigkeit) oder mittels der Internet IP Adresse (> 1 km Genauigkeit) bestimmt werden.
▸
|
✗
≡
|
Es soll ein einfacher HTTP Server gebaut werden der mittels eines HTTP basierten RPC Protokolls Sensordaten von Sensorknoten empfängt und diese in einem weiteren WEB HTTP-HTML Service textuell darstellt. Also zweimal HTTP mit dem gleichen IP Port:
LusOS bietet die http
Klasse um einen HTTP Server zu erzeugen (nur native Plattform, im WEB Browser nicht möglich/verfügbar):
local hs = http:new()
hs:service(hostip, ipport, function (method,url,peername,params,body)
...
return response -- Text!
end)
Die Parameter des HTTP Request Handlers:
"GET"/"PUT"
http://127.0.0.1:22223
)
▸
|
✗
≡
|
Ein HTTP/TCP IP Port kann nur einmal belegt werden. Startet man einen zweiter Server auf dem gleichen Port gibt es einen Fehler. Wird der Server Handler überarbeitet einfach den Thread Prozess stoppen und dann wieder neu starten.
Einfache HTML Seiten können mit der LuaOS html
Klasse erzeugt werden:
local H = html:new()
local htmltext = H:html(
H:head(),
H:body({
H:h1("text"),
H:h2("text"),
H:p("text"),
H:ol({
H:li("text"),
H:li("text"),
..
}),
H:table({
{ "text", "text", .. },
{ "text", "text", .. },
...
})
})
)
Beispiel der Erzeugung einer HTML Seite
▸
|
✗
≡
|
date()
).Im nächsten Schritt soll ein Sensor Service programmiert werden der folgende Aufgaben erfüllen soll:
Alle eingehenden Sensordaten (über PUT Request) im Format {sensor:string,time:number, data:string,unit:string} sollen in einer dynamisch wachsenden Tabelle eingbaut werden. Wenn das Sensordatenrekord keinen Zeitstempel enthält muss im Server einer hinzugefügt werden. Die (Lua) Tabelle enthält direkt die emfpangenen Sensordatenrekords.
Es soll eine Coroutine geben die in periodischen Abständen alte Einträge entfernt (Zeitstempel verwenden). Der Timeout soll konfigurierbar sein.
Es sollen Mittelwerte aktueller Sensordaten berechnet werden (nur numerische Sensoren wie Geo/GPS) oder Verteilungen bei kategorischen Werten (siehe 6.). Der Geo Sensor liefert eine Tabelle mit numerischen lon und lat Feldern. Wichtig: Die Sensordaten werden im JSON Textformat übertragen und müssen in ein Lua Datentyp mittels JSON.decode(textdata)
konvertiert werden.
Der Server soll eine dynamische HTML Seite erzeugen die alle Sensoreinträge als HTML Tabelle listet und eine weitere Tabelle mit Sensormittelwerten (+ Standardabweichung der Werte) oder bei kategorischen Werten eine Verteilung
Es soll aus dem Agententext das Betriebssystem (Linux, Windows, MacOS) und die Plattform (Browser/lvm) mit String Funktionen LUA Strings und LUA String Operationen sowie LUA Patterns bestimmt und als eigenständige Sensor eingetragen werden.
Die Programmierung erfolgt hier!
▸
|
✗
≡
|
▸
|
✗
≡
|
▸
|
✗
≡
|
▸
|
✗
≡
|
Jeder Sensorknoten ist ein Klient der Sensorservices (Server) und kann auf eigene Sensoren über die generische Sensorklasse zugreifen. Dabei stehen je nach Plattform verschiedene Sensorunterklassen zur Verfügung die mittels der sensor:all
Methode abgefragt werden können. Im WEB Browser werden es nur wenige sein, u.A. geo der die GPS Koordinaten des Standortes über die IP Adresse liefert (sehr ungenau) sowie agent der Informationen über die Plattform als String ausgibt. Ein Sensor muss von der generischen Klasse durch s=sensor:new("class")
erzeugt werden:
▸
|
✗
≡
|
▸
|
✗
≡
|
Ein Sensor muss i.A. gestartet werden (genauer das periodische Sampling). Mittels der s:read()
Methode wird der aktuelle Wert gelesen. Dieser kann aus einem bereits erfolgten Samplingvorgang stammen (z.B. in einer Smartphone App) oder direkt erfasst werden.
local geo1 = sensor:new("geo")
geo1:start()
sleep(1000) -- Die initiale Geo Erfassung dauert eine kurze Zeit
local sample = geo1:read()
print(sample)
Der Klient wird hier direkt im Web Browser laufen!
Ein HTTP PUT Request kann über die http Klasse erzeugt werden:
local hc = http:new()
local url = "localhost:22223"
local data = { sensor="test",time=time(), data=0, unit="integer" }
local response,header,error = hc:put(url,JSON.encode(data))
Beispiel HTTP PUT/POST Request zu einem externen Server (Internet)
▸
|
✗
≡
|
▸
|
✗
≡
|
Der Sensor Server muss natürlich zuerst auf der lvm gestartet werden (siehe oben)!
Der HTTP PUT Request liefert eine (textuelle) Rückantwort des Servers (hier z.B. einfach "OK").
Zwei Sensoren sollen ausgelesen werden: agent und geo.
Die Sensorwerte sollen (einmalig) zum Sensor Server im JSON Format gesendet werden (JSON.encode(request)
). Dabei ist ein Sensordatenwert eine Lua Tabelle {sensor:string, time:number, data:table|string|number, unit:table|string}
die im JSON Format übertragen wird. Das Feld sensor enthält den Klassennamen des Sensors.
Teste die Ausgabe der Sensoren im Klientencode und dann nach der Versendung auf dem Server über das WEB Interface
▸
|
✗
≡
|