LCOV - code coverage report
Current view: top level - include - thingset.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 3 3 100.0 %
Date: 2025-02-03 11:19:13 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 2 50.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) The ThingSet Project Contributors
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: Apache-2.0
       5                 :            :  */
       6                 :            : 
       7                 :            : #ifndef THINGSET_H_
       8                 :            : #define THINGSET_H_
       9                 :            : 
      10                 :            : /**
      11                 :            :  * @file
      12                 :            :  */
      13                 :            : 
      14                 :            : /** @cond INTERNAL_HIDDEN */
      15                 :            : #define JSMN_HEADER
      16                 :            : /** @endcond */
      17                 :            : #include "jsmn.h"
      18                 :            : 
      19                 :            : #include <zephyr/kernel.h>
      20                 :            : 
      21                 :            : #include <zcbor_common.h>
      22                 :            : 
      23                 :            : #include <stdbool.h>
      24                 :            : #include <stddef.h>
      25                 :            : #include <stdint.h>
      26                 :            : 
      27                 :            : /** @cond INTERNAL_HIDDEN */
      28                 :            : #ifndef _ARRAY_SIZE
      29                 :            : /* custom ARRAY_SIZE to avoid redefinition warning if thingset.h is included before Zephr headers */
      30                 :            : #define _ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
      31                 :            : #endif
      32                 :            : /** @endcond */
      33                 :            : 
      34                 :            : #ifdef __cplusplus
      35                 :            : extern "C" {
      36                 :            : #endif
      37                 :            : 
      38                 :            : /* Function codes (binary mode) */
      39                 :            : #define THINGSET_BIN_GET    0x01 /**< Function code for GET request in binary mode. */
      40                 :            : #define THINGSET_BIN_EXEC   0x02 /**< Function code for EXEC request in binary mode. */
      41                 :            : #define THINGSET_BIN_DELETE 0x04 /**< Function code for DELETE request in binary mode. */
      42                 :            : #define THINGSET_BIN_FETCH  0x05 /**< Function code for FETCH request in binary mode. */
      43                 :            : #define THINGSET_BIN_CREATE 0x06 /**< Function code for CREATE request in binary mode. */
      44                 :            : #define THINGSET_BIN_UPDATE 0x07 /**< Function code for UPDATE request in binary mode. */
      45                 :            : #define THINGSET_BIN_DESIRE 0x1D /**< Function code for DESIRE in binary mode. */
      46                 :            : #define THINGSET_BIN_REPORT 0x1F /**< Function code for REPORT in binary mode. */
      47                 :            : 
      48                 :            : /* Function codes (text mode) */
      49                 :            : #define THINGSET_TXT_GET_FETCH '?' /**< Function code for GET and FETCH requests in text mode. */
      50                 :            : #define THINGSET_TXT_EXEC      '!' /**< Function code for EXEC request in text mode. */
      51                 :            : #define THINGSET_TXT_DELETE    '-' /**< Function code for DELETE request in text mode. */
      52                 :            : #define THINGSET_TXT_CREATE    '+' /**< Function code for CREATE request in text mode. */
      53                 :            : #define THINGSET_TXT_UPDATE    '=' /**< Function code for UPDATE request in text mode. */
      54                 :            : #define THINGSET_TXT_DESIRE    '@' /**< Function code for DESIRE in text mode. */
      55                 :            : #define THINGSET_TXT_REPORT    '#' /**< Function code for REPORT in text mode. */
      56                 :            : 
      57                 :            : /* Status codes (success) */
      58                 :            : #define THINGSET_STATUS_CREATED 0x81 /**< Response code for successful CREATE requests. */
      59                 :            : #define THINGSET_STATUS_DELETED 0x82 /**< Response code for successful DELETE requests. */
      60                 :            : #define THINGSET_STATUS_CHANGED 0x84 /**< Response code for successful EXEC/UPDATE requests. */
      61                 :            : #define THINGSET_STATUS_CONTENT 0x85 /**< Response code for successful GET/FETCH requests. */
      62                 :            : 
      63                 :            : /* Status codes (client errors) */
      64                 :            : #define THINGSET_ERR_BAD_REQUEST        0xA0 /**< Error code: Bad request. */
      65                 :            : #define THINGSET_ERR_UNAUTHORIZED       0xA1 /**< Error code: Authentication needed. */
      66                 :            : #define THINGSET_ERR_FORBIDDEN          0xA3 /**< Error code: Access forbidden. */
      67                 :            : #define THINGSET_ERR_NOT_FOUND          0xA4 /**< Error code: Data object not found. */
      68                 :            : #define THINGSET_ERR_METHOD_NOT_ALLOWED 0xA5 /**< Error code: Method not allowed. */
      69                 :            : #define THINGSET_ERR_REQUEST_INCOMPLETE 0xA8 /**< Error code: Request incomplete. */
      70                 :            : #define THINGSET_ERR_CONFLICT           0xA9 /**< Error code: Conflict. */
      71                 :            : #define THINGSET_ERR_REQUEST_TOO_LARGE  0xAD /**< Error code: Request not fitting into buffer. */
      72                 :            : #define THINGSET_ERR_UNSUPPORTED_FORMAT 0xAF /**< Error code: Format for an item not supported. */
      73                 :            : 
      74                 :            : /* Status codes (server errors) */
      75                 :            : #define THINGSET_ERR_INTERNAL_SERVER_ERR 0xC0 /**< Error code: Generic catch-all response. */
      76                 :            : #define THINGSET_ERR_NOT_IMPLEMENTED     0xC1 /**< Error code: Request method not implemented. */
      77                 :            : #define THINGSET_ERR_GATEWAY_TIMEOUT     0xC4 /**< Error code: Node cannot be reached. */
      78                 :            : #define THINGSET_ERR_NOT_A_GATEWAY       0xC5 /**< Error code: Node is not a gateway. */
      79                 :            : 
      80                 :            : /* Status codes (ThingSet specific errors) */
      81                 :            : #define THINGSET_ERR_RESPONSE_TOO_LARGE 0xE1 /**< Error code: Response not fitting into buffer. */
      82                 :            : 
      83                 :            : /* Internal status codes */
      84                 :            : #define THINGSET_ERR_DESERIALIZATION_FINISHED 0xF0 /**< Internal indication: Parsing finished. */
      85                 :            : 
      86                 :            : #define THINGSET_ERROR(code) (code >= 0xA0) /**< Check if provided code indicates an error. */
      87                 :            : #define THINGSET_SUCCESS(code) \
      88                 :            :     (code >= 0x80 && code < 0xA0) /**< Check if provided code indicates success. */
      89                 :            : 
      90                 :            : /* Reserved data object IDs */
      91                 :            : #define THINGSET_ID_ROOT        0x00 /**< Root object for a node (empty path) */
      92                 :            : #define THINGSET_ID_TIME        0x10 /**< Unix timestamp `t_s` */
      93                 :            : #define THINGSET_ID_IDS         0x16 /**< `_Ids` overlay */
      94                 :            : #define THINGSET_ID_PATHS       0x17 /**< `_Paths` overlay */
      95                 :            : #define THINGSET_ID_METADATAURL 0x18 /**< URL for extended metadata information: `cMetadataURL` */
      96                 :            : #define THINGSET_ID_METADATA    0x19 /**< `_Metadata` overlay */
      97                 :            : #define THINGSET_ID_NODEID      0x1D /**< String containing the node ID: `cNodeID` */
      98                 :            : 
      99                 :            : /*
     100                 :            :  * Macros for defining data object array elements.
     101                 :            :  */
     102                 :            : 
     103                 :            : /**
     104                 :            :  * Initialize struct thingset_data_object to expose `bool` variable via ThingSet.
     105                 :            :  *
     106                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     107                 :            :  * @param id ID of this data object
     108                 :            :  * @param name String literal with the data object name
     109                 :            :  * @param bool_ptr Pointer to the `bool` variable
     110                 :            :  * @param access Flags to define read/write access for this data object
     111                 :            :  * @param subsets Subset(s) this data object belongs to
     112                 :            :  */
     113                 :            : #define THINGSET_ITEM_BOOL(parent_id, id, name, bool_ptr, access, subsets) \
     114                 :            :     { \
     115                 :            :         parent_id, id, name, { .b = bool_ptr }, THINGSET_TYPE_BOOL, 0, access, subsets \
     116                 :            :     }
     117                 :            : 
     118                 :            : /**
     119                 :            :  * Initialize struct thingset_data_object to expose `uint8_t` variable via ThingSet.
     120                 :            :  *
     121                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     122                 :            :  * @param id ID of this data object
     123                 :            :  * @param name String literal with the data object name
     124                 :            :  * @param uint8_ptr Pointer to the `uint8_t` variable
     125                 :            :  * @param access Flags to define read/write access for this data object
     126                 :            :  * @param subsets Subset(s) this data object belongs to
     127                 :            :  */
     128                 :            : #define THINGSET_ITEM_UINT8(parent_id, id, name, uint8_ptr, access, subsets) \
     129                 :            :     { \
     130                 :            :         parent_id, id, name, { .u8 = uint8_ptr }, THINGSET_TYPE_U8, 0, access, subsets \
     131                 :            :     }
     132                 :            : 
     133                 :            : /**
     134                 :            :  * Initialize struct thingset_data_object to expose `int8_t` variable via ThingSet.
     135                 :            :  *
     136                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     137                 :            :  * @param id ID of this data object
     138                 :            :  * @param name String literal with the data object name
     139                 :            :  * @param int8_ptr Pointer to the `int8_t` variable
     140                 :            :  * @param access Flags to define read/write access for this data object
     141                 :            :  * @param subsets Subset(s) this data object belongs to
     142                 :            :  */
     143                 :            : #define THINGSET_ITEM_INT8(parent_id, id, name, int8_ptr, access, subsets) \
     144                 :            :     { \
     145                 :            :         parent_id, id, name, { .i8 = int8_ptr }, THINGSET_TYPE_I8, 0, access, subsets \
     146                 :            :     }
     147                 :            : 
     148                 :            : /**
     149                 :            :  * Initialize struct thingset_data_object to expose `uint16_t` variable via ThingSet.
     150                 :            :  *
     151                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     152                 :            :  * @param id ID of this data object
     153                 :            :  * @param name String literal with the data object name
     154                 :            :  * @param uint16_ptr Pointer to the `uint16_t` variable
     155                 :            :  * @param access Flags to define read/write access for this data object
     156                 :            :  * @param subsets Subset(s) this data object belongs to
     157                 :            :  */
     158                 :            : #define THINGSET_ITEM_UINT16(parent_id, id, name, uint16_ptr, access, subsets) \
     159                 :            :     { \
     160                 :            :         parent_id, id, name, { .u16 = uint16_ptr }, THINGSET_TYPE_U16, 0, access, subsets \
     161                 :            :     }
     162                 :            : 
     163                 :            : /**
     164                 :            :  * Initialize struct thingset_data_object to expose `int16_t` variable via ThingSet.
     165                 :            :  *
     166                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     167                 :            :  * @param id ID of this data object
     168                 :            :  * @param name String literal with the data object name
     169                 :            :  * @param int16_ptr Pointer to the `int16_t` variable
     170                 :            :  * @param access Flags to define read/write access for this data object
     171                 :            :  * @param subsets Subset(s) this data object belongs to
     172                 :            :  */
     173                 :            : #define THINGSET_ITEM_INT16(parent_id, id, name, int16_ptr, access, subsets) \
     174                 :            :     { \
     175                 :            :         parent_id, id, name, { .i16 = int16_ptr }, THINGSET_TYPE_I16, 0, access, subsets \
     176                 :            :     }
     177                 :            : 
     178                 :            : /**
     179                 :            :  * Initialize struct thingset_data_object to expose `uint32_t` variable via ThingSet.
     180                 :            :  *
     181                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     182                 :            :  * @param id ID of this data object
     183                 :            :  * @param name String literal with the data object name
     184                 :            :  * @param uint32_ptr Pointer to the `uint32_t` variable
     185                 :            :  * @param access Flags to define read/write access for this data object
     186                 :            :  * @param subsets Subset(s) this data object belongs to
     187                 :            :  */
     188                 :            : #define THINGSET_ITEM_UINT32(parent_id, id, name, uint32_ptr, access, subsets) \
     189                 :            :     { \
     190                 :            :         parent_id, id, name, { .u32 = uint32_ptr }, THINGSET_TYPE_U32, 0, access, subsets \
     191                 :            :     }
     192                 :            : 
     193                 :            : /**
     194                 :            :  * Initialize struct thingset_data_object to expose `int32_t` variable via ThingSet.
     195                 :            :  *
     196                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     197                 :            :  * @param id ID of this data object
     198                 :            :  * @param name String literal with the data object name
     199                 :            :  * @param int32_ptr Pointer to the `int32_t` variable
     200                 :            :  * @param access Flags to define read/write access for this data object
     201                 :            :  * @param subsets Subset(s) this data object belongs to
     202                 :            :  */
     203                 :            : #define THINGSET_ITEM_INT32(parent_id, id, name, int32_ptr, access, subsets) \
     204                 :            :     { \
     205                 :            :         parent_id, id, name, { .i32 = int32_ptr }, THINGSET_TYPE_I32, 0, access, subsets \
     206                 :            :     }
     207                 :            : 
     208                 :            : /**
     209                 :            :  * Initialize struct thingset_data_object to expose `uint64_t` variable via ThingSet.
     210                 :            :  *
     211                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     212                 :            :  * @param id ID of this data object
     213                 :            :  * @param name String literal with the data object name
     214                 :            :  * @param uint64_ptr Pointer to the `uint64_t` variable
     215                 :            :  * @param access Flags to define read/write access for this data object
     216                 :            :  * @param subsets Subset(s) this data object belongs to
     217                 :            :  */
     218                 :            : #define THINGSET_ITEM_UINT64(parent_id, id, name, uint64_ptr, access, subsets) \
     219                 :            :     { \
     220                 :            :         parent_id, id, name, { .u64 = uint64_ptr }, THINGSET_TYPE_U64, 0, access, subsets \
     221                 :            :     }
     222                 :            : 
     223                 :            : /**
     224                 :            :  * Initialize struct thingset_data_object to expose `int64_t` variable via ThingSet.
     225                 :            :  *
     226                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     227                 :            :  * @param id ID of this data object
     228                 :            :  * @param name String literal with the data object name
     229                 :            :  * @param int64_ptr Pointer to the `int64_t` variable
     230                 :            :  * @param access Flags to define read/write access for this data object
     231                 :            :  * @param subsets Subset(s) this data object belongs to
     232                 :            :  */
     233                 :            : #define THINGSET_ITEM_INT64(parent_id, id, name, int64_ptr, access, subsets) \
     234                 :            :     { \
     235                 :            :         parent_id, id, name, { .i64 = int64_ptr }, THINGSET_TYPE_I64, 0, access, subsets \
     236                 :            :     }
     237                 :            : 
     238                 :            : /**
     239                 :            :  * Initialize struct thingset_data_object to expose `float` variable via ThingSet.
     240                 :            :  *
     241                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     242                 :            :  * @param id ID of this data object
     243                 :            :  * @param name String literal with the data object name
     244                 :            :  * @param float_ptr Pointer to the `float` variable
     245                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
     246                 :            :  * @param access Flags to define read/write access for this data object
     247                 :            :  * @param subsets Subset(s) this data object belongs to
     248                 :            :  */
     249                 :            : #define THINGSET_ITEM_FLOAT(parent_id, id, name, float_ptr, decimals, access, subsets) \
     250                 :            :     { \
     251                 :            :         parent_id, id, name, { .f32 = float_ptr }, THINGSET_TYPE_F32, decimals, access, subsets \
     252                 :            :     }
     253                 :            : 
     254                 :            : /**
     255                 :            :  * Initialize struct thingset_data_object to expose decimal fraction variable via ThingSet.
     256                 :            :  *
     257                 :            :  * The mantissa is internally stored as int32_t.
     258                 :            :  * The value is converted into a float (JSON) or decimal fraction type (CBOR) for the protocol,
     259                 :            :  * based on the specified number of decimal digits.
     260                 :            :  *
     261                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     262                 :            :  * @param id ID of this data object
     263                 :            :  * @param name String literal with the data object name
     264                 :            :  * @param mantissa_ptr Pointer to the `int32_t` variable
     265                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
     266                 :            :  * @param access Flags to define read/write access for this data object
     267                 :            :  * @param subsets Subset(s) this data object belongs to
     268                 :            :  */
     269                 :            : #define THINGSET_ITEM_DECFRAC(parent_id, id, name, mantissa_ptr, decimals, access, subsets) \
     270                 :            :     { \
     271                 :            :         parent_id, id, name, { .i32 = mantissa_ptr }, THINGSET_TYPE_DECFRAC, decimals, access, \
     272                 :            :             subsets \
     273                 :            :     }
     274                 :            : 
     275                 :            : /**
     276                 :            :  * Initialize struct thingset_data_object to expose a null-terminated character string buffer via
     277                 :            :  * ThingSet.
     278                 :            :  *
     279                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     280                 :            :  * @param id ID of this data object
     281                 :            :  * @param name String literal with the data object name
     282                 :            :  * @param char_ptr Pointer to the `char` buffer
     283                 :            :  * @param buf_size Maximum length of the buffer including the null-termination character
     284                 :            :  * @param access Flags to define read/write access for this data object
     285                 :            :  * @param subsets Subset(s) this data object belongs to
     286                 :            :  */
     287                 :            : #define THINGSET_ITEM_STRING(parent_id, id, name, char_ptr, buf_size, access, subsets) \
     288                 :            :     { \
     289                 :            :         parent_id, id, name, { .str = char_ptr }, THINGSET_TYPE_STRING, buf_size, access, subsets \
     290                 :            :     }
     291                 :            : 
     292                 :            : /**
     293                 :            :  * Initialize struct thingset_data_object to expose a byte buffer containing arbitrary binary data
     294                 :            :  * via ThingSet.
     295                 :            :  *
     296                 :            :  * In contrast to string buffers, no null-termination is used.
     297                 :            :  *
     298                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     299                 :            :  * @param id ID of this data object
     300                 :            :  * @param name String literal with the data object name
     301                 :            :  * @param bytes_ptr Pointer to the struct thingset_bytes object
     302                 :            :  * @param access Flags to define read/write access for this data object
     303                 :            :  * @param subsets Subset(s) this data object belongs to
     304                 :            :  */
     305                 :            : #define THINGSET_ITEM_BYTES(parent_id, id, name, bytes_ptr, access, subsets) \
     306                 :            :     { \
     307                 :            :         parent_id, id, name, { .bytes = bytes_ptr }, THINGSET_TYPE_BYTES, 0, access, subsets \
     308                 :            :     }
     309                 :            : 
     310                 :            : /**
     311                 :            :  * Initialize struct thingset_data_object to expose a function with `void` return value as an
     312                 :            :  * executable item via ThingSet.
     313                 :            :  *
     314                 :            :  * If the function should have input parameters, child object with this object as their parent_id
     315                 :            :  * have to be defined.
     316                 :            :  *
     317                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     318                 :            :  * @param id ID of this data object
     319                 :            :  * @param name String literal with the data object name
     320                 :            :  * @param void_fn_ptr Pointer to the `void` function
     321                 :            :  * @param access Flags to define read/write access for this data object
     322                 :            :  */
     323                 :            : #define THINGSET_FN_VOID(parent_id, id, name, void_fn_ptr, access) \
     324                 :            :     { \
     325                 :            :         parent_id, id, name, { .void_fn = void_fn_ptr }, THINGSET_TYPE_FN_VOID, 0, access, 0 \
     326                 :            :     }
     327                 :            : 
     328                 :            : /**
     329                 :            :  * Initialize struct thingset_data_object to expose a function with `int32_t` return value as an
     330                 :            :  * executable item via ThingSet.
     331                 :            :  *
     332                 :            :  * If the function should have input parameters, child object with this object as their parent_id
     333                 :            :  * have to be defined.
     334                 :            :  *
     335                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     336                 :            :  * @param id ID of this data object
     337                 :            :  * @param name String literal with the data object name
     338                 :            :  * @param int32_fn_ptr Pointer to the `int32_t` function
     339                 :            :  * @param access Flags to define read/write access for this data object
     340                 :            :  */
     341                 :            : #define THINGSET_FN_INT32(parent_id, id, name, int32_fn_ptr, access) \
     342                 :            :     { \
     343                 :            :         parent_id, id, name, { .i32_fn = int32_fn_ptr }, THINGSET_TYPE_FN_I32, 0, access, 0 \
     344                 :            :     }
     345                 :            : 
     346                 :            : /**
     347                 :            :  * Initialize struct thingset_data_object to expose an array of simple values via ThingSet.
     348                 :            :  *
     349                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     350                 :            :  * @param id ID of this data object
     351                 :            :  * @param name String literal with the data object name
     352                 :            :  * @param array_ptr Pointer to the struct thingset_array object
     353                 :            :  * @param access Flags to define read/write access for this data object
     354                 :            :  * @param subsets Subset(s) this data object belongs to
     355                 :            :  */
     356                 :            : #define THINGSET_ITEM_ARRAY(parent_id, id, name, array_ptr, access, subsets) \
     357                 :            :     { \
     358                 :            :         parent_id, id, name, { .array = array_ptr }, THINGSET_TYPE_ARRAY, 0, access, subsets \
     359                 :            :     }
     360                 :            : 
     361                 :            : /**
     362                 :            :  * Initialize struct thingset_data_object to expose records of similar data via ThingSet.
     363                 :            :  *
     364                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     365                 :            :  * @param id ID of this data object
     366                 :            :  * @param name String literal with the data object name
     367                 :            :  * @param records_ptr Pointer to the struct thingset_records object
     368                 :            :  * @param access Flags to define read/write access for this data object
     369                 :            :  * @param subsets Subset(s) this data object belongs to
     370                 :            :  */
     371                 :            : #define THINGSET_RECORDS(parent_id, id, name, records_ptr, access, subsets) \
     372                 :            :     { \
     373                 :            :         parent_id, id, name, { .records = records_ptr }, THINGSET_TYPE_RECORDS, 0, access, subsets \
     374                 :            :     }
     375                 :            : 
     376                 :            : /**
     377                 :            :  * Initialize struct thingset_data_object to expose dynamic records of similar data via ThingSet.
     378                 :            :  *
     379                 :            :  * In contrast to normal records, dynamic records don't keep the data for all records in memory.
     380                 :            :  * Instead, the data must be retrieved dynamically in the THINGSET_CALLBACK_PRE_READ callback and
     381                 :            :  * stored in the referenced struct object. This type of records can be used to store large amounts
     382                 :            :  * of data in an external flash or EEPROM and only read the data on demand.
     383                 :            :  *
     384                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     385                 :            :  * @param id ID of this data object
     386                 :            :  * @param name String literal with the data object name
     387                 :            :  * @param records_ptr Pointer to the struct thingset_records object
     388                 :            :  * @param access Flags to define read/write access for this data object
     389                 :            :  * @param subsets Subset(s) this data object belongs to
     390                 :            :  */
     391                 :            : #define THINGSET_DYN_RECORDS(parent_id, id, name, records_ptr, access, subsets) \
     392                 :            :     { \
     393                 :            :         parent_id, id, name, { .records = records_ptr }, THINGSET_TYPE_RECORDS, \
     394                 :            :             THINGSET_DETAIL_DYN_RECORDS, access, subsets \
     395                 :            :     }
     396                 :            : 
     397                 :            : /**
     398                 :            :  * Initialize struct thingset_data_object to expose a subset item via ThingSet.
     399                 :            :  *
     400                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     401                 :            :  * @param id ID of this data object
     402                 :            :  * @param name String literal with the data object name
     403                 :            :  * @param subset_flag Single subset flag to be used
     404                 :            :  * @param access Flags to define read/write access for this data object
     405                 :            :  */
     406                 :            : #define THINGSET_SUBSET(parent_id, id, name, subset_flag, access) \
     407                 :            :     { \
     408                 :            :         parent_id, id, name, { .subset = subset_flag }, THINGSET_TYPE_SUBSET, 0, access, 0 \
     409                 :            :     }
     410                 :            : 
     411                 :            : /**
     412                 :            :  * Initialize struct thingset_data_object to group hierarchical data via ThingSet.
     413                 :            :  *
     414                 :            :  * @param parent_id ID of the parent data object of type `GROUP`
     415                 :            :  * @param id ID of this data object
     416                 :            :  * @param name String literal with the data object name
     417                 :            :  * @param update_callback Pointer to a function to be called before/after read/write operations.
     418                 :            :  */
     419                 :            : #define THINGSET_GROUP(parent_id, id, name, update_callback) \
     420                 :            :     { \
     421                 :            :         parent_id, id, name, { .group_callback = update_callback }, THINGSET_TYPE_GROUP, 0, \
     422                 :            :             THINGSET_READ_MASK \
     423                 :            :     }
     424                 :            : 
     425                 :            : /**
     426                 :            :  * Initialize struct thingset_data_object to expose `bool` record item.
     427                 :            :  *
     428                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     429                 :            :  * @param id ID of this data object (same for all records of this kind)
     430                 :            :  * @param name String literal with the data object name
     431                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     432                 :            :  * @param struct_member Struct member of type `bool` used for this item
     433                 :            :  */
     434                 :            : #define THINGSET_RECORD_ITEM_BOOL(parent_id, id, name, struct_type, struct_member) \
     435                 :            :     { \
     436                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     437                 :            :             THINGSET_TYPE_BOOL, 0, THINGSET_READ_MASK \
     438                 :            :     }
     439                 :            : 
     440                 :            : /**
     441                 :            :  * Initialize struct thingset_data_object to expose `uint64_t` record item.
     442                 :            :  *
     443                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     444                 :            :  * @param id ID of this data object (same for all records of this kind)
     445                 :            :  * @param name String literal with the data object name
     446                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     447                 :            :  * @param struct_member Struct member of type `uint64_t` used for this item
     448                 :            :  */
     449                 :            : #define THINGSET_RECORD_ITEM_UINT64(parent_id, id, name, struct_type, struct_member) \
     450                 :            :     { \
     451                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     452                 :            :             THINGSET_TYPE_U64, 0, THINGSET_READ_MASK \
     453                 :            :     }
     454                 :            : 
     455                 :            : /**
     456                 :            :  * Initialize struct thingset_data_object to expose `int64_t` record item.
     457                 :            :  *
     458                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     459                 :            :  * @param id ID of this data object (same for all records of this kind)
     460                 :            :  * @param name String literal with the data object name
     461                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     462                 :            :  * @param struct_member Struct member of type `int64_t` used for this item
     463                 :            :  */
     464                 :            : #define THINGSET_RECORD_ITEM_INT64(parent_id, id, name, struct_type, struct_member) \
     465                 :            :     { \
     466                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     467                 :            :             THINGSET_TYPE_I64, 0, THINGSET_READ_MASK \
     468                 :            :     }
     469                 :            : 
     470                 :            : /**
     471                 :            :  * Initialize struct thingset_data_object to expose `uint32_t` record item.
     472                 :            :  *
     473                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     474                 :            :  * @param id ID of this data object (same for all records of this kind)
     475                 :            :  * @param name String literal with the data object name
     476                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     477                 :            :  * @param struct_member Struct member of type `uint32_t` used for this item
     478                 :            :  */
     479                 :            : #define THINGSET_RECORD_ITEM_UINT32(parent_id, id, name, struct_type, struct_member) \
     480                 :            :     { \
     481                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     482                 :            :             THINGSET_TYPE_U32, 0, THINGSET_READ_MASK \
     483                 :            :     }
     484                 :            : 
     485                 :            : /**
     486                 :            :  * Initialize struct thingset_data_object to expose `int32_t` record item.
     487                 :            :  *
     488                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     489                 :            :  * @param id ID of this data object (same for all records of this kind)
     490                 :            :  * @param name String literal with the data object name
     491                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     492                 :            :  * @param struct_member Struct member of type `int32_t` used for this item
     493                 :            :  */
     494                 :            : #define THINGSET_RECORD_ITEM_INT32(parent_id, id, name, struct_type, struct_member) \
     495                 :            :     { \
     496                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     497                 :            :             THINGSET_TYPE_I32, 0, THINGSET_READ_MASK \
     498                 :            :     }
     499                 :            : 
     500                 :            : /**
     501                 :            :  * Initialize struct thingset_data_object to expose `uint16_t` record item.
     502                 :            :  *
     503                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     504                 :            :  * @param id ID of this data object (same for all records of this kind)
     505                 :            :  * @param name String literal with the data object name
     506                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     507                 :            :  * @param struct_member Struct member of type `uint16_t` used for this item
     508                 :            :  */
     509                 :            : #define THINGSET_RECORD_ITEM_UINT16(parent_id, id, name, struct_type, struct_member) \
     510                 :            :     { \
     511                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     512                 :            :             THINGSET_TYPE_U16, 0, THINGSET_READ_MASK \
     513                 :            :     }
     514                 :            : 
     515                 :            : /**
     516                 :            :  * Initialize struct thingset_data_object to expose `int16_t` record item.
     517                 :            :  *
     518                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     519                 :            :  * @param id ID of this data object (same for all records of this kind)
     520                 :            :  * @param name String literal with the data object name
     521                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     522                 :            :  * @param struct_member Struct member of type `int16_t` used for this item
     523                 :            :  */
     524                 :            : #define THINGSET_RECORD_ITEM_INT16(parent_id, id, name, struct_type, struct_member) \
     525                 :            :     { \
     526                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     527                 :            :             THINGSET_TYPE_I16, 0, THINGSET_READ_MASK \
     528                 :            :     }
     529                 :            : 
     530                 :            : /**
     531                 :            :  * Initialize struct thingset_data_object to expose `uint8_t` record item.
     532                 :            :  *
     533                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     534                 :            :  * @param id ID of this data object (same for all records of this kind)
     535                 :            :  * @param name String literal with the data object name
     536                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     537                 :            :  * @param struct_member Struct member of type `uint8_t` used for this item
     538                 :            :  */
     539                 :            : #define THINGSET_RECORD_ITEM_UINT8(parent_id, id, name, struct_type, struct_member) \
     540                 :            :     { \
     541                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, THINGSET_TYPE_U8, \
     542                 :            :             0, THINGSET_READ_MASK \
     543                 :            :     }
     544                 :            : 
     545                 :            : /**
     546                 :            :  * Initialize struct thingset_data_object to expose `int8_t` record item.
     547                 :            :  *
     548                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     549                 :            :  * @param id ID of this data object (same for all records of this kind)
     550                 :            :  * @param name String literal with the data object name
     551                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     552                 :            :  * @param struct_member Struct member of type `int8_t` used for this item
     553                 :            :  */
     554                 :            : #define THINGSET_RECORD_ITEM_INT8(parent_id, id, name, struct_type, struct_member) \
     555                 :            :     { \
     556                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, THINGSET_TYPE_I8, \
     557                 :            :             0, THINGSET_READ_MASK \
     558                 :            :     }
     559                 :            : 
     560                 :            : /**
     561                 :            :  * Initialize struct thingset_data_object to expose `float` record item.
     562                 :            :  *
     563                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     564                 :            :  * @param id ID of this data object (same for all records of this kind)
     565                 :            :  * @param name String literal with the data object name
     566                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     567                 :            :  * @param struct_member Struct member of type `float` used for this item
     568                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
     569                 :            :  */
     570                 :            : #define THINGSET_RECORD_ITEM_FLOAT(parent_id, id, name, struct_type, struct_member, decimals) \
     571                 :            :     { \
     572                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     573                 :            :             THINGSET_TYPE_F32, decimals, THINGSET_READ_MASK \
     574                 :            :     }
     575                 :            : 
     576                 :            : /**
     577                 :            :  * Initialize struct thingset_data_object to expose decimal fraction record item.
     578                 :            :  *
     579                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     580                 :            :  * @param id ID of this data object (same for all records of this kind)
     581                 :            :  * @param name String literal with the data object name
     582                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     583                 :            :  * @param struct_member Struct member of type `int32_t` used as the mantissa for this item
     584                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
     585                 :            :  */
     586                 :            : #define THINGSET_RECORD_ITEM_DECFRAC(parent_id, id, name, struct_type, struct_member, decimals) \
     587                 :            :     { \
     588                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     589                 :            :             THINGSET_TYPE_DECFRAC, decimals, THINGSET_READ_MASK \
     590                 :            :     }
     591                 :            : 
     592                 :            : /**
     593                 :            :  * Initialize struct thingset_data_object to expose a null-terminated character string buffer
     594                 :            :  * record item.
     595                 :            :  *
     596                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     597                 :            :  * @param id ID of this data object (same for all records of this kind)
     598                 :            :  * @param name String literal with the data object name
     599                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
     600                 :            :  * @param struct_member Struct member of type `char *` used for this item
     601                 :            :  * @param buf_size Maximum length of the buffer including the null-termination character
     602                 :            :  */
     603                 :            : #define THINGSET_RECORD_ITEM_STRING(parent_id, id, name, struct_type, struct_member, buf_size) \
     604                 :            :     { \
     605                 :            :         parent_id, id, name, { .offset = offsetof(struct_type, struct_member) }, \
     606                 :            :             THINGSET_TYPE_STRING, buf_size, THINGSET_READ_MASK \
     607                 :            :     }
     608                 :            : 
     609                 :            : /**
     610                 :            :  * Initialize struct thingset_data_object to expose an array record item.
     611                 :            :  *
     612                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     613                 :            :  * @param id ID of this data object (same for all records of this kind)
     614                 :            :  * @param name String literal with the data object name
     615                 :            :  * @param array_ptr Pointer to the struct thingset_array object
     616                 :            :  */
     617                 :            : #define THINGSET_RECORD_ITEM_ARRAY(parent_id, id, name, array_ptr) \
     618                 :            :     { \
     619                 :            :         parent_id, id, name, { .array = array_ptr }, THINGSET_TYPE_ARRAY, 0, THINGSET_READ_MASK \
     620                 :            :     }
     621                 :            : 
     622                 :            : /**
     623                 :            :  * Initialize struct thingset_data_object to expose a nested record item.
     624                 :            :  *
     625                 :            :  * @param parent_id ID of the parent data object of type `RECORDS`
     626                 :            :  * @param id ID of this data object (same for all records of this kind)
     627                 :            :  * @param name String literal with the data object name
     628                 :            :  * @param records_ptr Pointer to the struct thingset_records object
     629                 :            :  */
     630                 :            : #define THINGSET_RECORD_ITEM_RECORD(parent_id, id, name, records_ptr) \
     631                 :            :     { \
     632                 :            :         parent_id, id, name, { .records = records_ptr }, THINGSET_TYPE_RECORDS, 0, \
     633                 :            :             THINGSET_READ_MASK \
     634                 :            :     }
     635                 :            : 
     636                 :            : /*
     637                 :            :  * Macros for defining data objects using Zephyr iterable sections.
     638                 :            :  *
     639                 :            :  * These macros can be used to populate the data objects array from multiple independent files.
     640                 :            :  *
     641                 :            :  * See also: https://docs.zephyrproject.org/latest/kernel/iterable_sections/index.html
     642                 :            :  */
     643                 :            : 
     644                 :            : /** @cond INTERNAL_HIDDEN */
     645                 :            : 
     646                 :            : #ifdef CONFIG_THINGSET_IMMUTABLE_OBJECTS
     647                 :            : #define MAYBE_CONST const
     648                 :            : #else
     649                 :            : #define MAYBE_CONST
     650                 :            : #endif
     651                 :            : 
     652                 :            : #define _THINGSET_ADD_ITERABLE_SECTION(type, parent_id, id, ...) \
     653                 :            :     MAYBE_CONST STRUCT_SECTION_ITERABLE(thingset_data_object, _CONCAT(obj_, id)) = \
     654                 :            :         _CONCAT(THINGSET_, type)(parent_id, id, __VA_ARGS__)
     655                 :            : 
     656                 :            : /** @endcond */
     657                 :            : 
     658                 :            : /**
     659                 :            :  * Add data item for `bool` variable to global iterable section.
     660                 :            :  *
     661                 :            :  * See #THINGSET_ITEM_BOOL for parameter description.
     662                 :            :  */
     663                 :            : #define THINGSET_ADD_ITEM_BOOL(parent_id, id, ...) \
     664                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_BOOL, parent_id, id, __VA_ARGS__)
     665                 :            : 
     666                 :            : /**
     667                 :            :  * Add data item for `uint64_t` variable to global iterable section.
     668                 :            :  *
     669                 :            :  * See #THINGSET_ITEM_UINT64 for parameter description.
     670                 :            :  */
     671                 :            : #define THINGSET_ADD_ITEM_UINT64(parent_id, id, ...) \
     672                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_UINT64, parent_id, id, __VA_ARGS__)
     673                 :            : 
     674                 :            : /**
     675                 :            :  * Add data item for `int64_t` variable to global iterable section.
     676                 :            :  *
     677                 :            :  * See #THINGSET_ITEM_INT64 for parameter description.
     678                 :            :  */
     679                 :            : #define THINGSET_ADD_ITEM_INT64(parent_id, id, ...) \
     680                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_INT64, parent_id, id, __VA_ARGS__)
     681                 :            : 
     682                 :            : /**
     683                 :            :  * Add data item for `uint32_t` variable to global iterable section.
     684                 :            :  *
     685                 :            :  * See #THINGSET_ITEM_UINT32 for parameter description.
     686                 :            :  */
     687                 :            : #define THINGSET_ADD_ITEM_UINT32(parent_id, id, ...) \
     688                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_UINT32, parent_id, id, __VA_ARGS__)
     689                 :            : 
     690                 :            : /**
     691                 :            :  * Add data item for `int32_t` variable to global iterable section.
     692                 :            :  *
     693                 :            :  * See #THINGSET_ITEM_INT32 for parameter description.
     694                 :            :  */
     695                 :            : #define THINGSET_ADD_ITEM_INT32(parent_id, id, ...) \
     696                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_INT32, parent_id, id, __VA_ARGS__)
     697                 :            : 
     698                 :            : /**
     699                 :            :  * Add data item for `uint16_t` variable to global iterable section.
     700                 :            :  *
     701                 :            :  * See #THINGSET_ITEM_UINT16 for parameter description.
     702                 :            :  */
     703                 :            : #define THINGSET_ADD_ITEM_UINT16(parent_id, id, ...) \
     704                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_UINT16, parent_id, id, __VA_ARGS__)
     705                 :            : 
     706                 :            : /**
     707                 :            :  * Add data item for `int16_t` variable to global iterable section.
     708                 :            :  *
     709                 :            :  * See #THINGSET_ITEM_INT16 for parameter description.
     710                 :            :  */
     711                 :            : #define THINGSET_ADD_ITEM_INT16(parent_id, id, ...) \
     712                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_INT16, parent_id, id, __VA_ARGS__)
     713                 :            : 
     714                 :            : /**
     715                 :            :  * Add data item for `uint8_t` variable to global iterable section.
     716                 :            :  *
     717                 :            :  * See #THINGSET_ITEM_UINT8 for parameter description.
     718                 :            :  */
     719                 :            : #define THINGSET_ADD_ITEM_UINT8(parent_id, id, ...) \
     720                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_UINT8, parent_id, id, __VA_ARGS__)
     721                 :            : 
     722                 :            : /**
     723                 :            :  * Add data item for `int8_t` variable to global iterable section.
     724                 :            :  *
     725                 :            :  * See #THINGSET_ITEM_INT8 for parameter description.
     726                 :            :  */
     727                 :            : #define THINGSET_ADD_ITEM_INT8(parent_id, id, ...) \
     728                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_INT8, parent_id, id, __VA_ARGS__)
     729                 :            : 
     730                 :            : /**
     731                 :            :  * Add data item for `float` variable to global iterable section.
     732                 :            :  *
     733                 :            :  * See #THINGSET_ITEM_FLOAT for parameter description.
     734                 :            :  */
     735                 :            : #define THINGSET_ADD_ITEM_FLOAT(parent_id, id, ...) \
     736                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_FLOAT, parent_id, id, __VA_ARGS__)
     737                 :            : 
     738                 :            : /**
     739                 :            :  * Add data item for decimal fraction variable to global iterable section.
     740                 :            :  *
     741                 :            :  * See #THINGSET_ITEM_DECFRAC for parameter description.
     742                 :            :  */
     743                 :            : #define THINGSET_ADD_ITEM_DECFRAC(parent_id, id, ...) \
     744                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_DECFRAC, parent_id, id, __VA_ARGS__)
     745                 :            : 
     746                 :            : /**
     747                 :            :  * Add data item for character string buffer to global iterable section.
     748                 :            :  *
     749                 :            :  * See #THINGSET_ITEM_STRING for parameter description.
     750                 :            :  */
     751                 :            : #define THINGSET_ADD_ITEM_STRING(parent_id, id, ...) \
     752                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_STRING, parent_id, id, __VA_ARGS__)
     753                 :            : 
     754                 :            : /**
     755                 :            :  * Add data item for byte string buffer to global iterable section.
     756                 :            :  *
     757                 :            :  * See #THINGSET_ITEM_BYTES for parameter description.
     758                 :            :  */
     759                 :            : #define THINGSET_ADD_ITEM_BYTES(parent_id, id, ...) \
     760                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_BYTES, parent_id, id, __VA_ARGS__)
     761                 :            : 
     762                 :            : /**
     763                 :            :  * Add data item for an array to global iterable section.
     764                 :            :  *
     765                 :            :  * See #THINGSET_ITEM_ARRAY for parameter description.
     766                 :            :  */
     767                 :            : #define THINGSET_ADD_ITEM_ARRAY(parent_id, id, ...) \
     768                 :            :     _THINGSET_ADD_ITERABLE_SECTION(ITEM_ARRAY, parent_id, id, __VA_ARGS__)
     769                 :            : 
     770                 :            : /**
     771                 :            :  * Add executable item for `void` function to global iterable section.
     772                 :            :  *
     773                 :            :  * See #THINGSET_FN_VOID for parameter description.
     774                 :            :  */
     775                 :            : #define THINGSET_ADD_FN_VOID(parent_id, id, ...) \
     776                 :            :     _THINGSET_ADD_ITERABLE_SECTION(FN_VOID, parent_id, id, __VA_ARGS__)
     777                 :            : 
     778                 :            : /**
     779                 :            :  * Add executable item for `int32_t` function to global iterable section.
     780                 :            :  *
     781                 :            :  * See #THINGSET_FN_INT32 for parameter description.
     782                 :            :  */
     783                 :            : #define THINGSET_ADD_FN_INT32(parent_id, id, ...) \
     784                 :            :     _THINGSET_ADD_ITERABLE_SECTION(FN_INT32, parent_id, id, __VA_ARGS__)
     785                 :            : 
     786                 :            : /**
     787                 :            :  * Add subset item to global iterable section.
     788                 :            :  *
     789                 :            :  * See #THINGSET_SUBSET for parameter description.
     790                 :            :  */
     791                 :            : #define THINGSET_ADD_SUBSET(parent_id, id, ...) \
     792                 :            :     _THINGSET_ADD_ITERABLE_SECTION(SUBSET, parent_id, id, __VA_ARGS__)
     793                 :            : 
     794                 :            : /**
     795                 :            :  * Add group data object to global iterable section.
     796                 :            :  *
     797                 :            :  * See #THINGSET_GROUP for parameter description.
     798                 :            :  */
     799                 :            : #define THINGSET_ADD_GROUP(parent_id, id, ...) \
     800                 :            :     _THINGSET_ADD_ITERABLE_SECTION(GROUP, parent_id, id, __VA_ARGS__)
     801                 :            : 
     802                 :            : /**
     803                 :            :  * Add records object to global iterable section.
     804                 :            :  *
     805                 :            :  * See #THINGSET_RECORDS for parameter description.
     806                 :            :  */
     807                 :            : #define THINGSET_ADD_RECORDS(parent_id, id, ...) \
     808                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORDS, parent_id, id, __VA_ARGS__)
     809                 :            : 
     810                 :            : /**
     811                 :            :  * Add dynamic records object to global iterable section.
     812                 :            :  *
     813                 :            :  * See #THINGSET_DYN_RECORDS for parameter description.
     814                 :            :  */
     815                 :            : #define THINGSET_ADD_DYN_RECORDS(parent_id, id, ...) \
     816                 :            :     _THINGSET_ADD_ITERABLE_SECTION(DYN_RECORDS, parent_id, id, __VA_ARGS__)
     817                 :            : 
     818                 :            : /**
     819                 :            :  * Add record member of type `bool` to global iterable section.
     820                 :            :  *
     821                 :            :  * See #THINGSET_RECORD_ITEM_BOOL for parameter description.
     822                 :            :  */
     823                 :            : #define THINGSET_ADD_RECORD_ITEM_BOOL(parent_id, id, ...) \
     824                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_BOOL, parent_id, id, __VA_ARGS__)
     825                 :            : 
     826                 :            : /**
     827                 :            :  * Add record member of type `uint64_t` to global iterable section.
     828                 :            :  *
     829                 :            :  * See #THINGSET_RECORD_ITEM_UINT64 for parameter description.
     830                 :            :  */
     831                 :            : #define THINGSET_ADD_RECORD_ITEM_UINT64(parent_id, id, ...) \
     832                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_UINT64, parent_id, id, __VA_ARGS__)
     833                 :            : 
     834                 :            : /**
     835                 :            :  * Add record member of type `int64_t` to global iterable section.
     836                 :            :  *
     837                 :            :  * See #THINGSET_RECORD_ITEM_INT64 for parameter description.
     838                 :            :  */
     839                 :            : #define THINGSET_ADD_RECORD_ITEM_INT64(parent_id, id, ...) \
     840                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_INT64, parent_id, id, __VA_ARGS__)
     841                 :            : 
     842                 :            : /**
     843                 :            :  * Add record member of type `uint32_t` to global iterable section.
     844                 :            :  *
     845                 :            :  * See #THINGSET_RECORD_ITEM_UINT32 for parameter description.
     846                 :            :  */
     847                 :            : #define THINGSET_ADD_RECORD_ITEM_UINT32(parent_id, id, ...) \
     848                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_UINT32, parent_id, id, __VA_ARGS__)
     849                 :            : 
     850                 :            : /**
     851                 :            :  * Add record member of type `int32_t` to global iterable section.
     852                 :            :  *
     853                 :            :  * See #THINGSET_RECORD_ITEM_INT32 for parameter description.
     854                 :            :  */
     855                 :            : #define THINGSET_ADD_RECORD_ITEM_INT32(parent_id, id, ...) \
     856                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_INT32, parent_id, id, __VA_ARGS__)
     857                 :            : 
     858                 :            : /**
     859                 :            :  * Add record member of type `uint16_t` to global iterable section.
     860                 :            :  *
     861                 :            :  * See #THINGSET_RECORD_ITEM_UINT16 for parameter description.
     862                 :            :  */
     863                 :            : #define THINGSET_ADD_RECORD_ITEM_UINT16(parent_id, id, ...) \
     864                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_UINT16, parent_id, id, __VA_ARGS__)
     865                 :            : 
     866                 :            : /**
     867                 :            :  * Add record member of type `int16_t` to global iterable section.
     868                 :            :  *
     869                 :            :  * See #THINGSET_RECORD_ITEM_INT16 for parameter description.
     870                 :            :  */
     871                 :            : #define THINGSET_ADD_RECORD_ITEM_INT16(parent_id, id, ...) \
     872                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_INT16, parent_id, id, __VA_ARGS__)
     873                 :            : 
     874                 :            : /**
     875                 :            :  * Add record member of type `uint8_t` to global iterable section.
     876                 :            :  *
     877                 :            :  * See #THINGSET_RECORD_ITEM_UINT8 for parameter description.
     878                 :            :  */
     879                 :            : #define THINGSET_ADD_RECORD_ITEM_UINT8(parent_id, id, ...) \
     880                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_UINT8, parent_id, id, __VA_ARGS__)
     881                 :            : 
     882                 :            : /**
     883                 :            :  * Add record member of type `int8_t` to global iterable section.
     884                 :            :  *
     885                 :            :  * See #THINGSET_RECORD_ITEM_INT8 for parameter description.
     886                 :            :  */
     887                 :            : #define THINGSET_ADD_RECORD_ITEM_INT8(parent_id, id, ...) \
     888                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_INT8, parent_id, id, __VA_ARGS__)
     889                 :            : 
     890                 :            : /**
     891                 :            :  * Add record member of type `float` to global iterable section.
     892                 :            :  *
     893                 :            :  * See #THINGSET_RECORD_ITEM_FLOAT for parameter description.
     894                 :            :  */
     895                 :            : #define THINGSET_ADD_RECORD_ITEM_FLOAT(parent_id, id, ...) \
     896                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_FLOAT, parent_id, id, __VA_ARGS__)
     897                 :            : 
     898                 :            : /**
     899                 :            :  * Add record member of type decimal fraction to global iterable section.
     900                 :            :  *
     901                 :            :  * See #THINGSET_RECORD_ITEM_DECFRAC for parameter description.
     902                 :            :  */
     903                 :            : #define THINGSET_ADD_RECORD_ITEM_DECFRAC(parent_id, id, ...) \
     904                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_DECFRAC, parent_id, id, __VA_ARGS__)
     905                 :            : 
     906                 :            : /**
     907                 :            :  * Add record member of type `char *` to global iterable section.
     908                 :            :  *
     909                 :            :  * See #THINGSET_RECORD_ITEM_STRING for parameter description.
     910                 :            :  */
     911                 :            : #define THINGSET_ADD_RECORD_ITEM_STRING(parent_id, id, ...) \
     912                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_STRING, parent_id, id, __VA_ARGS__)
     913                 :            : 
     914                 :            : /**
     915                 :            :  * Add record member of type array to global iterable section.
     916                 :            :  *
     917                 :            :  * See #THINGSET_RECORD_ITEM_ARRAY for parameter description.
     918                 :            :  */
     919                 :            : #define THINGSET_ADD_RECORD_ITEM_ARRAY(parent_id, id, ...) \
     920                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_ARRAY, parent_id, id, __VA_ARGS__)
     921                 :            : 
     922                 :            : /**
     923                 :            :  * Add record member of type record to global iterable section.
     924                 :            :  *
     925                 :            :  * Seee #THINGSET_RECORD_ITEM_RECORD for parameter description.
     926                 :            :  */
     927                 :            : #define THINGSET_ADD_RECORD_ITEM_RECORD(parent_id, id, ...) \
     928                 :            :     _THINGSET_ADD_ITERABLE_SECTION(RECORD_ITEM_RECORD, parent_id, id, __VA_ARGS__)
     929                 :            : 
     930                 :            : /**
     931                 :            :  * Define a struct thingset_bytes to be used with #THINGSET_ITEM_BYTES
     932                 :            :  *
     933                 :            :  * @param var_name Name of the created variable of struct thingset_bytes
     934                 :            :  * @param buffer Existing `uint8_t` array (must be an array, pointer not allowed)
     935                 :            :  * @param used_bytes Currently used elements in the buffer
     936                 :            :  */
     937                 :            : #define THINGSET_DEFINE_BYTES(var_name, buffer, used_bytes) \
     938                 :            :     struct thingset_bytes var_name = { buffer, sizeof(buffer), used_bytes };
     939                 :            : 
     940                 :            : /**
     941                 :            :  * Define a struct thingset_array to expose `bool` arrays with #THINGSET_ITEM_ARRAY
     942                 :            :  *
     943                 :            :  * @param var_name Name of the created struct thingset_array variable
     944                 :            :  * @param array Existing fixed-size array of type `bool` (must be an array and not a pointer)
     945                 :            :  * @param used_elements Currently used elements in the array
     946                 :            :  */
     947                 :            : #define THINGSET_DEFINE_BOOL_ARRAY(var_name, array, used_elements) \
     948                 :            :     struct thingset_array var_name = { \
     949                 :            :         { .b = array }, THINGSET_TYPE_BOOL, 0, _ARRAY_SIZE(array), used_elements, \
     950                 :            :     };
     951                 :            : 
     952                 :            : /**
     953                 :            :  * Define a struct thingset_array to expose `uint8_t` arrays with #THINGSET_ITEM_ARRAY
     954                 :            :  *
     955                 :            :  * @param var_name Name of the created struct thingset_array variable
     956                 :            :  * @param array Existing fixed-size array of type `uint8_t` (must be an array and not a pointer)
     957                 :            :  * @param used_elements Currently used elements in the array
     958                 :            :  */
     959                 :            : #define THINGSET_DEFINE_UINT8_ARRAY(var_name, array, used_elements) \
     960                 :            :     struct thingset_array var_name = { \
     961                 :            :         { .u8 = array }, THINGSET_TYPE_U8, 0, _ARRAY_SIZE(array), used_elements, \
     962                 :            :     };
     963                 :            : 
     964                 :            : /**
     965                 :            :  * Define a struct thingset_array to expose `int8_t` arrays with #THINGSET_ITEM_ARRAY
     966                 :            :  *
     967                 :            :  * @param var_name Name of the created struct thingset_array variable
     968                 :            :  * @param array Existing fixed-size array of type `int8_t` (must be an array and not a pointer)
     969                 :            :  * @param used_elements Currently used elements in the array
     970                 :            :  */
     971                 :            : #define THINGSET_DEFINE_INT8_ARRAY(var_name, array, used_elements) \
     972                 :            :     struct thingset_array var_name = { \
     973                 :            :         { .i8 = array }, THINGSET_TYPE_I8, 0, _ARRAY_SIZE(array), used_elements, \
     974                 :            :     };
     975                 :            : 
     976                 :            : /**
     977                 :            :  * Define a struct thingset_array to expose `uint16_t` arrays with #THINGSET_ITEM_ARRAY
     978                 :            :  *
     979                 :            :  * @param var_name Name of the created struct thingset_array variable
     980                 :            :  * @param array Existing fixed-size array of type `uint16_t` (must be an array and not a pointer)
     981                 :            :  * @param used_elements Currently used elements in the array
     982                 :            :  */
     983                 :            : #define THINGSET_DEFINE_UINT16_ARRAY(var_name, array, used_elements) \
     984                 :            :     struct thingset_array var_name = { \
     985                 :            :         { .u16 = array }, THINGSET_TYPE_U16, 0, _ARRAY_SIZE(array), used_elements, \
     986                 :            :     };
     987                 :            : 
     988                 :            : /**
     989                 :            :  * Define a struct thingset_array to expose `int16_t` arrays with #THINGSET_ITEM_ARRAY
     990                 :            :  *
     991                 :            :  * @param var_name Name of the created struct thingset_array variable
     992                 :            :  * @param array Existing fixed-size array of type `int16_t` (must be an array and not a pointer)
     993                 :            :  * @param used_elements Currently used elements in the array
     994                 :            :  */
     995                 :            : #define THINGSET_DEFINE_INT16_ARRAY(var_name, array, used_elements) \
     996                 :            :     struct thingset_array var_name = { \
     997                 :            :         { .i16 = array }, THINGSET_TYPE_I16, 0, _ARRAY_SIZE(array), used_elements, \
     998                 :            :     };
     999                 :            : 
    1000                 :            : /**
    1001                 :            :  * Define a struct thingset_array to expose `uint32_t` arrays with #THINGSET_ITEM_ARRAY
    1002                 :            :  *
    1003                 :            :  * @param var_name Name of the created struct thingset_array variable
    1004                 :            :  * @param array Existing fixed-size array of type `uint32_t` (must be an array and not a pointer)
    1005                 :            :  * @param used_elements Currently used elements in the array
    1006                 :            :  */
    1007                 :            : #define THINGSET_DEFINE_UINT32_ARRAY(var_name, array, used_elements) \
    1008                 :            :     struct thingset_array var_name = { \
    1009                 :            :         { .u32 = array }, THINGSET_TYPE_U32, 0, _ARRAY_SIZE(array), used_elements, \
    1010                 :            :     };
    1011                 :            : 
    1012                 :            : /**
    1013                 :            :  * Define a struct thingset_array to expose `int32_t` arrays with #THINGSET_ITEM_ARRAY
    1014                 :            :  *
    1015                 :            :  * @param var_name Name of the created struct thingset_array variable
    1016                 :            :  * @param array Existing fixed-size array of type `int32_t` (must be an array and not a pointer)
    1017                 :            :  * @param used_elements Currently used elements in the array
    1018                 :            :  */
    1019                 :            : #define THINGSET_DEFINE_INT32_ARRAY(var_name, array, used_elements) \
    1020                 :            :     struct thingset_array var_name = { \
    1021                 :            :         { .i32 = array }, THINGSET_TYPE_I32, 0, _ARRAY_SIZE(array), used_elements, \
    1022                 :            :     };
    1023                 :            : 
    1024                 :            : /**
    1025                 :            :  * Define a struct thingset_array to expose `uint64_t` arrays with #THINGSET_ITEM_ARRAY
    1026                 :            :  *
    1027                 :            :  * @param var_name Name of the created struct thingset_array variable
    1028                 :            :  * @param array Existing fixed-size array of type `uint64_t` (must be an array and not a pointer)
    1029                 :            :  * @param used_elements Currently used elements in the array
    1030                 :            :  */
    1031                 :            : #define THINGSET_DEFINE_UINT64_ARRAY(var_name, array, used_elements) \
    1032                 :            :     struct thingset_array var_name = { \
    1033                 :            :         { .u64 = array }, THINGSET_TYPE_U64, 0, _ARRAY_SIZE(array), used_elements, \
    1034                 :            :     };
    1035                 :            : 
    1036                 :            : /**
    1037                 :            :  * Define a struct thingset_array to expose `int64_t` arrays with #THINGSET_ITEM_ARRAY
    1038                 :            :  *
    1039                 :            :  * @param var_name Name of the created struct thingset_array variable
    1040                 :            :  * @param array Existing fixed-size array of type `int64_t` (must be an array and not a pointer)
    1041                 :            :  * @param used_elements Currently used elements in the array
    1042                 :            :  */
    1043                 :            : #define THINGSET_DEFINE_INT64_ARRAY(var_name, array, used_elements) \
    1044                 :            :     struct thingset_array var_name = { \
    1045                 :            :         { .i64 = array }, THINGSET_TYPE_I64, 0, _ARRAY_SIZE(array), used_elements, \
    1046                 :            :     };
    1047                 :            : 
    1048                 :            : /**
    1049                 :            :  * Define a struct thingset_array to expose `float` arrays with #THINGSET_ITEM_ARRAY
    1050                 :            :  *
    1051                 :            :  * @param var_name Name of the created struct thingset_array variable
    1052                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
    1053                 :            :  * @param array Existing fixed-size array of type `float` (must be an array and not a pointer)
    1054                 :            :  * @param used_elements Currently used elements in the array
    1055                 :            :  */
    1056                 :            : #define THINGSET_DEFINE_FLOAT_ARRAY(var_name, decimals, array, used_elements) \
    1057                 :            :     struct thingset_array var_name = { \
    1058                 :            :         { .f32 = array }, THINGSET_TYPE_F32, decimals, _ARRAY_SIZE(array), used_elements, \
    1059                 :            :     };
    1060                 :            : 
    1061                 :            : /**
    1062                 :            :  * Define a struct thingset_array to expose decimal fraction arrays with #THINGSET_ITEM_ARRAY
    1063                 :            :  *
    1064                 :            :  * @param var_name Name of the created struct thingset_array variable
    1065                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
    1066                 :            :  * @param array Existing fixed-size array of type `int32_t` (must be an array and not a pointer)
    1067                 :            :  * @param used_elements Currently used elements in the array
    1068                 :            :  */
    1069                 :            : #define THINGSET_DEFINE_DECFRAC_ARRAY(var_name, decimals, array, used_elements) \
    1070                 :            :     struct thingset_array var_name = { \
    1071                 :            :         { .decfrac = array }, THINGSET_TYPE_DECFRAC, decimals, _ARRAY_SIZE(array), used_elements, \
    1072                 :            :     };
    1073                 :            : 
    1074                 :            : /**
    1075                 :            :  * Define a struct thingset_array to expose `bool` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1076                 :            :  *
    1077                 :            :  * @param var_name Name of the created struct thingset_array variable
    1078                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1079                 :            :  * @param struct_member Struct member of type `bool` array used for this item
    1080                 :            :  */
    1081                 :            : #define THINGSET_DEFINE_RECORD_BOOL_ARRAY(var_name, struct_type, struct_member) \
    1082                 :            :     struct thingset_array var_name = { \
    1083                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1084                 :            :         THINGSET_TYPE_BOOL, \
    1085                 :            :         0, \
    1086                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1087                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1088                 :            :     };
    1089                 :            : 
    1090                 :            : /**
    1091                 :            :  * Define a struct thingset_array to expose `uint8_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1092                 :            :  *
    1093                 :            :  * @param var_name Name of the created struct thingset_array variable
    1094                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1095                 :            :  * @param struct_member Struct member of type `uint8_t` array used for this item
    1096                 :            :  */
    1097                 :            : #define THINGSET_DEFINE_RECORD_UINT8_ARRAY(var_name, struct_type, struct_member) \
    1098                 :            :     struct thingset_array var_name = { \
    1099                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1100                 :            :         THINGSET_TYPE_U8, \
    1101                 :            :         0, \
    1102                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1103                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1104                 :            :     };
    1105                 :            : 
    1106                 :            : /**
    1107                 :            :  * Define a struct thingset_array to expose `int8_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1108                 :            :  *
    1109                 :            :  * @param var_name Name of the created struct thingset_array variable
    1110                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1111                 :            :  * @param struct_member Struct member of type `int8_t` array used for this item
    1112                 :            :  */
    1113                 :            : #define THINGSET_DEFINE_RECORD_INT8_ARRAY(var_name, struct_type, struct_member) \
    1114                 :            :     struct thingset_array var_name = { \
    1115                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1116                 :            :         THINGSET_TYPE_I8, \
    1117                 :            :         0, \
    1118                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1119                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1120                 :            :     };
    1121                 :            : 
    1122                 :            : /**
    1123                 :            :  * Define a struct thingset_array to expose `uint16_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1124                 :            :  *
    1125                 :            :  * @param var_name Name of the created struct thingset_array variable
    1126                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1127                 :            :  * @param struct_member Struct member of type `uint16_t` array used for this item
    1128                 :            :  */
    1129                 :            : #define THINGSET_DEFINE_RECORD_UINT16_ARRAY(var_name, struct_type, struct_member) \
    1130                 :            :     struct thingset_array var_name = { \
    1131                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1132                 :            :         THINGSET_TYPE_U16, \
    1133                 :            :         0, \
    1134                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1135                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1136                 :            :     };
    1137                 :            : 
    1138                 :            : /**
    1139                 :            :  * Define a struct thingset_array to expose `int16_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1140                 :            :  *
    1141                 :            :  * @param var_name Name of the created struct thingset_array variable
    1142                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1143                 :            :  * @param struct_member Struct member of type `int16_t` array used for this item
    1144                 :            :  */
    1145                 :            : #define THINGSET_DEFINE_RECORD_INT16_ARRAY(var_name, struct_type, struct_member) \
    1146                 :            :     struct thingset_array var_name = { \
    1147                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1148                 :            :         THINGSET_TYPE_I16, \
    1149                 :            :         0, \
    1150                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1151                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1152                 :            :     };
    1153                 :            : 
    1154                 :            : /**
    1155                 :            :  * Define a struct thingset_array to expose `uint32_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1156                 :            :  *
    1157                 :            :  * @param var_name Name of the created struct thingset_array variable
    1158                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1159                 :            :  * @param struct_member Struct member of type `uint32_t` array used for this item
    1160                 :            :  */
    1161                 :            : #define THINGSET_DEFINE_RECORD_UINT32_ARRAY(var_name, struct_type, struct_member) \
    1162                 :            :     struct thingset_array var_name = { \
    1163                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1164                 :            :         THINGSET_TYPE_U32, \
    1165                 :            :         0, \
    1166                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1167                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1168                 :            :     };
    1169                 :            : 
    1170                 :            : /**
    1171                 :            :  * Define a struct thingset_array to expose `int32_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1172                 :            :  *
    1173                 :            :  * @param var_name Name of the created struct thingset_array variable
    1174                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1175                 :            :  * @param struct_member Struct member of type `int32_t` array used for this item
    1176                 :            :  */
    1177                 :            : #define THINGSET_DEFINE_RECORD_INT32_ARRAY(var_name, struct_type, struct_member) \
    1178                 :            :     struct thingset_array var_name = { \
    1179                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1180                 :            :         THINGSET_TYPE_I32, \
    1181                 :            :         0, \
    1182                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1183                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1184                 :            :     };
    1185                 :            : 
    1186                 :            : /**
    1187                 :            :  * Define a struct thingset_array to expose `uint64_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1188                 :            :  *
    1189                 :            :  * @param var_name Name of the created struct thingset_array variable
    1190                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1191                 :            :  * @param struct_member Struct member of type `uint64_t` array used for this item
    1192                 :            :  */
    1193                 :            : #define THINGSET_DEFINE_RECORD_UINT64_ARRAY(var_name, struct_type, struct_member) \
    1194                 :            :     struct thingset_array var_name = { \
    1195                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1196                 :            :         THINGSET_TYPE_U64, \
    1197                 :            :         0, \
    1198                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1199                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1200                 :            :     };
    1201                 :            : 
    1202                 :            : /**
    1203                 :            :  * Define a struct thingset_array to expose `int64_t` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1204                 :            :  *
    1205                 :            :  * @param var_name Name of the created struct thingset_array variable
    1206                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1207                 :            :  * @param struct_member Struct member of type `int64_t` array used for this item
    1208                 :            :  */
    1209                 :            : #define THINGSET_DEFINE_RECORD_INT64_ARRAY(var_name, struct_type, struct_member) \
    1210                 :            :     struct thingset_array var_name = { \
    1211                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1212                 :            :         THINGSET_TYPE_I64, \
    1213                 :            :         0, \
    1214                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1215                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1216                 :            :     };
    1217                 :            : 
    1218                 :            : /**
    1219                 :            :  * Define a struct thingset_array to expose `float` arrays with #THINGSET_RECORD_ITEM_ARRAY
    1220                 :            :  *
    1221                 :            :  * @param var_name Name of the created struct thingset_array variable
    1222                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
    1223                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1224                 :            :  * @param struct_member Struct member of type `float` array used for this item
    1225                 :            :  */
    1226                 :            : #define THINGSET_DEFINE_RECORD_FLOAT_ARRAY(var_name, decimals, struct_type, struct_member) \
    1227                 :            :     struct thingset_array var_name = { \
    1228                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1229                 :            :         THINGSET_TYPE_F32, \
    1230                 :            :         decimals, \
    1231                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1232                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1233                 :            :     };
    1234                 :            : 
    1235                 :            : /**
    1236                 :            :  * Define a struct thingset_array to expose decimal fraction arrays with #THINGSET_RECORD_ITEM_ARRAY
    1237                 :            :  *
    1238                 :            :  * @param var_name Name of the created struct thingset_array variable
    1239                 :            :  * @param decimals Number of decimal digits to be serialized in text mode
    1240                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1241                 :            :  * @param struct_member Struct member of type `int32_t` array used for this item
    1242                 :            :  */
    1243                 :            : #define THINGSET_DEFINE_RECORD_DECFRAC_ARRAY(var_name, decfrac, struct_type, struct_member) \
    1244                 :            :     struct thingset_array var_name = { \
    1245                 :            :         { .offset = offsetof(struct_type, struct_member) }, \
    1246                 :            :         THINGSET_TYPE_F32, \
    1247                 :            :         decimals, \
    1248                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1249                 :            :         _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1250                 :            :     };
    1251                 :            : 
    1252                 :            : /**
    1253                 :            :  * Define a struct thingset_records to expose a nested array of records.
    1254                 :            :  *
    1255                 :            :  * @param var_name Name of the created struct thingset_records variable
    1256                 :            :  * @param struct_type Type of the struct used for the records (e.g. `struct my_record`)
    1257                 :            :  * @param struct_member Struct member used for this item
    1258                 :            :  */
    1259                 :            : #define THINGSET_DEFINE_RECORD_RECORDS(var_name, struct_type, struct_member) \
    1260                 :            :     struct thingset_records var_name = { (void *)offsetof(struct_type, struct_member), \
    1261                 :            :                                          sizeof(__typeof__(((struct_type *)0)->struct_member)) \
    1262                 :            :                                              / _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1263                 :            :                                          _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1264                 :            :                                          _ARRAY_SIZE(((struct_type *)0)->struct_member), \
    1265                 :            :                                          THINGSET_NO_CALLBACK };
    1266                 :            : 
    1267                 :            : /**
    1268                 :            :  * Define a struct thingset_records to be used with #THINGSET_RECORDS
    1269                 :            :  *
    1270                 :            :  * @param var_name Name of the created struct thingset_records variable
    1271                 :            :  * @param records Existing fixed-size array of custom struct containing the records
    1272                 :            :  * @param used_records Number of currently used records
    1273                 :            :  */
    1274                 :            : #define THINGSET_DEFINE_RECORDS(var_name, records, used_records) \
    1275                 :            :     struct thingset_records var_name = { records, sizeof(__typeof__(*records)), \
    1276                 :            :                                          ARRAY_SIZE(records), used_records, \
    1277                 :            :                                          THINGSET_NO_CALLBACK };
    1278                 :            : 
    1279                 :            : /**
    1280                 :            :  * Define a struct thingset_records to be used with #THINGSET_DYN_RECORDS
    1281                 :            :  *
    1282                 :            :  * @param var_name Name of the created struct thingset_records variable
    1283                 :            :  * @param record Pointer to existing struct object containing the dynamically created data
    1284                 :            :  * @param available_records Number of available records
    1285                 :            :  * @param callback Pointer to a function to be called before/after read/write operations.
    1286                 :            :  */
    1287                 :            : #define THINGSET_DEFINE_DYN_RECORDS(var_name, record, available_records, callback) \
    1288                 :            :     struct thingset_records var_name = { record, sizeof(__typeof__(*record)), 1, \
    1289                 :            :                                          available_records, callback };
    1290                 :            : 
    1291                 :            : /*
    1292                 :            :  * Defines to make data object definitions more explicit
    1293                 :            :  */
    1294                 :            : #define THINGSET_NO_CALLBACK NULL /**< No callback assigned to group */
    1295                 :            : 
    1296                 :            : /** @cond INTERNAL_HIDDEN */
    1297                 :            : #define THINGSET_DETAIL_DYN_RECORDS -1
    1298                 :            : /** @endcond */
    1299                 :            : 
    1300                 :            : /*
    1301                 :            :  * Access right macros for data objects
    1302                 :            :  */
    1303                 :            : 
    1304                 :            : /** @cond INTERNAL_HIDDEN */
    1305                 :            : 
    1306                 :            : #define THINGSET_ROLE_USR (1U << 0) /**< Normal user */
    1307                 :            : #define THINGSET_ROLE_EXP (1U << 1) /**< Expert user */
    1308                 :            : #define THINGSET_ROLE_MFR (1U << 2) /**< Manufacturer */
    1309                 :            : #define THINGSET_ROLE_ANY (THINGSET_USR_R | THINGSET_EXP_R | THINGSET_MFR_R)
    1310                 :            : 
    1311                 :            : #define THINGSET_READ_MASK  0x0F /**< Read flags stored in 4 least-significant bits */
    1312                 :            : #define THINGSET_WRITE_MASK 0xF0 /**< Write flags stored in 4 most-significant bits */
    1313                 :            : 
    1314                 :            : /* Masks for different roles */
    1315                 :            : #define THINGSET_USR_MASK (THINGSET_ROLE_USR << 4 | THINGSET_ROLE_USR)
    1316                 :            : #define THINGSET_EXP_MASK (THINGSET_ROLE_EXP << 4 | THINGSET_ROLE_EXP)
    1317                 :            : #define THINGSET_MFR_MASK (THINGSET_ROLE_MFR << 4 | THINGSET_ROLE_MFR)
    1318                 :            : 
    1319                 :            : #define THINGSET_READ(roles)       ((roles) & THINGSET_READ_MASK)
    1320                 :            : #define THINGSET_WRITE(roles)      (((roles) << 4) & THINGSET_WRITE_MASK)
    1321                 :            : #define THINGSET_READ_WRITE(roles) (THINGSET_READ(roles) | THINGSET_WRITE(roles))
    1322                 :            : 
    1323                 :            : /** @endcond */
    1324                 :            : 
    1325                 :            : #define THINGSET_USR_R THINGSET_READ(THINGSET_ROLE_USR) /**< Read-only access for normal user */
    1326                 :            : #define THINGSET_EXP_R THINGSET_READ(THINGSET_ROLE_EXP) /**< Read-only access for expert user */
    1327                 :            : #define THINGSET_MFR_R THINGSET_READ(THINGSET_ROLE_MFR) /**< Read-only access for manufacturer */
    1328                 :            : #define THINGSET_ANY_R THINGSET_READ(THINGSET_ROLE_ANY) /**< Read-only access for any user */
    1329                 :            : 
    1330                 :            : #define THINGSET_USR_W THINGSET_WRITE(THINGSET_ROLE_USR) /**< Write-only access for normal user */
    1331                 :            : #define THINGSET_EXP_W THINGSET_WRITE(THINGSET_ROLE_EXP) /**< Write-only access for expert user */
    1332                 :            : #define THINGSET_MFR_W THINGSET_WRITE(THINGSET_ROLE_MFR) /**< Write-only access for manuf. */
    1333                 :            : #define THINGSET_ANY_W THINGSET_WRITE(THINGSET_ROLE_ANY) /**< Write-only access for any user */
    1334                 :            : 
    1335                 :            : #define THINGSET_USR_RW \
    1336                 :            :     THINGSET_READ_WRITE(THINGSET_ROLE_USR) /**< Read/write access for normal user */
    1337                 :            : #define THINGSET_EXP_RW \
    1338                 :            :     THINGSET_READ_WRITE(THINGSET_ROLE_EXP) /**< Read/write access for expert user */
    1339                 :            : #define THINGSET_MFR_RW \
    1340                 :            :     THINGSET_READ_WRITE(THINGSET_ROLE_MFR) /**< Read/write access for manufacturer */
    1341                 :            : #define THINGSET_ANY_RW \
    1342                 :            :     THINGSET_READ_WRITE(THINGSET_ROLE_ANY) /**< Read/write access for any user */
    1343                 :            : 
    1344                 :            : #define THINGSET_ENDPOINT_INDEX_NONE (-1) /**< No index provided for endpoint */
    1345                 :            : #define THINGSET_ENDPOINT_INDEX_NEW  (-2) /**< Non-existent element behind the last element */
    1346                 :            : 
    1347                 :            : #define THINGSET_CONTEXT_LOCK_TIMEOUT_MS (1000)
    1348                 :            : 
    1349                 :            : /** ThingSet data object ID (16-bit) */
    1350                 :            : typedef uint16_t thingset_object_id_t;
    1351                 :            : 
    1352                 :            : /**
    1353                 :            :  * Indication for which reason a callback assigned to a group was called.
    1354                 :            :  *
    1355                 :            :  * The reason is passed to the callback as a parameter, such that the application can perform
    1356                 :            :  * desired actions, e.g. update data from ADC before it is read/serialized or write data to an
    1357                 :            :  * EEPROM after it was written/deserialized.
    1358                 :            :  */
    1359                 :            : enum thingset_callback_reason
    1360                 :            : {
    1361                 :            :     THINGSET_CALLBACK_PRE_READ,   /**< Function was called before serializing data of the group */
    1362                 :            :     THINGSET_CALLBACK_POST_READ,  /**< Function was called after serializing data of the group */
    1363                 :            :     THINGSET_CALLBACK_PRE_WRITE,  /**< Function was called before deserializing data of the group */
    1364                 :            :     THINGSET_CALLBACK_POST_WRITE, /**< Function was called after deserializing data of the group */
    1365                 :            : };
    1366                 :            : 
    1367                 :            : /** Function to be called before/after read/write operations to groups. */
    1368                 :            : typedef void (*thingset_group_callback_t)(enum thingset_callback_reason cb_reason);
    1369                 :            : 
    1370                 :            : /** Function to be called before/after read/write operations to records. */
    1371                 :            : typedef void (*thingset_records_callback_t)(enum thingset_callback_reason cb_reason, int index);
    1372                 :            : 
    1373                 :            : /** @cond INTERNAL_HIDDEN */
    1374                 :            : 
    1375                 :            : /**
    1376                 :            :  * Internal C data types (used together with union thingset_data_pointer)
    1377                 :            :  */
    1378                 :            : enum thingset_type
    1379                 :            : {
    1380                 :            :     THINGSET_TYPE_BOOL,    /**< bool */
    1381                 :            :     THINGSET_TYPE_U8,      /**< uint8_t */
    1382                 :            :     THINGSET_TYPE_I8,      /**< int8_t */
    1383                 :            :     THINGSET_TYPE_U16,     /**< uint16_t */
    1384                 :            :     THINGSET_TYPE_I16,     /**< int16_t */
    1385                 :            :     THINGSET_TYPE_U32,     /**< uint32_t */
    1386                 :            :     THINGSET_TYPE_I32,     /**< int32_t */
    1387                 :            :     THINGSET_TYPE_U64,     /**< uint64_t */
    1388                 :            :     THINGSET_TYPE_I64,     /**< int64_t */
    1389                 :            :     THINGSET_TYPE_F32,     /**< float */
    1390                 :            :     THINGSET_TYPE_DECFRAC, /**< decimal fraction */
    1391                 :            :     THINGSET_TYPE_STRING,  /**< String buffer (UTF-8 text) */
    1392                 :            :     THINGSET_TYPE_BYTES,   /**< Byte buffer (binary data) */
    1393                 :            :     THINGSET_TYPE_ARRAY,   /**< Array */
    1394                 :            :     THINGSET_TYPE_RECORDS, /**< Records (array of arbitrary struct objects) */
    1395                 :            :     THINGSET_TYPE_GROUP,   /**< Internal object to describe data hierarchy */
    1396                 :            :     THINGSET_TYPE_SUBSET,  /**< Subset of data items */
    1397                 :            :     THINGSET_TYPE_FN_VOID, /**< Function with void return value */
    1398                 :            :     THINGSET_TYPE_FN_I32,  /**< Function with int32_t return value */
    1399                 :            : };
    1400                 :            : 
    1401                 :            : /**
    1402                 :            :  * Helper function to determine the size of above ThingSet types in bytes
    1403                 :            :  */
    1404                 :         19 : static inline size_t thingset_type_size(uint8_t type)
    1405                 :            : {
    1406                 :         19 :     uint8_t sizes[] = { sizeof(bool),    sizeof(uint8_t),  sizeof(int8_t),  sizeof(uint16_t),
    1407                 :            :                         sizeof(int16_t), sizeof(uint32_t), sizeof(int32_t), sizeof(uint64_t),
    1408                 :            :                         sizeof(int64_t), sizeof(float),    sizeof(int32_t) };
    1409         [ +  - ]:         19 :     return type < sizeof(sizes) ? sizes[type] : 0;
    1410                 :            : }
    1411                 :            : 
    1412                 :            : /**
    1413                 :            :  * Union for type-checking of provided data item variable pointers through the macros.
    1414                 :            :  */
    1415                 :            : union thingset_data_pointer {
    1416                 :            :     bool *b;                          /**< Pointer to bool variable */
    1417                 :            :     uint8_t *u8;                      /**< Pointer to uint8_t variable */
    1418                 :            :     int8_t *i8;                       /**< Pointer to int8_t variable */
    1419                 :            :     uint16_t *u16;                    /**< Pointer to uint16_t variable */
    1420                 :            :     int16_t *i16;                     /**< Pointer to int16_t variable */
    1421                 :            :     uint32_t *u32;                    /**< Pointer to uint32_t variable */
    1422                 :            :     int32_t *i32;                     /**< Pointer to int32_t variable */
    1423                 :            :     uint64_t *u64;                    /**< Pointer to uint64_t variable */
    1424                 :            :     int64_t *i64;                     /**< Pointer to int64_t variable */
    1425                 :            :     float *f32;                       /**< Pointer to float variable */
    1426                 :            :     int32_t *decfrac;                 /**< Pointer to decimal fraction mantissa */
    1427                 :            :     char *str;                        /**< Pointer to string buffer */
    1428                 :            :     struct thingset_bytes *bytes;     /**< Pointer to thingset_bytes struct */
    1429                 :            :     struct thingset_array *array;     /**< Pointer to thingset_array struct */
    1430                 :            :     struct thingset_records *records; /**< Pointer to thingset_records struct */
    1431                 :            :     size_t offset;                    /**< Offset for record elements */
    1432                 :            :     uint32_t subset;                  /**< Subset flag(s) */
    1433                 :            :     void (*void_fn)();                /**< Pointer to function with void return value */
    1434                 :            :     int32_t (*i32_fn)();              /**< Pointer to function with int32_t return value */
    1435                 :            :     /** Pointer to group callback function */
    1436                 :            :     thingset_group_callback_t group_callback;
    1437                 :            : };
    1438                 :            : 
    1439                 :            : /** @endcond */
    1440                 :            : 
    1441                 :            : /**
    1442                 :            :  * Enum to define ThingSet data format (used by export/import and report functions).
    1443                 :            :  */
    1444                 :            : enum thingset_data_format
    1445                 :            : {
    1446                 :            :     THINGSET_TXT_NAMES_VALUES, /**< Text names and values (JSON) */
    1447                 :            :     THINGSET_TXT_NAMES_ONLY,   /**< Text names only (JSON) */
    1448                 :            :     THINGSET_TXT_VALUES_ONLY,  /**< Text values only (JSON) */
    1449                 :            :     THINGSET_BIN_IDS_VALUES,   /**< Binary IDs and values (CBOR) */
    1450                 :            :     THINGSET_BIN_NAMES_VALUES, /**< Binary names and values (CBOR) */
    1451                 :            :     THINGSET_BIN_IDS_ONLY,     /**< Binary IDs only (CBOR) */
    1452                 :            :     THINGSET_BIN_VALUES_ONLY,  /**< Binary values only (CBOR) */
    1453                 :            : };
    1454                 :            : 
    1455                 :            : /**
    1456                 :            :  * Data structure to specify a binary data buffer
    1457                 :            :  */
    1458                 :            : struct thingset_bytes
    1459                 :            : {
    1460                 :            :     uint8_t *bytes;           /**< Pointer to the bytes buffer */
    1461                 :            :     const uint16_t max_bytes; /**< Maximum number of bytes in the buffer */
    1462                 :            :     uint16_t num_bytes;       /**< Actual number of bytes in the buffer */
    1463                 :            : };
    1464                 :            : 
    1465                 :            : /**
    1466                 :            :  * Data structure to specify an array data object
    1467                 :            :  */
    1468                 :            : struct thingset_array
    1469                 :            : {
    1470                 :            :     const union thingset_data_pointer elements; /**< Pointer to the first element of the array */
    1471                 :            :     const enum thingset_type element_type; /**< Type of the array elements (enum thingset_type) */
    1472                 :            :     const int16_t decimals;                /**< See detail in struct thingset_data_object */
    1473                 :            :     const uint16_t max_elements;           /**< Maximum number of elements in the array */
    1474                 :            :     uint16_t num_elements;                 /**< Actual number of elements in the array */
    1475                 :            : };
    1476                 :            : 
    1477                 :            : /**
    1478                 :            :  * Data structure to specify records of an arbitrary struct
    1479                 :            :  */
    1480                 :            : struct thingset_records
    1481                 :            : {
    1482                 :            :     const void *records;        /**< Pointer to the first record */
    1483                 :            :     const size_t record_size;   /**< Size of one record in bytes */
    1484                 :            :     const uint16_t max_records; /**< Maximum number of records in the array */
    1485                 :            :     uint16_t num_records;       /**< Actual number of records in the array */
    1486                 :            :     thingset_records_callback_t callback;
    1487                 :            : };
    1488                 :            : 
    1489                 :            : /**
    1490                 :            :  * ThingSet data object struct.
    1491                 :            :  */
    1492                 :            : struct thingset_data_object
    1493                 :            : {
    1494                 :            :     /**
    1495                 :            :      * ID of parent object
    1496                 :            :      */
    1497                 :            :     const thingset_object_id_t parent_id;
    1498                 :            : 
    1499                 :            :     /**
    1500                 :            :      * Data object ID
    1501                 :            :      */
    1502                 :            :     const thingset_object_id_t id;
    1503                 :            : 
    1504                 :            :     /**
    1505                 :            :      * Data object name
    1506                 :            :      */
    1507                 :            :     const char *name;
    1508                 :            : 
    1509                 :            :     /**
    1510                 :            :      * Pointer to the variable containing the data. The variable type must match the type as
    1511                 :            :      * specified.
    1512                 :            :      *
    1513                 :            :      * For record items, the offset of this item inside the struct is stored (in bytes).
    1514                 :            :      */
    1515                 :            :     const union thingset_data_pointer data;
    1516                 :            : 
    1517                 :            :     /**
    1518                 :            :      * One of THINGSET_TYPE_INT32, _FLOAT, ...
    1519                 :            :      */
    1520                 :            :     const enum thingset_type type : 5;
    1521                 :            : 
    1522                 :            :     /**
    1523                 :            :      * Variable storing different detail information depending on the data type
    1524                 :            :      *
    1525                 :            :      * - FLOAT32: Decimal digits (precision) to use during serialization to JSON.
    1526                 :            :      *
    1527                 :            :      * - DECFRAC: Exponent for conversion between internal unit and unit exposed via ThingSet
    1528                 :            :      *   (equivalent to decimal digits for FLOAT32).
    1529                 :            :      *   Formula: internal value = 10^exponent * ThingSet value
    1530                 :            :      *   Example: If a voltage measurement is internally stored as an integer in mV, use exponent 3
    1531                 :            :      *   to convert to the SI base unit V as exposed via ThingSet.
    1532                 :            :      *
    1533                 :            :      * - STRING: Size of the internal buffer in bytes.
    1534                 :            :      */
    1535                 :            :     const int32_t detail : 12;
    1536                 :            : 
    1537                 :            :     /**
    1538                 :            :      * Flags to define read/write access
    1539                 :            :      */
    1540                 :            :     const uint32_t access : 8;
    1541                 :            : 
    1542                 :            :     /**
    1543                 :            :      * Flags to assign data item to different data item subsets (e.g. for reports)
    1544                 :            :      */
    1545                 :            :     MAYBE_CONST uint32_t subsets : 7;
    1546                 :            : 
    1547                 :            : #ifdef CONFIG_THINGSET_OBJECT_LOOKUP_MAP
    1548                 :            :     /**
    1549                 :            :      * Pointer to next node in list for map lookup
    1550                 :            :      */
    1551                 :            :     sys_snode_t node;
    1552                 :            : #endif /* CONFIG_THINGSET_OBJECT_LOOKUP_MAP */
    1553                 :            : };
    1554                 :            : 
    1555                 :            : /**
    1556                 :            :  * Data to describe the endpoint parsed from a ThingSet request
    1557                 :            :  */
    1558                 :            : struct thingset_endpoint
    1559                 :            : {
    1560                 :            :     /** Pointer to the data object in memory (must never be NULL) */
    1561                 :            :     struct thingset_data_object *object;
    1562                 :            :     /** Index number or THINGSET_ENDPOINT_INDEX_NONE or THINGSET_ENDPOINT_INDEX_NEW */
    1563                 :            :     int32_t index;
    1564                 :            :     /** Use names or IDs (relevant for binary mode) */
    1565                 :            :     bool use_ids;
    1566                 :            : };
    1567                 :            : 
    1568                 :            : /* Forward-declaration of internal ThingSet API struct (defined in thingset_internal.h) */
    1569                 :            : struct thingset_api;
    1570                 :            : 
    1571                 :            : /**
    1572                 :            :  * ThingSet context.
    1573                 :            :  *
    1574                 :            :  * Stores and handles all data objects exposed to different communication interfaces.
    1575                 :            :  */
    1576                 :            : struct thingset_context
    1577                 :            : {
    1578                 :            :     /**
    1579                 :            :      * Array of objects database provided during initialization
    1580                 :            :      */
    1581                 :            :     struct thingset_data_object *data_objects;
    1582                 :            : 
    1583                 :            : #ifdef CONFIG_THINGSET_OBJECT_LOOKUP_MAP
    1584                 :            :     /**
    1585                 :            :      * Array of linked lists: map for object ID lookup
    1586                 :            :      */
    1587                 :            :     sys_slist_t data_objects_lookup[CONFIG_THINGSET_OBJECT_LOOKUP_BUCKETS];
    1588                 :            : #endif
    1589                 :            : 
    1590                 :            :     /**
    1591                 :            :      * Number of objects in the data_objects array
    1592                 :            :      */
    1593                 :            :     size_t num_objects;
    1594                 :            : 
    1595                 :            :     /**
    1596                 :            :      * Semaphore to lock this context and avoid race conditions if the context may be used by
    1597                 :            :      * multiple threads in parallel.
    1598                 :            :      */
    1599                 :            :     struct k_sem lock;
    1600                 :            : 
    1601                 :            :     /**
    1602                 :            :      * Pointer to the incoming message buffer (request or desire, provided by process function)
    1603                 :            :      */
    1604                 :            :     const uint8_t *msg;
    1605                 :            : 
    1606                 :            :     /**
    1607                 :            :      * Length of the incoming message
    1608                 :            :      */
    1609                 :            :     size_t msg_len;
    1610                 :            : 
    1611                 :            :     /**
    1612                 :            :      * Position in the message currently being parsed
    1613                 :            :      */
    1614                 :            :     size_t msg_pos;
    1615                 :            : 
    1616                 :            :     /**
    1617                 :            :      * Pointer to the start of the payload in the message buffer
    1618                 :            :      */
    1619                 :            :     const uint8_t *msg_payload;
    1620                 :            : 
    1621                 :            :     /**
    1622                 :            :      * Pointer to the response buffer (provided by process function)
    1623                 :            :      */
    1624                 :            :     uint8_t *rsp;
    1625                 :            : 
    1626                 :            :     /**
    1627                 :            :      * Size of response buffer (i.e. maximum length)
    1628                 :            :      */
    1629                 :            :     size_t rsp_size;
    1630                 :            : 
    1631                 :            :     /**
    1632                 :            :      * Current position inside the response (equivalent to length of the response at end of
    1633                 :            :      * processing)
    1634                 :            :      */
    1635                 :            :     size_t rsp_pos;
    1636                 :            : 
    1637                 :            :     /**
    1638                 :            :      * Function pointers to mode-specific implementation (text or binary)
    1639                 :            :      */
    1640                 :            :     struct thingset_api *api;
    1641                 :            : 
    1642                 :            :     /**
    1643                 :            :      * State information for data processing, either for text mode or binary mode depending on the
    1644                 :            :      * assigned api.
    1645                 :            :      */
    1646                 :            :     union {
    1647                 :            :         /* Text mode */
    1648                 :            :         struct
    1649                 :            :         {
    1650                 :            :             /** JSON tokens in msg_payload parsed by JSMN */
    1651                 :            :             jsmntok_t tokens[CONFIG_THINGSET_NUM_JSON_TOKENS];
    1652                 :            : 
    1653                 :            :             /** Number of JSON tokens parsed by JSMN */
    1654                 :            :             size_t tok_count;
    1655                 :            : 
    1656                 :            :             /** Current position of the parsing process */
    1657                 :            :             size_t tok_pos;
    1658                 :            :         };
    1659                 :            :         /* Binary mode */
    1660                 :            :         struct
    1661                 :            :         {
    1662                 :            :             /** CBOR encoder states for binary mode */
    1663                 :            :             zcbor_state_t encoder[CONFIG_THINGSET_BINARY_MAX_DEPTH];
    1664                 :            : 
    1665                 :            :             /** CBOR decoder states for binary mode */
    1666                 :            :             zcbor_state_t decoder[CONFIG_THINGSET_BINARY_MAX_DEPTH];
    1667                 :            :         };
    1668                 :            :     };
    1669                 :            : 
    1670                 :            :     /**
    1671                 :            :      * Stores current authentication status (authentication as "normal" user as default)
    1672                 :            :      */
    1673                 :            :     uint8_t auth_flags;
    1674                 :            : 
    1675                 :            :     /**
    1676                 :            :      * Stores current authentication status (authentication as "normal" user as default)
    1677                 :            :      */
    1678                 :            :     uint8_t update_subsets;
    1679                 :            : 
    1680                 :            :     /**
    1681                 :            :      * Callback to be called from patch function if a value belonging to update_subsets
    1682                 :            :      * was changed
    1683                 :            :      */
    1684                 :            :     void (*update_cb)(void);
    1685                 :            : 
    1686                 :            :     /**
    1687                 :            :      * Endpoint used for the current message
    1688                 :            :      */
    1689                 :            :     struct thingset_endpoint endpoint;
    1690                 :            : };
    1691                 :            : 
    1692                 :            : /**
    1693                 :            :  * Initialize a ThingSet context.
    1694                 :            :  *
    1695                 :            :  * @param ts Pointer to ThingSet context.
    1696                 :            :  * @param objects Pointer to array containing the ThingSet object database
    1697                 :            :  * @param num_objects Number of elements in that array
    1698                 :            :  */
    1699                 :            : void thingset_init(struct thingset_context *ts, struct thingset_data_object *objects,
    1700                 :            :                    size_t num_objects);
    1701                 :            : 
    1702                 :            : /**
    1703                 :            :  * Initialize a ThingSet context using Zephyr iterable sections.
    1704                 :            :  *
    1705                 :            :  * Data objects defined using THINGSET_ADD_* macros will be magically added to the object database
    1706                 :            :  * by the linker.
    1707                 :            :  *
    1708                 :            :  * @param ts Pointer to ThingSet context.
    1709                 :            :  */
    1710                 :            : void thingset_init_global(struct thingset_context *ts);
    1711                 :            : 
    1712                 :            : /**
    1713                 :            :  * Process ThingSet request or desire.
    1714                 :            :  *
    1715                 :            :  * This function also detects if text mode (JSON) or binary mode (CBOR) is used.
    1716                 :            :  *
    1717                 :            :  * The string in the buffer will be null-terminated in case of text mode, but the termination
    1718                 :            :  * character is not included in the returned length.
    1719                 :            :  *
    1720                 :            :  * @param ts Pointer to ThingSet context.
    1721                 :            :  * @param msg Pointer to the ThingSet message (request or desire)
    1722                 :            :  * @param msg_len Length of the message
    1723                 :            :  * @param rsp Pointer to the buffer where the response should be stored (if any)
    1724                 :            :  * @param rsp_size Size of the response buffer
    1725                 :            :  *
    1726                 :            :  * @retval rsp_len Length of the response written to the buffer after processing a request
    1727                 :            :  * @retval 0 If the message was empty or a desire was processed successfully (no response)
    1728                 :            :  * @retval err Negative ThingSet response code if a desire could not be processed successfully
    1729                 :            :  */
    1730                 :            : int thingset_process_message(struct thingset_context *ts, const uint8_t *msg, size_t msg_len,
    1731                 :            :                              uint8_t *rsp, size_t rsp_size);
    1732                 :            : 
    1733                 :            : /**
    1734                 :            :  * Retrieve data for given subset(s).
    1735                 :            :  *
    1736                 :            :  * This function does not return a complete ThingSet message, but only the payload data as a
    1737                 :            :  * name/value map. It can be used e.g. to store data in the EEPROM or other non-volatile memory.
    1738                 :            :  *
    1739                 :            :  * The string in the buffer will be null-terminated, but the termination character is not included
    1740                 :            :  * in the returned length.
    1741                 :            :  *
    1742                 :            :  * @param ts Pointer to ThingSet context.
    1743                 :            :  * @param buf Pointer to the buffer where the data should be stored
    1744                 :            :  * @param buf_size Size of the buffer, i.e. maximum allowed length of the data
    1745                 :            :  * @param subsets Flags to select which subset(s) of data items should be exported
    1746                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1747                 :            :  *
    1748                 :            :  * @return Actual length of the data or negative ThingSet response code in case of error.
    1749                 :            :  */
    1750                 :            : int thingset_export_subsets(struct thingset_context *ts, uint8_t *buf, size_t buf_size,
    1751                 :            :                             uint16_t subsets, enum thingset_data_format format);
    1752                 :            : 
    1753                 :            : /**
    1754                 :            :  * EXPERIMENTAL
    1755                 :            :  *
    1756                 :            :  * Exports object data for the given subset to the supplied buffer in the specified format starting
    1757                 :            :  * at the given object index. At present, only binary formats are supported.
    1758                 :            :  *
    1759                 :            :  * @param ts Pointer to ThingSet context.
    1760                 :            :  * @param buf Pointer to the buffer where the data should be stored
    1761                 :            :  * @param buf_size Size of the buffer, i.e. maximum allowed length of the data
    1762                 :            :  * @param subsets Flags to select which subset(s) of data items should be exported
    1763                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1764                 :            :  * @param index Pointer to an integer which tracks the current object being exported
    1765                 :            :  * @param len Number of bytes written to the buffer
    1766                 :            :  *
    1767                 :            :  * @returns 1 if there are more objects to export, 0 when complete or negative if an error.
    1768                 :            :  */
    1769                 :            : int thingset_export_subsets_progressively(struct thingset_context *ts, uint8_t *buf,
    1770                 :            :                                           size_t buf_size, uint16_t subsets,
    1771                 :            :                                           enum thingset_data_format format, unsigned int *index,
    1772                 :            :                                           size_t *len);
    1773                 :            : 
    1774                 :            : /**
    1775                 :            :  * Export id, value and/or name of a single data item.
    1776                 :            :  *
    1777                 :            :  * This function is typically used together with thingset_iterate_subsets to export items of a
    1778                 :            :  * subset one by one, e.g. for publishing them via CAN.
    1779                 :            :  *
    1780                 :            :  * The string in the buffer will be null-terminated, but the termination character is not included
    1781                 :            :  * in the returned length.
    1782                 :            :  *
    1783                 :            :  * @param ts Pointer to ThingSet context.
    1784                 :            :  * @param buf Pointer to the buffer where the data should be stored
    1785                 :            :  * @param buf_size Size of the buffer, i.e. maximum allowed length of the data
    1786                 :            :  * @param obj Pointer to data item which should be exported
    1787                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1788                 :            :  *
    1789                 :            :  * @return Actual length of the data or negative ThingSet response code in case of error.
    1790                 :            :  */
    1791                 :            : int thingset_export_item(struct thingset_context *ts, uint8_t *buf, size_t buf_size,
    1792                 :            :                          const struct thingset_data_object *obj, enum thingset_data_format format);
    1793                 :            : 
    1794                 :            : /**
    1795                 :            :  * Iterate over all objects of given subset(s).
    1796                 :            :  *
    1797                 :            :  * @param ts Pointer to ThingSet context.
    1798                 :            :  * @param subsets Flags to select which subset(s) of data items should be iterated over
    1799                 :            :  * @param start_obj Data object to start searching (use NULL to start at the beginning)
    1800                 :            :  *
    1801                 :            :  * @returns Pointer to the next object found or NULL if end of data objects was reached
    1802                 :            :  */
    1803                 :            : struct thingset_data_object *thingset_iterate_subsets(struct thingset_context *ts, uint16_t subset,
    1804                 :            :                                                       struct thingset_data_object *start_obj);
    1805                 :            : 
    1806                 :            : /**
    1807                 :            :  * Import data into data objects.
    1808                 :            :  *
    1809                 :            :  * This function can be used to initialize data objects from previously exported data (using
    1810                 :            :  * thingset_export_subsets function) and stored in the EEPROM or other non-volatile memory.
    1811                 :            :  *
    1812                 :            :  * Unknown data items are silently ignored.
    1813                 :            :  *
    1814                 :            :  * @param ts Pointer to ThingSet context.
    1815                 :            :  * @param data Buffer containing ID/value map that should be written to the data objects
    1816                 :            :  * @param len Length of the data in the buffer
    1817                 :            :  * @param auth_flags Authentication flags to be used in this function (to override auth_flags)
    1818                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1819                 :            :  *
    1820                 :            :  * @returns 0 for success or negative ThingSet response code in case of error
    1821                 :            :  */
    1822                 :            : int thingset_import_data(struct thingset_context *ts, const uint8_t *data, size_t len,
    1823                 :            :                          uint8_t auth_flags, enum thingset_data_format format);
    1824                 :            : 
    1825                 :            : /**
    1826                 :            :  * Import report into data objects.
    1827                 :            :  *
    1828                 :            :  * This function allows importing data objects from a received report.
    1829                 :            :  *
    1830                 :            :  * Unknown data items are silently ignored.
    1831                 :            :  *
    1832                 :            :  * @param ts Pointer to ThingSet context.
    1833                 :            :  * @param data Buffer containing ID/value map that should be written to the data objects
    1834                 :            :  * @param len Length of the data in the buffer
    1835                 :            :  * @param auth_flags Authentication flags to be used in this function (to override auth_flags)
    1836                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1837                 :            :  * @param subset The subset associated with the published report
    1838                 :            :  *
    1839                 :            :  * @returns 0 for success or negative ThingSet response code in case of error
    1840                 :            :  */
    1841                 :            : int thingset_import_report(struct thingset_context *ts, const uint8_t *data, size_t len,
    1842                 :            :                            uint8_t auth_flags, enum thingset_data_format format, uint16_t subset);
    1843                 :            : 
    1844                 :            : /**
    1845                 :            :  * EXPERIMENTAL
    1846                 :            :  *
    1847                 :            :  * Import data from a buffer into data objects.
    1848                 :            :  *
    1849                 :            :  * This function can be used to initialize data objects from previously exported data (using
    1850                 :            :  * thingset_export_subsets function) and stored in the EEPROM or other non-volatile memory.
    1851                 :            :  *
    1852                 :            :  * Unknown data items are silently ignored.
    1853                 :            :  *
    1854                 :            :  * @param ts Pointer to ThingSet context.
    1855                 :            :  * @param data Buffer containing ID/value map that should be written to the data objects
    1856                 :            :  * @param len Length of the data in the buffer
    1857                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1858                 :            :  * @param auth_flags Authentication flags to be used in this function (to override auth_flags)
    1859                 :            :  * @param last_id ID of last object successfully processed. This *must* be 0 for the first call.
    1860                 :            :  * @param consumed When the method returns, contains the number of bytes consumed. This may be
    1861                 :            :  * less than @ref size.
    1862                 :            :  *
    1863                 :            :  * @returns 0 for success, 1 if more data is required or negative ThingSet response code
    1864                 :            :  * in case of error
    1865                 :            :  */
    1866                 :            : int thingset_import_data_progressively(struct thingset_context *ts, const uint8_t *data, size_t len,
    1867                 :            :                                        enum thingset_data_format format, uint8_t auth_flags,
    1868                 :            :                                        uint32_t *last_id, size_t *consumed);
    1869                 :            : 
    1870                 :            : /**
    1871                 :            :  * Completes the import of data from the buffer passed to @ref
    1872                 :            :  * thingset_begin_import_data_progressively into data objects.
    1873                 :            :  * Call this method if an import completes without errors.
    1874                 :            :  *
    1875                 :            :  * @param ts Pointer to ThingSet context.
    1876                 :            :  *
    1877                 :            :  * @returns 0 for success
    1878                 :            :  */
    1879                 :            : int thingset_import_data_progressively_end(struct thingset_context *ts);
    1880                 :            : 
    1881                 :            : /**
    1882                 :            :  * Import data into a record.
    1883                 :            :  *
    1884                 :            :  * Unknown data items are silently ignored.
    1885                 :            :  *
    1886                 :            :  * @param ts Pointer to ThingSet context.
    1887                 :            :  * @param data Buffer containing ID/value map that should be written to the record
    1888                 :            :  * @param len Length of the data in the buffer
    1889                 :            :  * @param endpoint Records endpoint (including index) to be used
    1890                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1891                 :            :  *
    1892                 :            :  * @returns 0 for success or negative ThingSet response code in case of error
    1893                 :            :  */
    1894                 :            : int thingset_import_record(struct thingset_context *ts, const uint8_t *data, size_t len,
    1895                 :            :                            struct thingset_endpoint *endpoint, enum thingset_data_format format);
    1896                 :            : 
    1897                 :            : /**
    1898                 :            :  * Generate a report for a given path.
    1899                 :            :  *
    1900                 :            :  * @note Searching the object database to find the path and items to be published based on the
    1901                 :            :  * path provides the most user-friendly API, but is not the most efficient way to generate the
    1902                 :            :  * report. A more efficient method which caches the pointers to the data objects may be added
    1903                 :            :  * in the future.
    1904                 :            :  *
    1905                 :            :  * The string in the buffer will be null-terminated, but the termination character is not included
    1906                 :            :  * in the returned length.
    1907                 :            :  *
    1908                 :            :  * @param ts Pointer to ThingSet context.
    1909                 :            :  * @param buf Pointer to the buffer where the report should be stored
    1910                 :            :  * @param buf_size Size of the buffer, i.e. maximum allowed length of the report
    1911                 :            :  * @param path Path of subset/group/record to be published
    1912                 :            :  * @param format Protocol data format to be used (text, binary with IDs or binary with names)
    1913                 :            :  *
    1914                 :            :  * @return Actual length of the report or negative ThingSet response code in case of error
    1915                 :            :  */
    1916                 :            : int thingset_report_path(struct thingset_context *ts, char *buf, size_t buf_size, const char *path,
    1917                 :            :                          enum thingset_data_format format);
    1918                 :            : 
    1919                 :            : /**
    1920                 :            :  * Set current authentication level.
    1921                 :            :  *
    1922                 :            :  * The authentication flags must match with read/write access flags of the a data objects.
    1923                 :            :  *
    1924                 :            :  * @param ts Pointer to ThingSet context.
    1925                 :            :  * @param flags Flags to define authentication level (1 = access allowed)
    1926                 :            :  */
    1927                 :            : void thingset_set_authentication(struct thingset_context *ts, uint8_t flags);
    1928                 :            : 
    1929                 :            : /**
    1930                 :            :  * Configure a callback for notification if data belonging to specified subset(s) was updated.
    1931                 :            :  *
    1932                 :            :  * @param ts Pointer to ThingSet context.
    1933                 :            :  * @param subsets Flags to select which subset(s) of data items should be considered
    1934                 :            :  * @param update_cb Callback to be called after an update.
    1935                 :            :  */
    1936                 :            : void thingset_set_update_callback(struct thingset_context *ts, const uint16_t subsets,
    1937                 :            :                                   void (*update_cb)(void));
    1938                 :            : 
    1939                 :            : /**
    1940                 :            :  * Get the endpoint from a provided path.
    1941                 :            :  *
    1942                 :            :  * @param ts Pointer to ThingSet context.
    1943                 :            :  * @param endpoint Pointer to the struct thingset_endpoint to store the result.
    1944                 :            :  * @param path Relative path with multiple object names separated by forward slash.
    1945                 :            :  * @param len Length of the entire path.
    1946                 :            :  *
    1947                 :            :  * @return 0 if successful or negative ThingSet error code to be reported
    1948                 :            :  */
    1949                 :            : int thingset_endpoint_by_path(struct thingset_context *ts, struct thingset_endpoint *endpoint,
    1950                 :            :                               const char *path, size_t len);
    1951                 :            : 
    1952                 :            : /**
    1953                 :            :  * Get the endpoint from a provided ID.
    1954                 :            :  *
    1955                 :            :  * @param ts Pointer to ThingSet context.
    1956                 :            :  * @param endpoint Pointer to the struct thingset_endpoint to store the result.
    1957                 :            :  * @param id Numeric ID of the ThingSet object.
    1958                 :            :  *
    1959                 :            :  * @return 0 if successful or negative ThingSet error code to be reported
    1960                 :            :  */
    1961                 :            : int thingset_endpoint_by_id(struct thingset_context *ts, struct thingset_endpoint *endpoint,
    1962                 :            :                             uint16_t id);
    1963                 :            : 
    1964                 :            : #ifdef __cplusplus
    1965                 :            : } /* extern "C" */
    1966                 :            : #endif
    1967                 :            : 
    1968                 :            : #endif /* THINGSET_H_ */

Generated by: LCOV version 1.14