From 5d6f27b54cbafd144eca69dd532df0c492060895 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Wed, 20 Nov 2024 11:17:27 +0100 Subject: [PATCH] skald_bthome_saul: add message fragmentation --- sys/include/net/skald/bthome.h | 18 +++++++++++++ sys/net/ble/skald/skald_bthome.c | 5 +++- sys/net/ble/skald/skald_bthome_saul.c | 38 ++++++++++++++++++++------- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/sys/include/net/skald/bthome.h b/sys/include/net/skald/bthome.h index 4a4edf50d8..249faaa02c 100644 --- a/sys/include/net/skald/bthome.h +++ b/sys/include/net/skald/bthome.h @@ -167,6 +167,24 @@ struct skald_bthome_ctx { */ uint8_t encrypt; #endif +#if IS_USED(MODULE_SKALD_BTHOME_SAUL) || defined(DOXYGEN) + /** + * @brief The index of the last device sent in skald_bthome_ctx_t::devs. + * + * Will be updated on each periodic advertisement to allow for fragmenting + * different measurement readings across multiple advertisements (in case all + * measurements from skald_bthome_ctx_t::devs are too large for one + * advertisement). Is initialized to 0. + * + * If a single reading is too big to fit into an advertisement, + * the skald_ctx_t::update_pkt() callback will just return (i.e. BTHome + * payload may be left empty) and skald_bthome_ctx_t::last_dev_sent will + * be reset to 0. + * This can e.g. happen with a @ref BTHOME_ID_TEXT or @ref BTHOME_ID_RAW record + * if the appended bytes are larger than a BLE advertisement. + */ + uint8_t last_dev_sent; +#endif }; /** diff --git a/sys/net/ble/skald/skald_bthome.c b/sys/net/ble/skald/skald_bthome.c index f81269ac9b..dce28b3cdb 100644 --- a/sys/net/ble/skald/skald_bthome.c +++ b/sys/net/ble/skald/skald_bthome.c @@ -160,8 +160,11 @@ int skald_bthome_add_measurement( uint16_t exp_size = ctx->skald.pkt.len + sizeof(obj_id) + data_len + data_contains_length; uint8_t offset = ctx->skald.pkt.len; +#ifdef MODULE_SKALD_BTHOME_ENCRYPT + exp_size += 8; +#endif + if (exp_size >= NETDEV_BLE_PDU_MAXLEN) { - assert(exp_size < NETDEV_BLE_PDU_MAXLEN); return -EMSGSIZE; } ctx->skald.pkt.pdu[offset++] = (uint8_t)obj_id; diff --git a/sys/net/ble/skald/skald_bthome_saul.c b/sys/net/ble/skald/skald_bthome_saul.c index 7c36c855db..238598fb5a 100644 --- a/sys/net/ble/skald/skald_bthome_saul.c +++ b/sys/net/ble/skald/skald_bthome_saul.c @@ -423,32 +423,50 @@ static void _reset_hdr(skald_bthome_ctx_t *ctx) static void _update_saul_measurements(skald_ctx_t *skald_ctx) { skald_bthome_ctx_t *ctx = container_of(skald_ctx, skald_bthome_ctx_t, skald); + uint8_t dev_idx = 0; + uint8_t orig_last_dev_sent = ctx->last_dev_sent; _reset_hdr(ctx); skald_bthome_saul_t *ptr = ctx->devs; while (ptr) { - int dim = 1; - phydat_t data = { 0 }; + if ((ctx->last_dev_sent == 0) || + (dev_idx > ctx->last_dev_sent)) { + int dim = 1; + int res = 0; + phydat_t data = { 0 }; - if (ptr->saul.driver) { - dim = saul_reg_read(&ptr->saul, &data); - if (dim <= 0) { - continue; + if (ptr->saul.driver) { + dim = saul_reg_read(&ptr->saul, &data); + if (dim <= 0) { + continue; + } } - } - for (uint8_t i = 0; i < dim; i++) { - if (ptr->add_measurement(ctx, ptr->obj_id, &data, i) < 0) { + for (uint8_t i = 0; i < dim; i++) { + if ((res = ptr->add_measurement(ctx, ptr->obj_id, &data, i)) < 0) { + break; + } + } + if ((res == -EMSGSIZE) && (dev_idx > 0)) { + ctx->last_dev_sent = dev_idx - 1; + } + if (res < 0) { break; } } - ptr = container_of( ptr->saul.next, skald_bthome_saul_t, saul ); + dev_idx++; } #if IS_USED(MODULE_SKALD_BTHOME_ENCRYPT) skald_bthome_encrypt(ctx); #endif + if ((ptr == NULL) || + /* or value just too big */ + (orig_last_dev_sent == ctx->last_dev_sent)) { + /* reset device train */ + ctx->last_dev_sent = 0; + } } int skald_bthome_saul_add(skald_bthome_ctx_t *ctx, skald_bthome_saul_t *saul)