In diesem Beitrag möchte ich die Datenstruktur die zur Verwaltung der Geräte und Meßwerte verwendet wird, im Detail erläutern. Alle Strukturdefinitionen finden sich in der Bibliotheksdatei AT_Database.h.
Wenn ein Gerät registriert wird,werden seine Kenndaten in der Geräteliste gespeichert. Die Geräteliste ist ein Array von Datenblöcken mit folgender Struktur:
typedef //Gerätedefinition
struct ATDEVICE {
uint8_t activ = 0; //das hier definierte Gerät existiert
uint8_t service = 0; //0=ESP-Now Vorbereitung falls später andere Dienste
//impülementiert werden
uint8_t id[6] = {0,0,0,0}; //MAC adresse des Geräts
uint16_t devicebits = 0; //Bitfeld mit Infos zum Gerät und zur Datenübertragung
String name = ""; //Name des Geräts
String last = ""; //Zeitstempel für die letzte erfolgreiche Datenübertragung
};
Als Index in dieses Array dient die Gerätenummer. Die Klasse AT_Database definiert eine Geräteliste für 32 Geräte. Um die Gerätedatren dauerhaft zu speichern, werden diese im SPIF Filesystem im Flash des ESP32 gespeichert.
Folgende Funktionen der Klasse dienen zum Arbeiten mit der Geräteliste:
-
boolean readDevices(String fileName); Liest die Geräteliste aus einem File mit Namen fileName im SPIFFS. Gibt false zurück wenn ein Fehler auftrat.
-
boolean writeDevices(String fileName); Schreibt die Geräteliste in ein File mit Namen fileName in das SPIFFS. Gibt false zurück wenn ein Fehler auftrat.
- boolean clearDevices(String fileName); Löscht alle Geräte und speichert das Ergebnis unter fileName im SPIFFS. Gibt false zurück wenn ein Fehler auftrat.
- int16_t findDevice(uint8_t id[6]); Diese Funktion sucht in der Geräteliste ein Gerät mit der angegebenen id (MAC Adresse). Die Funktion gibt den Index also die Gerätenummer des Geräts zurück. -1 bedeutet das Gerät ist nicht in der Geräteliste.
- String getDeviceId(uint8_t device); Gibt die Id des Geräts mit der Gerätenummer device zurück.
Treffen Messwerte für ein registriertes Gerät ein werden die in der Ergebnistabelle gespeichert. Die Ergebnistabelle besteht aus Elementen mit folgender Struktur:
typedef //Struktur zum Speichern der Messwerte
struct ATCURVALUES {
uint8_t valid; //Die Struktur enthält einen gültigen Messwert
uint8_t step; //wird benutzt um Verarbeitungsschritte zu speichern
uint8_t type; //Der Typ des gespeicherten Messwerts
uint8_t unit; //Die Einheit des gespeicherten Messwerts
uint8_t value[4]; //vier Bytes mit em Messwert, entweder 32bit Integer oder Float
//je nach Typ. Der Typ Boolean benutzt nur das erste Byte
};
Die Klasse AT_Database reserviert Speicherplatz für eine Ergebnistabelle mit 256 Einträgen (32 Geräte mit je bis zu acht Kanälen). Der Index für diese Tabelle errechnet sich aus Gerätenummer und Kanalnummer.
Index = Gerätenummer * 32 + Kanalnummer
Folgende Funktionen der Klkasse AT_Database arbeitet mit der Ergebnistabelle:
- void setResult(uint8_t index, ATDATAPACKET data); Diese Funktion aktualisiert die Daten an der Stelle Index mit den Werten in der Struktur data. Die Struktur ATDATAPACKET wurde in der Bibliothek ATMessageBuffer definiert und wird auch zur Datenübertragung verwendet.
- ATCURVALUES getResult(uint16_t index); Diese Funktion gibt die oben beschriebene Struktur für das Ergebnis and der Position Index in der Ergebnistabelle zurück.
- void setStep(uint8_t step, uint16_t index); Der Verarbeitungsschritt für das Ergebnis an der Stelle Index in der Ergebnistabelle wirt auf den Wert step gesetzt.
- String getValueString(uint16_t index, uint8_t precision, boolean useunit ); Returniert den Wert des Ergebnis an der Stelle Index in der Ergebnistabelle als String. Der Parameter precision gibt die Anzahl der Nachkommastellen für Float Werte an, Ist der Parameter useunit true wird die Eionheitenbezeichnung an den String angehängt.
- uint8_t getBooleanValue(uint16_t index); Gibt den boolschen Wert des Ergebnis an der Stelle Index als 0 oder 1 zurück. Nur für den Typ Boolean sinnvoll.
- boolean isValueOutput(uint16_t index); Gibt true zurück wenn der Typ des Ergebnis an der Stelle Index ein Output Typ ist, das heißt Daten enthält die von der Zentrale an das Gerät gesendet werden. (z.B. Schalter).
- boolean isSwitchOut(uint16_t index); Ähnlich wie vorherige Funktion liefert aber nur dann true wenn es sich um einen Schalter handelt:
- boolean isValueZero(uint16_t index); Gibt true zurück wenn der Wert des Ergebnis an der Stelle Index genau 0 ist.
- void toggleResult(uint16_t index); Schaltet das Ergebnis an der Stelle Index vo 0 auf 1 bzw umgekehrt. Nur für den Typ Boolean sinnvoll.
- int8_t getResponse(int16_t device, uint8_t * buffer, uint8_t * size); Untersucht alle Ergebnisse mit einem Output Typ für das Gerät device und füllt einen Buffer buffer mit einem fertigen Nachrichtenpaket, das dann an das Gerät übertragen werden kann. Der Parameter size enthält die maximale Buffergröße und nach Rückkehr der Funktion die wirklich genutzte Buffergröße. Der Rückgabewert ist die Anzahl der gefundenen Datenpakete oder -1 falls die Buffergröße zu klein war.
Eine weitere3 Struktur in dieser Bibliothek wird benutzt um die Darstellung der Ergebnisse am Display zu steuern. Es gibt eine Liste von Seiten. Jede Seite enthält 8 Widget einträge mit folgender Struktur:
typedef //Definition eines Diosplay-Widgets
struct ATDISPLAYWIDGET {
uint16_t source; //Index zum zugeordneten Ergebnis
uint8_t status; //Status 0=not used, 1=used, 2=placeholder, 3=hidden
uint8_t size; //Größe des Widgets 0=240x30,1=240x60 left
//2=120x60 right 3=120x60
uint8_t type; //Typ des Widgets, derzeit nur 0=simple
uint16_t bgcolor; //Hintergrundfarbe normal
uint16_t bgcolorOn; //Hintergrundfarbe für Knöpfe wenn Ein
uint16_t fontcolor; //Schriftfarbe
uint8_t image; //Index eines Bildes(noch nicht benutzt)
uint8_t precision; //Anzahl der Nachkommastellen für Messwerte
String label = ""; //Beschriftung
};
Die Klasse AT_Database reserviert den Platz für 32 Seiten mit je bis zu acht Widgets. Folgende Funktionen arbeiten mit dieser Tabelle:#
- int16_t getFreeSlot(uint8_t page, uint8_t size); Diese Funktion liefert den Index für ein Widget auf der Seite page mit der Grlöße size, das nocht plkatz hat oder -1 wenn auf der Seite kein Platz ist.
- ATDISPLAYPAGE getPage(uint8_t page); Gibt eine Liste mit allen Widgets auf der Seite page zurück.
Die Funktion
boolean registerDev(String deviceId, AT_MessageBuffer msg);
registriert ein Gerät mit der Id deviceId, wenn es noch nichtr registriert wurde. Der Parameter msg enthält eine AT_Messagebuffer Struktur mit den Daten, die zuletzt von diesem Gerät empfangen wurden. Für jeden Kanal dieses Geräts wird ein Eintrag in der Ergebnistabelle gefüllt und Platz für ein Display-Widget auf der ersten Seite möglichen Seite gesucht. Die Widgetgröße wird auf 30 x 240 Pixel gesetzt und alle Einstellungen mit default Werten gefüllt. Dadurch wird sichergestellt, dass ein neu registriertes Gerät alle seine Kanäle anzeigen kann. In späteren Versionen der Zentrale können dann diese Anzeige-Parameter über ein Setup individuell geändert werden.
So ich glaub es reicht jetzt mit der Theorie, aber mir ist wichtig, dass ihr auch die Struktur des Systems versteht um Fehler leichter zu finden und eventuell selbst Erweiterungen zu entwickeln.
So geht's weiter:
Smarthome Zentrale mit ArduiTouch Teil 5 - Neues GUI und Variation für ESP8266 statt ESP32
Folge verpasst?
Smarthome Zentrale mit ArduiTouch Teil 3 - Aktor Device mit D1Mini und Relais