mikrocontroller.net

Forum: PC-Programmierung SQLite3 Datenbank fuer Sensor-Daten


Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe im Haus mittlerweile 3 kleine Boards verteilt, die jeweils ihre 
Sensordaten (Temp, Luftfeuchtigkeit, etc.) auf eine SD-Karte schreiben.
Das laeuft auch ganz wunderbar.

Jetzt moechte ich gerne die Dateien von den 3 Boards in eine einzige 
SQLite3 Datenbank ueberfuehren (auf dem PC).
Hierfuer werden die SD-Karten kurzzeitig am PC ausgelesen und wieder in 
die Boards zurueckgesteckt.

Die Boards legen jeweils pro Tag eine Datei an (YYYYMMDD.dat).
Jede Datei hat ganz am Anfang einen Header stehen. Z.b.:

#device = "device_1"       // gibt den Namen des Boards an
#timestamp;temp;humi       // gibt die Struktur der nachfolgenden 
Datensaetze an

danach folgen die Daten
20170418_160930;20.78;76.14
20170418_161000;20.55;75.30
usw.

Ich weiss jetzt leider nicht, wie ich die Datenbank strukturieren soll. 
Ich moechte nur eine Datenbank-Datei auf dem PC haben und ich kann 
innerhalb einer DB ja nur Tabellen anlegen.

Die Hierarchie ist mir klar:
+ Tabelle mit den Devices/Boards
  ¦ 
  + Tabelle fuer den Tagesdatensatz 
    ¦
    + Tabelle mit den Daten fuer diesen Tag

Aber wie bilde ich dies in der Datenbank ab?

Hintergrund: Wenn die Datenbank steht, wuerde ich nachfolgend noch eine 
PC-Applikation schreiben (vermutlich mit Python) mit einer einfachen 
Maske (Auswahl Device, Zeitraum, Sensor), mit der ich gezielt die 
entsprechenden Diagramme erzeugen kann.
Fuer die GUI wuerde ich PyQt5 hernehmen.

Herzlichen Dank und beste Gruesse.

Autor: S. R. (svenska)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du erzeugst einfach eine Tabelle mit den Spalten
> (id,device,datum,uhrzeit,sensor_typ,sensor_wert).

Wenn du das etwas besser strukturieren willst, dann sortierst du 
sinnvollerweise nach "Gerät" und "Sensortyp", das ergibt dann drei 
Tabellen:
> geraete: (id, beschreibung)
> sensortypen: (id, beschreibung, minimum, maximum, einheit)
> werte: (id, geraete_id, sensortyp_id, datum, uhrzeit, wert)

Pro Sensorwert legst du eine Zeile in der Wertetabelle an. Nach Tagen zu 
trennen ist wenig sinnvoll, das kannst du bei der Abfrage machen. 
SQL-Datenbanken können mit (passend formatierten) Datumsangaben rechnen.

