Smarthome control center with ArduiTouch part 4 - data structure for managing the control center

In this article I would like to explain in detail the data structure used to manage the devices and measured values. All structure definitions can be found in the library file AT_Database.h.

When a device is registered, its characteristics are saved in the device list. The device list is an array of data blocks with the following structure:

typedef // device definition
struct ATDEVICE {
uint8_t activ = 0; // the device defined here exists
uint8_t service = 0; // 0 = ESP-Now preparation if other services later
// be implemented
uint8_t id [6] = {0,0,0,0}; // MAC address of the device
uint16_t device bits = 0; // Bit field with information about the device and data transmission
String name = ""; // device name
String last = ""; // Time stamp for the last successful data transfer

The device number serves as an index in this array. The AT_Database class defines a device list for 32 devices. To save the device data permanently, they are saved in the SPIF file system in the flash of the ESP32.

The following functions of the class are used to work with the device list:

  • boolean readDevices (String fileName); Reads the device list from a file with name fileName  in the SPIFFS. Returns false if an error occurred.
  • boolean writeDevices (String fileName); Writes the device list to a file with name fileName  into the SPIFFS. Returns false if an error occurred.
  • boolean clearDevices (String fileName);  Deletes all devices and saves the result as fileName  in the SPIFFS. Returns false if an error occurred.
  • int16_t findDevice (uint8_t id [6]);  This function searches for a device with the specified one in the device list id  (MAC address). The function returns the index, i.e. the device number of the device. -1 means the device is not in the device list.
  • String getDeviceId (uint8_t device);  Returns the ID of the device with the device number device  back.

If measured values ​​for a registered device arrive, they are saved in the results table. The result table consists of elements with the following structure:

typedef // Structure for storing the measured values
uint8_t valid; // The structure contains a valid measured value
uint8_t step; // is used to save processing steps
uint8_t type; // The type of the stored measurement
uint8_t unit; // The unit of the stored measurement
uint8_t value [4]; // four bytes with an measured value, either 32bit integer or float
// depending on the type. The Boolean type only uses the first byte

The AT_Database class reserves memory space for a result table with 256 entries (32 devices with up to eight channels each). The index for this table is calculated from the device number and channel number.

Index = device number * 32 + channel number

The following functions of the class AT_Database works with the results table:

  • void setResult (uint8_t index, ATDATAPACKET data);  This function updates the data at the index position with the values ​​in the data structure. The structure ATDATAPACKET was defined in the ATMessageBuffer library and is also used for data transmission.
  • ATCURVALUES getResult (uint16_t index);  This function returns the structure described above for the result at the position index in the result table.
  • void setStep (uint8_t step, uint16_t index);  The processing step for the result at the index position in the result table is set to the value step.
  • String getValueString (uint16_t index, uint8_t precision, boolean useunit); Returns the value of the result at the index position in the result table as a string. The precision parameter specifies the number of decimal places for float values. If the parameter useunit is true, the unit name is appended to the string.
  • uint8_t getBooleanValue (uint16_t index);  Returns the boolean of the result at the index location as 0 or 1. Only useful for the Boolean type.
  • boolean isValueOutput (uint16_t index);  Returns true if the type of the result at the index location is an output type, i.e. contains data that are sent from the control center to the device. (e.g. switch).
  • boolean isSwitchOut (uint16_t index);  Similar to the previous function, it only returns true if it is a switch:
  • boolean isValueZero (uint16_t index);  Returns true if the value of the result at index is exactly 0.
  • void toggleResult (uint16_t index);  Switches the result at index vo 0 to 1 or vice versa. Only useful for the Boolean type.
  • int8_t getResponse (int16_t device, uint8_t * buffer, uint8_t * size);Examines all results with an output type for the device device and fills a buffer buffer with a finished message packet, which can then be transferred to the device. The parameter size contains the maximum buffer size and after the function returns the actually used buffer size. The return value is the number of data packets found or -1 if the buffer size was too small.

Another3 structure in this library is used to control the display of the results on the display. There is a list of pages. Each page contains 8 widget entries with the following structure:

typedef // Definition of a Diosplay widget
uint16_t source; // Index to the assigned result
uint8_t status; // Status 0 = not used, 1 = used, 2 = placeholder, 3 = hidden
uint8_t size; // size of the widget 0 = 240x30,1 = 240x60 left
// 2 = 120x60 right 3 = 120x60
uint8_t type; // type of widget, currently only 0 = simple
uint16_t bgcolor; // background color normal
uint16_t bgcolorOn; // background color for buttons when on
uint16_t fontcolor; // font color
uint8_t image; // index of an image (not yet used)
uint8_t precision; // Number of decimal places for measured values
String label = ""; //Labeling

The class AT_Database reserves the space for 32 pages with up to eight widgets each. The following functions work with this table: #

  • int16_t getFreeSlot (uint8_t page, uint8_t size);  This function returns the index for a widget on the page with the size size, which still has space or -1 if there is no space on the page.
  • ATDISPLAYPAGE getPage (uint8_t page);  Returns a list of all widgets on the page.

The function

boolean registerDev (String deviceId, AT_MessageBuffer msg);

registers a device with the Id deviceId if it has not yet been registered. The msg parameter contains an AT_Messagebuffer structure with the data that was last received by this device. For each channel of this device, an entry is filled in the results table and space is searched for a display widget on the first page of the possible page. The widget size is set to 30 x 240 pixels and all settings are filled with default values. This ensures that a newly registered device can display all of its channels. In later versions of the control center, these display parameters can then be changed individually using a setup.

So I think it is enough with the theory, but it is important to me that you also understand the structure of the system in order to find errors more easily and possibly develop extensions yourself.

Projects for advancedSmart home

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN