From eea438bcad33bd1de80a62ddf0d72172e41ba4d5 Mon Sep 17 00:00:00 2001 From: Raj Nakarja Date: Thu, 30 Jan 2025 17:12:49 +0100 Subject: [PATCH 1/4] WIP decompression feature and callback --- source/application/Makefile | 1 + .../application/lua_libraries/compression.c | 112 ++++++++++++++++++ .../lua_libraries/frame_lua_libraries.h | 1 + source/application/luaport.c | 1 + 4 files changed, 115 insertions(+) create mode 100644 source/application/lua_libraries/compression.c diff --git a/source/application/Makefile b/source/application/Makefile index 54bfd551..45126216 100644 --- a/source/application/Makefile +++ b/source/application/Makefile @@ -39,6 +39,7 @@ C_FILES += \ watchdog.c \ lua_libraries/bluetooth.c \ lua_libraries/camera.c \ + lua_libraries/compression.c \ lua_libraries/display.c \ lua_libraries/file.c \ lua_libraries/imu.c \ diff --git a/source/application/lua_libraries/compression.c b/source/application/lua_libraries/compression.c new file mode 100644 index 00000000..97c8b15a --- /dev/null +++ b/source/application/lua_libraries/compression.c @@ -0,0 +1,112 @@ +/* + * This file is a part of: https://github.com/brilliantlabsAR/frame-codebase + * + * Authored by: Raj Nakarja / Brilliant Labs Ltd. (raj@brilliant.xyz) + * Rohit Rathnam / Silicon Witchery AB (rohit@siliconwitchery.com) + * Uma S. Gupta / Techno Exponent (umasankar@technoexponent.com) + * + * ISC Licence + * + * Copyright © 2025 Brilliant Labs Ltd. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "compression.h" +#include "frame_lua_libraries.h" +#include "lauxlib.h" +#include "lua.h" +#include "watchdog.h" + +static int registered_function = 0; + +static void decompression_lua_handler(lua_State *L, lua_Debug *ar) +{ + sethook_watchdog(L); + + if (registered_function != 0) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, registered_function); + + // TODO: Add the data to the function call if it's not already added + + if (lua_pcall(L, 0, 0, 0) != LUA_OK) + { + luaL_error(L, "%s", lua_tostring(L, -1)); + } + } +} + +static void process_function_callback(void *context, + void *data, + size_t data_size) +{ + // TODO copy the data to a buffer + + lua_sethook(L_global, + decompression_lua_handler, + LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, + 1); +} + +static int lua_compression_register_process_function(lua_State *L) +{ + if (lua_isnil(L, 1)) + { + registered_function = 0; + return 0; + } + + if (lua_isfunction(L, 1)) + { + registered_function = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; + } + + luaL_error(L, "expected nil or function"); + + return 0; +} + +static int lua_compression_decompress(lua_State *L) +{ + int status = compression_decompress(4096, // TODO figure out destination size + NULL, // TODO pass the source data to the decompression function + sizeof(0), // TODO set the source data size + process_function_callback, + NULL); + + if (status != 0) + { + luaL_error(L, "decompression failed"); + } + + return 0; +} + +void lua_open_compression_library(lua_State *L) +{ + lua_getglobal(L, "frame"); + + lua_newtable(L); + + lua_pushcfunction(L, lua_compression_register_process_function); + lua_setfield(L, -2, "process_function"); + + lua_pushcfunction(L, lua_compression_decompress); + lua_setfield(L, -2, "decompress"); + + lua_setfield(L, -2, "compression"); + + lua_pop(L, 1); +} \ No newline at end of file diff --git a/source/application/lua_libraries/frame_lua_libraries.h b/source/application/lua_libraries/frame_lua_libraries.h index a7151ae6..2b53dea4 100644 --- a/source/application/lua_libraries/frame_lua_libraries.h +++ b/source/application/lua_libraries/frame_lua_libraries.h @@ -33,6 +33,7 @@ void lua_bluetooth_data_interrupt(uint8_t *data, size_t length); void lua_open_bluetooth_library(lua_State *L); void lua_open_camera_library(lua_State *L); +void lua_open_compression_library(lua_State *L); void lua_open_display_library(lua_State *L); void lua_open_imu_library(lua_State *L); void lua_open_led_library(lua_State *L); diff --git a/source/application/luaport.c b/source/application/luaport.c index befdd804..4506f744 100644 --- a/source/application/luaport.c +++ b/source/application/luaport.c @@ -99,6 +99,7 @@ void run_lua(bool is_paired) lua_open_imu_library(L); lua_open_time_library(L); lua_open_led_library(L); + lua_open_compression_library(L); lua_open_file_library(L, !is_paired); From 9eae8d15806e83aeaaf7a2c12c5bf46f7377fd43 Mon Sep 17 00:00:00 2001 From: Raj Nakarja Date: Thu, 30 Jan 2025 18:34:58 +0100 Subject: [PATCH 2/4] Added initial test Added header length calc code to compression core file --- source/application/compression.c | 51 +++++++++- .../application/lua_libraries/compression.c | 96 +++++++++++++++++-- tests/test_compression.py | 20 ++++ 3 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 tests/test_compression.py diff --git a/source/application/compression.c b/source/application/compression.c index 461d2148..770f3453 100644 --- a/source/application/compression.c +++ b/source/application/compression.c @@ -25,6 +25,45 @@ #include #include "compression.h" #include "lz4.h" +#include "nrfx_log.h" + +#define LZ4F_MAGICNUMBER 0x184D2204U +#define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U +#define LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH 5 +#define LZ4F_HEADER_SIZE_MIN 7 + +static uint32_t LZ4F_readLE32(const void *src) +{ + const uint8_t *const srcPtr = (const uint8_t *)src; + uint32_t value32 = srcPtr[0]; + value32 |= ((uint32_t)srcPtr[1]) << 8; + value32 |= ((uint32_t)srcPtr[2]) << 16; + value32 |= ((uint32_t)srcPtr[3]) << 24; + return value32; +} + +size_t LZ4F_headerSize(const void *src, size_t srcSize) +{ + /* minimal srcSize to determine header size */ + if (srcSize < LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH) + return -20; + + /* special case : skippable frames */ + if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) + return 8; + + /* control magic number */ + if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER) + return -21; + + /* Frame Header Size */ + { + uint8_t const FLG = ((const uint8_t *)src)[4]; + uint32_t const contentSizeFlag = (FLG >> 3) & 0x01; + uint32_t const dictIDFlag = FLG & 0x01; + return LZ4F_HEADER_SIZE_MIN + (contentSizeFlag ? 8 : 0) + (dictIDFlag ? 4 : 0); + } +} int compression_decompress(size_t destination_size, const void *source, @@ -34,18 +73,24 @@ int compression_decompress(size_t destination_size, { int status = 0; + size_t header_size = LZ4F_headerSize(source, source_size); + + if (header_size < 0) + { + return header_size; + } + char *output_buffer = malloc(destination_size); + if (output_buffer == NULL) { return -1; } - // TODO the frame header might not be 7 - char *block_pointer = (char *)source + 7; + char *block_pointer = (char *)source + header_size; while (1) { - int current_block_size = ((uint8_t)block_pointer[0]) + ((uint8_t)block_pointer[1] << 8) + ((uint8_t)block_pointer[2] << 16) + diff --git a/source/application/lua_libraries/compression.c b/source/application/lua_libraries/compression.c index 97c8b15a..1ed0eb8a 100644 --- a/source/application/lua_libraries/compression.c +++ b/source/application/lua_libraries/compression.c @@ -22,13 +22,82 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include "compression.h" #include "frame_lua_libraries.h" #include "lauxlib.h" #include "lua.h" #include "watchdog.h" +/* + * Test steps: + * + * 1. Create a test file with some text + * + * 2. Compress the file + * + * lz4 -9 -B32 test.txt test.lz4 + * + * 3. Convert to header data + * + * xxd -include test.lz4 test.h + * + * 4. Copy the header data to the test buffer below + */ + +const unsigned char test_data[] = { + 0x04, 0x22, 0x4d, 0x18, 0x64, 0x40, 0xa7, 0x24, 0x02, 0x00, 0x00, 0xf0, + 0x30, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x2e, 0x0a, 0x0a, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, + 0x70, 0x73, 0x75, 0x6d, 0x35, 0x00, 0xc1, 0x73, 0x69, 0x6d, 0x70, 0x6c, + 0x79, 0x20, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x23, 0x00, 0xf1, 0x0d, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, + 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x65, 0x74, 0x10, 0x00, 0xa8, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, + 0x72, 0x79, 0x2e, 0x20, 0x4b, 0x00, 0x81, 0x68, 0x61, 0x73, 0x20, 0x62, + 0x65, 0x65, 0x6e, 0x3c, 0x00, 0x04, 0x23, 0x00, 0xb8, 0x27, 0x73, 0x20, + 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x62, 0x00, 0xa1, 0x65, + 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x2e, 0x00, 0xf2, + 0x07, 0x31, 0x35, 0x30, 0x30, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, + 0x20, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x81, + 0x00, 0xf1, 0x01, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x61, + 0x20, 0x67, 0x61, 0x6c, 0x6c, 0x65, 0x79, 0x9e, 0x00, 0x31, 0x79, 0x70, + 0x65, 0x96, 0x00, 0xf2, 0x07, 0x73, 0x63, 0x72, 0x61, 0x6d, 0x62, 0x6c, + 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, + 0x65, 0x20, 0x61, 0x20, 0x00, 0xf1, 0x02, 0x73, 0x70, 0x65, 0x63, 0x69, + 0x6d, 0x65, 0x6e, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x20, 0x49, 0x74, + 0xa2, 0x00, 0xf1, 0x1b, 0x73, 0x75, 0x72, 0x76, 0x69, 0x76, 0x65, 0x64, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x69, + 0x76, 0x65, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x69, 0x65, 0x73, + 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x9a, 0x00, + 0xf8, 0x05, 0x6c, 0x65, 0x61, 0x70, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x0c, 0x01, + 0x80, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x17, 0x01, 0xf1, + 0x06, 0x65, 0x73, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x79, + 0x20, 0x75, 0x6e, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x79, 0x00, + 0xd0, 0x77, 0x61, 0x73, 0x20, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x72, + 0x69, 0x73, 0xad, 0x00, 0x02, 0x25, 0x01, 0xa1, 0x31, 0x39, 0x36, 0x30, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x0f, 0x00, 0x70, 0x72, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0xe1, 0x00, 0xf4, 0x00, 0x4c, 0x65, 0x74, 0x72, + 0x61, 0x73, 0x65, 0x74, 0x20, 0x73, 0x68, 0x65, 0x65, 0x74, 0x73, 0xc8, + 0x01, 0x00, 0x66, 0x00, 0x08, 0x73, 0x01, 0x60, 0x70, 0x61, 0x73, 0x73, + 0x61, 0x67, 0xb5, 0x00, 0x00, 0x0d, 0x01, 0x30, 0x6d, 0x6f, 0x72, 0x45, + 0x00, 0x00, 0xcb, 0x00, 0x22, 0x6c, 0x79, 0x57, 0x00, 0xf0, 0x00, 0x64, + 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x73, 0x68, 0x40, 0x00, 0xf0, 0x15, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, + 0x72, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x41, 0x6c, 0x64, 0x75, + 0x73, 0x20, 0x50, 0x61, 0x67, 0x65, 0x4d, 0x61, 0x6b, 0x65, 0x72, 0x20, + 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x28, 0x00, 0x81, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x8f, 0x00, 0xb0, 0x6f, 0x72, 0x65, 0x6d, + 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x31, + 0xb8, 0x0d, 0xa8}; + static int registered_function = 0; +static uint8_t decompression_buffer[4096]; +static size_t decompression_buffer_size = 0; static void decompression_lua_handler(lua_State *L, lua_Debug *ar) { @@ -38,9 +107,11 @@ static void decompression_lua_handler(lua_State *L, lua_Debug *ar) { lua_rawgeti(L, LUA_REGISTRYINDEX, registered_function); - // TODO: Add the data to the function call if it's not already added + lua_pushlstring(L, + (char *)decompression_buffer, + decompression_buffer_size); - if (lua_pcall(L, 0, 0, 0) != LUA_OK) + if (lua_pcall(L, 1, 0, 0) != LUA_OK) { luaL_error(L, "%s", lua_tostring(L, -1)); } @@ -51,7 +122,10 @@ static void process_function_callback(void *context, void *data, size_t data_size) { - // TODO copy the data to a buffer + decompression_buffer_size = data_size; + memcpy(decompression_buffer, data, data_size); + + LOG("decompression_buffer_size: %d", decompression_buffer_size); lua_sethook(L_global, decompression_lua_handler, @@ -80,14 +154,22 @@ static int lua_compression_register_process_function(lua_State *L) static int lua_compression_decompress(lua_State *L) { - int status = compression_decompress(4096, // TODO figure out destination size - NULL, // TODO pass the source data to the decompression function - sizeof(0), // TODO set the source data size + lua_Integer block_size = luaL_checkinteger(L, 1); + + if (block_size <= 0) + { + luaL_error(L, "bytes must be greater than 0"); + } + + int status = compression_decompress(block_size, + test_data, // TODO pass the source data to the decompression function + sizeof(test_data), // TODO set the source data size process_function_callback, NULL); - if (status != 0) + if (status) { + LOG("%d", status); luaL_error(L, "decompression failed"); } diff --git a/tests/test_compression.py b/tests/test_compression.py new file mode 100644 index 00000000..eac499c3 --- /dev/null +++ b/tests/test_compression.py @@ -0,0 +1,20 @@ +import asyncio +from frameutils import Bluetooth + + +async def main(): + b = Bluetooth() + + await b.connect(print_response_handler=lambda s: print(s)) + + await b.send_lua("function process_function(data) print(data) end") + await b.send_lua("frame.compression.process_function(process_function)") + await b.send_lua("frame.compression.decompress(1024)") + await b.send_lua("process_function(1)") + + await asyncio.sleep(1) + + await b.disconnect() + + +asyncio.run(main()) From 158f97dfa5a77c56cbacfc6e19b6ae703daf99fb Mon Sep 17 00:00:00 2001 From: Raj Nakarja Date: Fri, 31 Jan 2025 10:17:46 +0100 Subject: [PATCH 3/4] Decompression function working Added example test file --- .../application/lua_libraries/compression.c | 78 ++----------------- tests/test_compression.py | 38 ++++++++- 2 files changed, 40 insertions(+), 76 deletions(-) diff --git a/source/application/lua_libraries/compression.c b/source/application/lua_libraries/compression.c index 1ed0eb8a..102bea54 100644 --- a/source/application/lua_libraries/compression.c +++ b/source/application/lua_libraries/compression.c @@ -29,72 +29,6 @@ #include "lua.h" #include "watchdog.h" -/* - * Test steps: - * - * 1. Create a test file with some text - * - * 2. Compress the file - * - * lz4 -9 -B32 test.txt test.lz4 - * - * 3. Convert to header data - * - * xxd -include test.lz4 test.h - * - * 4. Copy the header data to the test buffer below - */ - -const unsigned char test_data[] = { - 0x04, 0x22, 0x4d, 0x18, 0x64, 0x40, 0xa7, 0x24, 0x02, 0x00, 0x00, 0xf0, - 0x30, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, - 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x65, - 0x78, 0x74, 0x2e, 0x0a, 0x0a, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x49, - 0x70, 0x73, 0x75, 0x6d, 0x35, 0x00, 0xc1, 0x73, 0x69, 0x6d, 0x70, 0x6c, - 0x79, 0x20, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x23, 0x00, 0xf1, 0x0d, 0x20, - 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, - 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x65, 0x74, 0x10, 0x00, 0xa8, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, - 0x72, 0x79, 0x2e, 0x20, 0x4b, 0x00, 0x81, 0x68, 0x61, 0x73, 0x20, 0x62, - 0x65, 0x65, 0x6e, 0x3c, 0x00, 0x04, 0x23, 0x00, 0xb8, 0x27, 0x73, 0x20, - 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x62, 0x00, 0xa1, 0x65, - 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x2e, 0x00, 0xf2, - 0x07, 0x31, 0x35, 0x30, 0x30, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, - 0x20, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x81, - 0x00, 0xf1, 0x01, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x61, - 0x20, 0x67, 0x61, 0x6c, 0x6c, 0x65, 0x79, 0x9e, 0x00, 0x31, 0x79, 0x70, - 0x65, 0x96, 0x00, 0xf2, 0x07, 0x73, 0x63, 0x72, 0x61, 0x6d, 0x62, 0x6c, - 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, - 0x65, 0x20, 0x61, 0x20, 0x00, 0xf1, 0x02, 0x73, 0x70, 0x65, 0x63, 0x69, - 0x6d, 0x65, 0x6e, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x20, 0x49, 0x74, - 0xa2, 0x00, 0xf1, 0x1b, 0x73, 0x75, 0x72, 0x76, 0x69, 0x76, 0x65, 0x64, - 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x69, - 0x76, 0x65, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x69, 0x65, 0x73, - 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x9a, 0x00, - 0xf8, 0x05, 0x6c, 0x65, 0x61, 0x70, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x0c, 0x01, - 0x80, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x17, 0x01, 0xf1, - 0x06, 0x65, 0x73, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x79, - 0x20, 0x75, 0x6e, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x79, 0x00, - 0xd0, 0x77, 0x61, 0x73, 0x20, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x72, - 0x69, 0x73, 0xad, 0x00, 0x02, 0x25, 0x01, 0xa1, 0x31, 0x39, 0x36, 0x30, - 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x0f, 0x00, 0x70, 0x72, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0xe1, 0x00, 0xf4, 0x00, 0x4c, 0x65, 0x74, 0x72, - 0x61, 0x73, 0x65, 0x74, 0x20, 0x73, 0x68, 0x65, 0x65, 0x74, 0x73, 0xc8, - 0x01, 0x00, 0x66, 0x00, 0x08, 0x73, 0x01, 0x60, 0x70, 0x61, 0x73, 0x73, - 0x61, 0x67, 0xb5, 0x00, 0x00, 0x0d, 0x01, 0x30, 0x6d, 0x6f, 0x72, 0x45, - 0x00, 0x00, 0xcb, 0x00, 0x22, 0x6c, 0x79, 0x57, 0x00, 0xf0, 0x00, 0x64, - 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x73, 0x68, 0x40, 0x00, 0xf0, 0x15, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, - 0x72, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x41, 0x6c, 0x64, 0x75, - 0x73, 0x20, 0x50, 0x61, 0x67, 0x65, 0x4d, 0x61, 0x6b, 0x65, 0x72, 0x20, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x28, 0x00, 0x81, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x8f, 0x00, 0xb0, 0x6f, 0x72, 0x65, 0x6d, - 0x20, 0x49, 0x70, 0x73, 0x75, 0x6d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x31, - 0xb8, 0x0d, 0xa8}; - static int registered_function = 0; static uint8_t decompression_buffer[4096]; static size_t decompression_buffer_size = 0; @@ -125,8 +59,6 @@ static void process_function_callback(void *context, decompression_buffer_size = data_size; memcpy(decompression_buffer, data, data_size); - LOG("decompression_buffer_size: %d", decompression_buffer_size); - lua_sethook(L_global, decompression_lua_handler, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, @@ -154,7 +86,10 @@ static int lua_compression_register_process_function(lua_State *L) static int lua_compression_decompress(lua_State *L) { - lua_Integer block_size = luaL_checkinteger(L, 1); + size_t length; + const char *data = luaL_checklstring(L, 1, &length); + + lua_Integer block_size = luaL_checkinteger(L, 2); if (block_size <= 0) { @@ -162,14 +97,13 @@ static int lua_compression_decompress(lua_State *L) } int status = compression_decompress(block_size, - test_data, // TODO pass the source data to the decompression function - sizeof(test_data), // TODO set the source data size + data, + length, process_function_callback, NULL); if (status) { - LOG("%d", status); luaL_error(L, "decompression failed"); } diff --git a/tests/test_compression.py b/tests/test_compression.py index eac499c3..3666483a 100644 --- a/tests/test_compression.py +++ b/tests/test_compression.py @@ -3,17 +3,47 @@ async def main(): + + lua_script = """ + -- Decompression function + function decomp_func(data) + print(data) + end + + -- Register the decompression function + frame.compression.process_function(decomp_func) + + -- Variable where the compressed data will be stored + compressed_data = '' + + -- Function to handle the compressed data received from Bluetooth + function ble_func(data) + frame.compression.decompress(data, 1024) + end + + -- Register the Bluetooth receive callback + frame.bluetooth.receive_callback(ble_func) + + """ + + compressed_data = bytearray( + b"\x04\x22\x4d\x18\x64\x40\xa7\x6f\x00\x00\x00\xf5\x3d\x48\x65\x6c\x6c\x6f\x21\x20\x49\x20\x77\x61\x73\x20\x73\x6f\x6d\x65\x20\x63\x6f\x6d\x70\x72\x65\x73\x73\x65\x64\x20\x64\x61\x74\x61\x2e\x20\x49\x6e\x20\x74\x68\x69\x73\x20\x63\x61\x73\x65\x2c\x20\x73\x74\x72\x69\x6e\x67\x73\x20\x61\x72\x65\x6e\x27\x74\x20\x70\x61\x72\x74\x69\x63\x75\x6c\x61\x72\x6c\x79\x3b\x00\xf1\x01\x69\x62\x6c\x65\x2c\x20\x62\x75\x74\x20\x73\x70\x72\x69\x74\x65\x49\x00\xa0\x20\x77\x6f\x75\x6c\x64\x20\x62\x65\x2e\x00\x00\x00\x00\x5f\xd0\xa3\x47" + ) + b = Bluetooth() await b.connect(print_response_handler=lambda s: print(s)) - await b.send_lua("function process_function(data) print(data) end") - await b.send_lua("frame.compression.process_function(process_function)") - await b.send_lua("frame.compression.decompress(1024)") - await b.send_lua("process_function(1)") + # Upload the Lua script + await b.upload_file(lua_script, "main.lua") + await b.send_reset_signal() await asyncio.sleep(1) + # Send compressed data + await b.send_data(compressed_data) + + await b.send_break_signal() await b.disconnect() From 88639fa66e45d60329a58456ec860c92e825c094 Mon Sep 17 00:00:00 2001 From: Raj Nakarja Date: Fri, 31 Jan 2025 10:21:28 +0100 Subject: [PATCH 4/4] Cleaned up comments --- tests/test_compression.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tests/test_compression.py b/tests/test_compression.py index 3666483a..47026ede 100644 --- a/tests/test_compression.py +++ b/tests/test_compression.py @@ -4,6 +4,11 @@ async def main(): + b = Bluetooth() + + await b.connect(print_response_handler=lambda s: print(s)) + + # Upload the Lua script lua_script = """ -- Decompression function function decomp_func(data) @@ -13,9 +18,6 @@ async def main(): -- Register the decompression function frame.compression.process_function(decomp_func) - -- Variable where the compressed data will be stored - compressed_data = '' - -- Function to handle the compressed data received from Bluetooth function ble_func(data) frame.compression.decompress(data, 1024) @@ -26,21 +28,18 @@ async def main(): """ - compressed_data = bytearray( - b"\x04\x22\x4d\x18\x64\x40\xa7\x6f\x00\x00\x00\xf5\x3d\x48\x65\x6c\x6c\x6f\x21\x20\x49\x20\x77\x61\x73\x20\x73\x6f\x6d\x65\x20\x63\x6f\x6d\x70\x72\x65\x73\x73\x65\x64\x20\x64\x61\x74\x61\x2e\x20\x49\x6e\x20\x74\x68\x69\x73\x20\x63\x61\x73\x65\x2c\x20\x73\x74\x72\x69\x6e\x67\x73\x20\x61\x72\x65\x6e\x27\x74\x20\x70\x61\x72\x74\x69\x63\x75\x6c\x61\x72\x6c\x79\x3b\x00\xf1\x01\x69\x62\x6c\x65\x2c\x20\x62\x75\x74\x20\x73\x70\x72\x69\x74\x65\x49\x00\xa0\x20\x77\x6f\x75\x6c\x64\x20\x62\x65\x2e\x00\x00\x00\x00\x5f\xd0\xa3\x47" - ) - - b = Bluetooth() - - await b.connect(print_response_handler=lambda s: print(s)) - - # Upload the Lua script await b.upload_file(lua_script, "main.lua") await b.send_reset_signal() await asyncio.sleep(1) - # Send compressed data + # Send the compressed data. Here the total size of the data is is pretty small, + # but usually you would want to split the data into MTU sized chunks and stitch + # them together on the device side before decompressing. + compressed_data = bytearray( + b"\x04\x22\x4d\x18\x64\x40\xa7\x6f\x00\x00\x00\xf5\x3d\x48\x65\x6c\x6c\x6f\x21\x20\x49\x20\x77\x61\x73\x20\x73\x6f\x6d\x65\x20\x63\x6f\x6d\x70\x72\x65\x73\x73\x65\x64\x20\x64\x61\x74\x61\x2e\x20\x49\x6e\x20\x74\x68\x69\x73\x20\x63\x61\x73\x65\x2c\x20\x73\x74\x72\x69\x6e\x67\x73\x20\x61\x72\x65\x6e\x27\x74\x20\x70\x61\x72\x74\x69\x63\x75\x6c\x61\x72\x6c\x79\x3b\x00\xf1\x01\x69\x62\x6c\x65\x2c\x20\x62\x75\x74\x20\x73\x70\x72\x69\x74\x65\x49\x00\xa0\x20\x77\x6f\x75\x6c\x64\x20\x62\x65\x2e\x00\x00\x00\x00\x5f\xd0\xa3\x47" + ) + await b.send_data(compressed_data) await b.send_break_signal()