Autor: 50c (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heinz schrieb:
> Aber wie bilde ich dies in der Datenbank ab?

entweder pro Device eine Tabelle mit den Spalten:
* timestamp
* temp
* humi

oder eine Tabelle für alles mit den Spalten:
* device
* timestamp
* temp
* humi

Ich würde die 2.Variante implementieren.

Autor: 50c (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> Pro Sensorwert legst du eine Zeile in der Wertetabelle an.

warum? Das verkompliziert nur die zukünftigen Abfragen...

Autor: Tom (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Dass ein Device Feuchtigkeit und Temperatur liefert, ist eigentlich 
ein Implementierungsdetail, das in der Datenbank nichts zu suchen hat. 
Nächsten Monat möchte man ein Board mit 2 Temperatursensoren 
anschließen, dann fängt der Pfusch a la "if (humi < 0) temp2 = -humi;" 
an, weil die Datenbank das nicht ermöglicht.

Autor: S. R. (svenska)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
50c schrieb:
>> Pro Sensorwert legst du eine Zeile in der Wertetabelle an.
> warum? Das verkompliziert nur die zukünftigen Abfragen...

Hä? Erklär mal, was du damit meinst.

Ich finde "eine Tabelle pro Gerät" ziemlich hässlich, weil das die 
Abfragen (und insbesondere das Pflegen der Geräte) ziemlich umständlich 
macht. Alle Sensorwerte in einer einzigen Tabelle zu halten, empfinde 
ich als einfach.

Siehe auch, was "Tom" schrieb. Das vermeidest du so nämlich.

Autor: fifila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde die Messwerte nicht (nur) dem device zuordnen, sondern dem 
jeweiligen Sensor.

Also
* timestamp
* sensor
* type ("temp", "humi", etc)
* messwert

Voraussetzung ist natürlich, dass alle Messwerte als ein Datentyp 
dargestellt werden können, also z.B. alle als Gleitkommazahl

Wenn nötig, kann man dann ja noch eine Tabelle machen, in der die 
Sensoren den devices zugeordnet werden, oder das device als zusätzliche 
Spalte in obere Tabelle.
So kann man auch später ein device mit meinetwegen 10 Temp-Sensoren, 8 
Humi-Sensoren und 3 Sensoren für den Wasserstand oder so anschließen.

Autor: fifila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fifila schrieb:
> Voraussetzung ist natürlich, dass alle Messwerte als ein Datentyp
> dargestellt werden können, also z.B. alle als Gleitkommazahl

Ergänzung: Auch alle zukünftigen Messwerttypen müssen das können, das 
sollte man nicht übersehen.

Autor: Clemens L. (c_l)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fifila schrieb:
> Voraussetzung ist natürlich, dass alle Messwerte als ein Datentyp
> dargestellt werden können, also z.B. alle als Gleitkommazahl

Bei SQLite ist das nicht notwendig.

http://www.sqlite.org/datatype3.html

Autor: fifila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Umso besser, danke, wusste ich noch nicht.

Autor: S. R. (svenska)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fifila schrieb:
> Ich würde die Messwerte nicht (nur) dem device zuordnen, sondern dem
> jeweiligen Sensor.

Guter Punkt. Also drei Tabellen wie folgt:
> geraete:  (id, beschreibung, start_timestamp, stop_timestamp)
> sensoren: (id, geraete_id, beschreibung, einheit, min, max)
> werte:    (id, timestamp, sensor_id, wert)

Für die Geräte sind zwei Timestamps ("ins System eingefügt" und "aus dem 
System entfernt") sinnvoll, weil man einmal eingepflegte Geräte nicht 
mehr aus der Datenbank entfernen kann, ohne die Verlinkung zu zerstören 
(oder alle Werte des Geräts zu löschen). Vielleicht ist noch eine 
Positionsangabe (z.B. "Dachboden") nützlich.

fifila schrieb:
> Voraussetzung ist natürlich, dass alle Messwerte als ein Datentyp
> dargestellt werden können

Gibt es Sensoren (in der Hausautomatisierung), deren Werte nicht 
sinnvoll mit einem Skalar abgebildet werden können?

Autor: fifila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> einmal eingepflegte Geräte nicht
> mehr aus der Datenbank entfernen kann, ohne die Verlinkung zu zerstören

Versteh ich nicht. Welche Verlinkung?

S. R. schrieb:
> Gibt es Sensoren (in der Hausautomatisierung), deren Werte nicht
> sinnvoll mit einem Skalar abgebildet werden können?

Wenn das auch Medien umfasst, ja (Titel, Interpret und solche Sachen). 
Aber wie ich aufgeklärt wurde, sollte das mit SQLite ja kein Problem 
sein.

S. R. schrieb:
> Vielleicht ist noch eine
> Positionsangabe (z.B. "Dachboden") nützlich.

Schaden kanns nicht, dann würde ich mir aber genau überlegen, wie die 
Position angegeben wird (z.B. Zimmer), sonst kannst du mit der Info 
später nicht viel anfangen.

Autor: S. R. (svenska)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fifila schrieb:
> Versteh ich nicht. Welche Verlinkung?

Ein Sensor ist an ein Gerät geknüpft; Sensor ohne Gerät geht nicht.
Ein Wert ist an einen Sensor geknüpft; Wert ohne Sensor geht nicht.

Was machst du, wenn du ein Gerät endgültig entfernst?
- du entfernst das Gerät aus der Datenbank und
  lässt die sensor_id/geraete_id ungültig werden;
- du entfernst das Gerät, dessen Sensoren und Werte;
- du markierst es als "entfernt".

fifila schrieb:
> Wenn das auch Medien umfasst, ja (Titel, Interpret und solche Sachen).

Die CD-Sammlung würde ich jetzt weder unter "Hausautmatisierung" noch 
unter "Sensordaten" abfassen wollen. Zumal ein Freitextfeld dafür eine 
denkbar schlechte Darstellung ist.

Naja, die Positionsangabe wird ohnehin veralten. Wenn ich mir da eine 
Datenbank mit den Temperaturen der letzten Jahre vorstelle, gepflegt 
über vier Umzüge und drölfzig Sensordefekte...

Autor: fifila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S. R. schrieb:
> Was machst du, wenn du ein Gerät endgültig entfernst?
> - du entfernst das Gerät aus der Datenbank und
>   lässt die sensor_id/geraete_id ungültig werden;
> - du entfernst das Gerät, dessen Sensoren und Werte;
> - du markierst es als "entfernt".

Ich würde eine Spalte "aktiv" oder "online" oder etwas in der Richtung 
in der geräte tabelle einführen.
Beim entfernen auf 0 setzen, alles andere kann bleiben wie es ist.
Soll das gerät wieder mit selber Aufgabe hinzugefügt werden, "online" 
auf 1 und weiter gehts.
Ändert sich z.B. der Aufstellungsort, bekommt das Gerät eine neue ID.

Autor: Kaj (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fifila schrieb:
> S. R. schrieb:
>> einmal eingepflegte Geräte nicht
>> mehr aus der Datenbank entfernen kann, ohne die Verlinkung zu zerstören
>
> Versteh ich nicht. Welche Verlinkung?
Sowas nennt sich Anomalie
https://de.wikipedia.org/wiki/Anomalie_(Informatik)

Autor: fifila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kaj schrieb:
> fifila schrieb:
>> S. R. schrieb:
>>> einmal eingepflegte Geräte nicht
>>> mehr aus der Datenbank entfernen kann, ohne die Verlinkung zu zerstören
>>
>> Versteh ich nicht. Welche Verlinkung?
> Sowas nennt sich Anomalie
> https://de.wikipedia.org/wiki/Anomalie_(Informatik)

Schon klar, aber warum sollte man ein Gerät aus der Datenbank entfernen, 
wenn man es einfach als offline markieren kann?

Wie man dann mit solchen Geräten bei der Auswertung umgeht, steht einem 
ja frei.
Oder gibt's hier irgendwelche Probleme in Richtung Datenschutz oder 
Speicherplatz?

Autor: S. R. (svenska)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fifila schrieb:
> Ich würde eine Spalte "aktiv" oder "online" oder etwas in der Richtung
> in der geräte tabelle einführen.

Ja, gut, ich hatte zwei Timestamps "eingebaut" und "entfernt" empfohlen. 
Ob ein Gerät "aktiv" ist, ist ja eher irrelevant (außer, um zu schauen, 
ob ein Gerät aufgehört hat zu senden), aber es ist nachträglich noch 
interessant zu wissen, wie lange ein Gerät existiert hat.

Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, danke fuer die Inspiration... :-)

Was heisst das jetzt eigentlich aus Sicht meiner PC-Applikation?

Angenommen ich habe jetzt 3 Tabellen innerhalb meiner Datenbank-Datei:
> geraete:  (id, beschreibung, start_timestamp, stop_timestamp)
> sensoren: (id, geraete_id, beschreibung, einheit, min, max)
> werte:    (id, timestamp, sensor_id, wert)

Jetzt liest die PC-Applikation das File 20170715.DAT aus:
#device = "device_1"       
#timestamp;sht21_temp;sht21_humi       

20170715_160930;20.78;76.14
20170715_161000;20.55;75.30

Danach muss die Datenbank mit den entsprechenden Daten befuellt werden:
a) Gibt es device_1 bereits in Tabelle geraete? (Wenn nicht erzeugen)
   - Beschreibung, etc. kann ich spaeter haendisch nachtragen
   - geraete_id zwischenspeichern
b) Gibt es sht21_temp in der Tabelle sensoren? (wenn nicht erzeugen)
   - Einheit, min, max werde ich spaeter manuell nachtragen
   - sensor_id zwischenspeichern
c) Gibt es timestamp & sensor_id in der Werte Tabelle? (wenn nicht   eintragen mit geraete_id und sensor_id)

Sehen die Schritte tatsaechlich dann so aehnlich aus?

Danke!

Autor: S. R. (svenska)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heinz schrieb:
> Sehen die Schritte tatsaechlich dann so aehnlich aus?

Ja, bis auf den dritten Schritt: Wenn du die Geräte- und Sensor-IDs aus 
der Datenbank geladen hast, dann trägst du den Sensorwert einfach ein. 
Ein Sensor kann zu jedem Zeitpunkt nur einen Wert haben, also ist jeder 
Wert eindeutig.

Du brauchst in der Geräte- und Sensorentabelle noch eine Spalte "name", 
wo der interne Name verzeichnet ist. Die IDs sollten normale Integers 
(PRIMARY KEY, AUTOINCREMENT) sein.

Ich weiß nicht, ob man Geräte und Sensoren automatisch (ohne Hinweis) 
hinzufügen sollte oder nicht, aber das ist Geschmackssache.

Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Danke.
Ich habe meine erste Version mit den 3 Tabellen zum Laufen gebracht...
Jetzt sammle ich erstmal Daten (und Erfahrungen im Umgang mit der 
Datenbank).

Muss mir das Thema Views bzw. Ansichten noch anschauen, scheint ein 
nuetzlicher Ansatz zu sein... :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.