.. include:: ../../../../macros.txt .. include:: ../../../../units.txt .. _HOW_TO_USE_THE_DATABASE_MODULE: How to Use the Database Module ============================== This How-to shows how to add new entries to the database, and how to read and write database entries. How to Add a Database Entry? ---------------------------- Four steps need to be undertaken to add an entry to the database. First, an identification number (ID) for this database entry must be added to enum ``DATA_BLOCK_ID_e`` in file ``src/app/engine/config/database_cfg.h``. This enumeration value respectively the identification number functions as ``uniqueId`` for each database entry to synchronize database entries with local copies during read and write access to the database. .. note:: The new ID must start with ``DATA_BLOCK_ID_``. Before any source is compiled the build process checks that a database variable is initialized with the matching ID from ``DATA_BLOCK_ID_e``. For the details of the checker implementation see :ref:`database_variable_checking`. In this example the name of the new database entry is **example**, therefore the corresponding ID must be the prefix and the name in uppercase, which gives ``DATA_BLOCK_ID_EXAMPLE``. .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-block-id-start :end-before: example-data-block-id-end :caption: Adding a new element **example** to the ``DATA_BLOCK_ID_e`` enum :name: adding-a-new-element-to-the-data-block-id-e-enum Second, a struct definition of the database entry has to be added in file ``src/app/engine/config/database_cfg.h``. This structure needs to contain a variable ``header`` of type ``DATA_BLOCK_HEADER_s`` at the beginning of the struct. This header contains a ``uniqueID`` for this database entry as well as timestamps. These timestamps (``timestamp`` and ``previousTimestamp``) are automatically updated each time new data is stored in this database entry. The remaining struct consists of all the data needed for the entry. .. note:: The new database entry must start with ``DATA_BLOCK_``. Before any source is compiled the build process checks that a database variable is initialized with the matching ID from ``DATA_BLOCK_ID_e``. For the details of the checker implementation see :ref:`database_variable_checking`. Again, the name of the new database entry is **example**, therefore the corresponding data block must be the prefix followed by the name in uppercase and the ``_s`` suffix as the typedef is a struct, which gives ``DATA_BLOCK_EXAMPLE_s``. .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-block-typedef-start :end-before: example-data-block-typedef-end :caption: Creating a new database struct :name: creating-a-new-database-struct The database checker basically checks that if a database struct is found (something matching ``DATA_BLOCK_(A_Z_0-9)_s``) that it is initialized with a corresponding ID name. Examples: +---------------------------------------+-----------------------------------+ | Struct | Id | +---------------------------------------+-----------------------------------+ | DATA_BLOCK\_\ **EXAMPLE**\ \_s | DATA_BLOCK_ID\_\ **EXAMPLE** | +---------------------------------------+-----------------------------------+ | DATA_BLOCK\_\ **CELL_VOLTAGE**\ \_s | DATA_BLOCK_ID\_\ **CELL_VOLTAGE** | +---------------------------------------+-----------------------------------+ Third, in ``src/app/engine/config/database_cfg.c``, a static variable with the structure type must be declared. In this declaration the ``uniqueId`` of the database header must be initialized with the identification number added in the first step. This structure ``data_blockExample`` contains the actual values of this database entry during once the BMS is running. .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-block-variable-start :end-before: example-data-block-variable-end :caption: Initialization of the static variable inside the database module :name: initialization-of-the-static-variable-inside-the-database-module Last, this declared struct must be linked to the actual database implementation by adding an additional entry to the structure ``DATA_BASE_s data_database[]`` in file ``src/app/engine/config/database_cfg.c`` .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-database-start :end-before: example-data-database-end :caption: Adding the struct to the database :name: adding-the-struct-to-the-database How to Read a Database Entry? ----------------------------- Data inside the database can not be accessed directly. The data from a database entry has to be copied inside a local representation of the requested entry. For the local structure of the database entry, the ``uniqueId`` of the database entry header has to be initialized with the identification number of the requested database entry. Once this is done, a database entry can simply be accessed by calling function ``DATA_READ_DATA()`` and passing the pointer to the local database entry structure. .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-read-data-start :end-before: example-data-read-data-end :caption: Reading a database entry :name: reading-a-database-entry :emphasize-lines: 4 Up to four database entries can be accessed on the same time with one call of ``DATA_READ_DATA()``. .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-read-multiple-data-entries-start :end-before: example-data-read-multiple-data-entries-end :caption: Reading multiple database entries :name: reading-multiple-database-entries :emphasize-lines: 6, 7 How to Write a Database Entry? ------------------------------ It is not possible to directly write data into a database entry. Only the content of a local representation of the requested database entry can be copied into the database. The ``uniqueId`` of the database entry header has to be initialized with the identification number of the requested database entry for the local structure of the database entry. Once this is done, a database entry can be written by calling function ``DATA_WRITE_DATA()`` and passing the pointer to the local database entry structure. Up to four database entries can be written with one call of ``DATA_WRITE_DATA()``. .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-write-data-start :end-before: example-data-write-data-end :caption: Writing a database entry :name: writing-a-database-entry :emphasize-lines: 6 After a call of ``DATA_WRITE_DATA`` the timestamp variables in the database entry header are automatically updated database entry **AND** the local database entry structure. Up to four database entries can be written on the same time with one call of ``DATA_WRITE_DATA()``. .. literalinclude:: ./database_how-to.c :language: C :linenos: :start-after: example-data-write-multiple-data-entries-start :end-before: example-data-write-multiple-data-entries-end :caption: Writing multiple database entries :name: writing-multiple-database-entries :emphasize-lines: 11, 12 Further Reading --------------- Implementation details of the database module are found in :ref:`DATABASE_MODULE`.