BLE gateway software architecture

Continuing the discussion of

From @floyddotnet

Maybe for the feature it would be a good idear in my opinion to split the communication and the parsing / processing into seperate files like:

// communication / platform related source in this files:
main/BLE/module/ESP32.ino
main/BLE/module/HM10.ino

// ble device related source into this file
main/BLE/device/general.ino
main/BLE/device/xiaomi.ino

// high level source (like module init, call device related source)
main/ZgatewayBT.ino

during this process we could add an abstraction layer for the communication / platform into main/BLE/module/abstraction.ino

        +-------------------+           +--------------------------------------------------+
+-------+main/ZgatewayBT.ino| +-------> |compile with one of the communication device files|
|       +-------------------+           +--------------------------------------------------+
|
|                 ^                                  +
|                 |                                  |
|                 |                           +------+-----------+
|                 |                           v                  v
|                 +
|                                       +---------+          +-------+
|         +-----------------+           |ESP32.ino|          |M10.ino|      Both are abstractions
|         |callback with new|           +---------+          +-------+      with has exactly the
|         |de^ice date      |          +                              +     same methods
|         +-----------------+          +--------------+---------------+
|                                                     |
|                ^                                    |
|                |                                    |
|                +------------------------------------+
|
|
|
|
|
|          +------------------------------+
+--------> |call ble device related source|
           +------------------------------+
           |xiaomi.ino                    |
           |.....                         |
           +------------------------------+
1 Like

From @floyddotnet

i donā€™t know if you confirm with the concept of interfaces and polymorphy.

the goal:

  1. separation of concerns & single-responsibility (each file should do only one job (a single part of the functionality))
  2. better readability (no file has more functions as it needed, avoiding spaghettification of the source in one file, avoiding to large files)
  3. following the open-close-princip (it is simple to add a new ble communication module without needing to modify the existing ones by creating a new file ā€˜main/BLE/module/HC05.inoā€™ and register it in main/ZgatewayBT.ino ; the same for supporting a new ble device)

From @floyddotnet

i mean something like this:

// main/BLE/module/ESP32.ino
ble_module_init(){ /* ... */ }
ble_module_register_advertised_device_callback(void (*callback)(JsonObject &BLEdat)){ /* ... */ }

// main/BLE/module/HM10.ino
ble_module_init(){ /* ... */ }
ble_module_register_advertised_device_callback(void (*callback)(JsonObject &BLEdat)){ /* ... */ }

// main/ZgatewayBT.ino
#ifdef ESP32
  #include <main/BLE/module/ESP32.ino>
#else
    #include <main/BLE/module/HM10.ino>
#endif

void advertised_device_callback(JsonObject &BLEdat) {
  if ((!oneWhite || isWhite(device)) && !isBlack(BLEdat))
  {
   //..
   PublishDeviceData(BLEdata);
  }
}

ble_module_init();
ble_module_register_advertised_device_callback(*advertised_device_callback);

@floyddotnet,
Thanks for these interesting proposals,
Added to that, does it makes sense in your point of view to use vectors of structure for the white and black list management?

Iā€™m thinking on expanding this functionality to the other gateways and Iā€™m asking myself if it is the best way to manage these restrictive lists.
Maybe a vector of Json Object would be easier to maintain and more coherent with the other functions.

topic white and blacklist:

I needed some time to thinking about the implication of this changes. At first, i think JsonObject should only used if it needed. because its consums muth more memory as an struct and accessing a field consumse more time and energy too.

in my opinion, two simple arrayā€™s of ids for white and blacklist or a simple array of struct is all we need and the best what we can do in terms of memory and performance. but i confirm with this point that a vector (or two) of ids / structs are easyer to maintence.

adopting this concept could be done by adding a prefix to the idā€™s or a type-flag. like:

blacklist: [ ā€œBT_00:22:fa:17:00:00ā€, ā€œIR_ dcba003dd00aaā€, ā€œā€¦ā€]

I really like the proposal and I agree, it would improve the readability of the code. Iā€™m currently working on including code for ruuvi tags and Iā€™m looking forward to this change.

Credit to @floyddotnet

I didnā€™t know these tags, they are very interesting

They are actually very well made and reliable, also low in power consumption. Protocol is public on Github (ruuvi-sensor-protocols/broadcast_formats.md at master Ā· ruuvi/ruuvi-sensor-protocols Ā· GitHub), all data is advertised very efficiently in the ā€œmanufacturerdataā€. (latest raw format, V5 ruuvi-sensor-protocols/dataformat_05.md at master Ā· ruuvi/ruuvi-sensor-protocols Ā· GitHub). While Iā€™m looking deeper in your implementation, it looks like most of the things I need are already there.

Since im playing around with the current implementation, I would need your advice for alter the ā€œvalue_from_service_dataā€ function. For the ruuvi-Tags I donā€™t need the revers order for the values. Would it be better to write a device specific ā€œvalue_from_serviceā€-function or should I extend the existing function?

I would prefer this one (less code to add).

1 Like

For info Iā€™m going to publish a PR with this modification, as I needed it for another purpose

1 Like

OK, thanks. Iā€™m still testing my modifications. Will publish the ruuvi support later this week.