From d1282841098a30131bd2dc88cc9d33df269885ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Tue, 5 Mar 2024 22:53:56 +0100 Subject: [PATCH] Add function to export subsets in chunks This is useful if large amounts of data should be exported using small buffer sizes. --- include/thingset.h | 29 +++++++++++++++++++++++++++-- src/thingset.c | 9 +++++---- tests/protocol/src/bin.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/include/thingset.h b/include/thingset.h index 5b7ad5d..502e81d 100644 --- a/include/thingset.h +++ b/include/thingset.h @@ -1693,6 +1693,27 @@ void thingset_init_global(struct thingset_context *ts); int thingset_process_message(struct thingset_context *ts, const uint8_t *msg, size_t msg_len, uint8_t *rsp, size_t rsp_size); +/** + * Retrieve data for given subset(s) in chunks. + * + * Exports object data for the given subset to the supplied buffer in the specified format starting + * at the given object index. At present, only binary formats are supported. + * + * @param ts Pointer to ThingSet context. + * @param buf Pointer to the buffer where the data should be stored + * @param buf_size Size of the buffer, i.e. maximum allowed length of the data + * @param subsets Flags to select which subset(s) of data items should be exported + * @param format Protocol data format to be used (text, binary with IDs or binary with names) + * @param index Pointer to an integer which tracks the current object being exported + * + * @retval len Length of the written chunk. + * @retval 0 When export is complete. + * @retval err Negative ThingSet response code in case of error. + */ +int thingset_export_subsets_chunks(struct thingset_context *ts, uint8_t *buf, size_t buf_size, + uint16_t subsets, enum thingset_data_format format, + uint16_t *index); + /** * Retrieve data for given subset(s). * @@ -1710,8 +1731,12 @@ int thingset_process_message(struct thingset_context *ts, const uint8_t *msg, si * * @return Actual length of the data or negative ThingSet response code in case of error. */ -int thingset_export_subsets(struct thingset_context *ts, uint8_t *buf, size_t buf_size, - uint16_t subsets, enum thingset_data_format format); +static inline int thingset_export_subsets(struct thingset_context *ts, uint8_t *buf, + size_t buf_size, uint16_t subsets, + enum thingset_data_format format) +{ + return thingset_export_subsets_chunks(ts, buf, buf_size, subsets, format, NULL); +} /** * Export id, value and/or name of a single data item. diff --git a/src/thingset.c b/src/thingset.c index c3d5e29..d717a0e 100644 --- a/src/thingset.c +++ b/src/thingset.c @@ -130,8 +130,9 @@ int thingset_process_message(struct thingset_context *ts, const uint8_t *msg, si return ret; } -int thingset_export_subsets(struct thingset_context *ts, uint8_t *buf, size_t buf_size, - uint16_t subsets, enum thingset_data_format format) +int thingset_export_subsets_chunks(struct thingset_context *ts, uint8_t *buf, size_t buf_size, + uint16_t subsets, enum thingset_data_format format, + uint16_t *index) { int ret; @@ -156,11 +157,11 @@ int thingset_export_subsets(struct thingset_context *ts, uint8_t *buf, size_t bu return -THINGSET_ERR_NOT_IMPLEMENTED; } - ret = ts->api->serialize_subsets(ts, subsets, NULL); + ret = ts->api->serialize_subsets(ts, subsets, index); ts->api->serialize_finish(ts); - if (ret == 0) { + if (ret == 0 || ret == 1) { ret = ts->rsp_pos; } diff --git a/tests/protocol/src/bin.c b/tests/protocol/src/bin.c index 2852404..62b11cc 100644 --- a/tests/protocol/src/bin.c +++ b/tests/protocol/src/bin.c @@ -876,6 +876,40 @@ ZTEST(thingset_bin, test_export_item) zassert_mem_equal(buf_exp, buf_act, 2); } +ZTEST(thingset_bin, test_export_subsets_chunks) +{ + uint8_t buf_chunk[16]; + uint16_t index = 0; + int ret; + + const char chunk1_exp_hex[] = + "A3 " + "10 19 03 E8 " /* t_s */ + "19 02 01 F5 " /* Types/wBool */ + "19 06 00 02"; /* Records: 2 */ + uint8_t chunk1_exp[THINGSET_TEST_BUF_SIZE]; + int chunk1_exp_len = hex2bin_spaced(chunk1_exp_hex, chunk1_exp, sizeof(chunk1_exp)); + + const char chunk2_exp_hex[] = + "A2 " + "19 07 01 01 " /* Nested/rBeginning */ + "19 07 08 FA 40 0C CC CD"; /* Nested/Obj2/rItem2_V */ + uint8_t chunk2_exp[THINGSET_TEST_BUF_SIZE]; + int chunk2_exp_len = hex2bin_spaced(chunk2_exp_hex, chunk2_exp, sizeof(chunk2_exp)); + + ret = thingset_export_subsets_chunks(&ts, buf_chunk, sizeof(buf_chunk), SUBSET_LIVE, + THINGSET_BIN_IDS_VALUES, &index); + zassert_equal(ret, chunk1_exp_len); + zassert_not_equal(index, 0); + zassert_mem_equal(chunk1_exp, buf_chunk, chunk1_exp_len); + + ret = thingset_export_subsets_chunks(&ts, buf_chunk, sizeof(buf_chunk), SUBSET_LIVE, + THINGSET_BIN_IDS_VALUES, &index); + zassert_equal(ret, chunk2_exp_len); + zassert_equal(index, 0); + zassert_mem_equal(chunk2_exp, buf_chunk, chunk2_exp_len); +} + ZTEST(thingset_bin, test_iterate_subsets) { struct thingset_data_object *obj = NULL;