From d6b7cdd2f2bfed709015afcccb6b8b1d454f71ab Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Fri, 31 Jan 2025 16:47:30 -0600 Subject: [PATCH] Feat/binary log (#364) * feat(log): WIP adding support for binary logging * WIP testing example more * flesh out example more * add simple tool for writing the appropriate files from copy-pasted data * update gitignore for this folder to ignore log files * update example to show use of run-length encoding and update python script with a little bit more info * flesh out some more * Update component to build unpacker automatically when the component is built. update readme accordingly * update ci * update docs * remove p-ranav/binary_log * update the repo to use finger563 fork * update commit ref * Update cmake lists to remove commented line and add comments about function --- .github/workflows/build.yml | 2 + .github/workflows/static_analysis.yml | 2 +- .gitmodules | 3 + components/binary-log/CMakeLists.txt | 19 ++ components/binary-log/detail | 1 + components/binary-log/example/.gitignore | 1 + components/binary-log/example/CMakeLists.txt | 21 ++ components/binary-log/example/README.md | 75 +++++++ .../binary-log/example/main/CMakeLists.txt | 2 + .../example/main/binary_log_example.cpp | 188 ++++++++++++++++++ components/binary-log/example/partitions.csv | 6 + .../binary-log/example/sdkconfig.defaults | 33 +++ components/binary-log/example/write_files.py | 32 +++ components/binary-log/include/binary-log.hpp | 3 + components/binary-log/src/binary-log.cpp | 1 + doc/Doxyfile | 2 + doc/en/binary_log_example.md | 2 + doc/en/logger.rst | 12 ++ 18 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 components/binary-log/CMakeLists.txt create mode 160000 components/binary-log/detail create mode 100644 components/binary-log/example/.gitignore create mode 100644 components/binary-log/example/CMakeLists.txt create mode 100644 components/binary-log/example/README.md create mode 100644 components/binary-log/example/main/CMakeLists.txt create mode 100644 components/binary-log/example/main/binary_log_example.cpp create mode 100644 components/binary-log/example/partitions.csv create mode 100644 components/binary-log/example/sdkconfig.defaults create mode 100644 components/binary-log/example/write_files.py create mode 100644 components/binary-log/include/binary-log.hpp create mode 100644 components/binary-log/src/binary-log.cpp create mode 100644 doc/en/binary_log_example.md diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 78fef1b34..a56cfcfaf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,8 @@ jobs: target: esp32s3 - path: 'components/aw9523/example' target: esp32 + - path: 'components/binary-log/example' + target: esp32s3 - path: 'components/bldc_haptics/example' target: esp32s3 - path: 'components/bldc_motor/example' diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index f77240a31..3842c6006 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -27,4 +27,4 @@ jobs: esp_idf_version: release/v5.2 # (Optional) cppcheck args - cppcheck_args: -i$GITHUB_WORKSPACE/lib -i$GITHUB_WORKSPACE/external -i$GITHUB_WORKSPACE/components/esp_littlefs -i$GITHUB_WORKSPACE/components/esp-nimble-cpp -i$GITHUB_WORKSPACE/components/hid-rp/include/hid -i$GITHUB_WORKSPACE/components/lvgl -i$GITHUB_WORKSPACE/components/esp-dsp --force --enable=all --inline-suppr --inconclusive --platform=mips32 --suppressions-list=$GITHUB_WORKSPACE/suppressions.txt + cppcheck_args: -i$GITHUB_WORKSPACE/lib -i$GITHUB_WORKSPACE/external -i$GITHUB_WORKSPACE/components/binary-log/detail -i$GITHUB_WORKSPACE/components/esp_littlefs -i$GITHUB_WORKSPACE/components/esp-nimble-cpp -i$GITHUB_WORKSPACE/components/hid-rp/include/hid -i$GITHUB_WORKSPACE/components/lvgl -i$GITHUB_WORKSPACE/components/esp-dsp --force --enable=all --inline-suppr --inconclusive --platform=mips32 --suppressions-list=$GITHUB_WORKSPACE/suppressions.txt diff --git a/.gitmodules b/.gitmodules index 33184d8cd..3f6682037 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,6 @@ [submodule "external/nearby"] path = external/nearby url = https://github.com/google/nearby +[submodule "components/binary-log/detail"] + path = components/binary-log/detail + url = https://github.com/finger563/binary_log diff --git a/components/binary-log/CMakeLists.txt b/components/binary-log/CMakeLists.txt new file mode 100644 index 000000000..5ce428ab4 --- /dev/null +++ b/components/binary-log/CMakeLists.txt @@ -0,0 +1,19 @@ +idf_component_register( + INCLUDE_DIRS "include" "detail/include" + SRC_DIRS "src" + REQUIRES "") + +# Build the unpacker tool and put it whereever the rest of the build binaries +# are going for this build. This will ensure that the user can always run +# `./build/unpacker ` +add_custom_command( + TARGET ${COMPONENT_TARGET} + POST_BUILD + DEPENDS ${COMPONENT_TARGET} + WORKING_DIRECTORY ${COMPONENT_DIR}/detail + COMMAND echo "Building binary-log unpacker" + COMMAND mkdir -p build + COMMAND cmake -B build -S . + COMMAND cmake --build build + COMMAND cp build/tools/unpacker/unpacker ${CMAKE_BINARY_DIR}/unpacker +) diff --git a/components/binary-log/detail b/components/binary-log/detail new file mode 160000 index 000000000..7d8ba9094 --- /dev/null +++ b/components/binary-log/detail @@ -0,0 +1 @@ +Subproject commit 7d8ba90941d6d7be208d8f7a758579cc6b468e01 diff --git a/components/binary-log/example/.gitignore b/components/binary-log/example/.gitignore new file mode 100644 index 000000000..80a243fa8 --- /dev/null +++ b/components/binary-log/example/.gitignore @@ -0,0 +1 @@ +log.* diff --git a/components/binary-log/example/CMakeLists.txt b/components/binary-log/example/CMakeLists.txt new file mode 100644 index 000000000..9c28dd626 --- /dev/null +++ b/components/binary-log/example/CMakeLists.txt @@ -0,0 +1,21 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +# add the component directories that we want to use +set(EXTRA_COMPONENT_DIRS + "../../../components/" +) + +set( + COMPONENTS + "main esptool_py espcoredump binary-log file_system format" + CACHE STRING + "List of components to include" + ) + +project(binary_log_example) + +set(CMAKE_CXX_STANDARD 20) diff --git a/components/binary-log/example/README.md b/components/binary-log/example/README.md new file mode 100644 index 000000000..dbe39c2f9 --- /dev/null +++ b/components/binary-log/example/README.md @@ -0,0 +1,75 @@ +# Binary Log Example + +This example shows how to use the `binary-log` component to format and store +logs in a binary packed form, either to disk or into a ringbuffer in memory. + +This component simply exposes the +[p-ranav/binary_log](https://github.com/p-ranav/binary_log) binary logger, with +some modifications in a fork +[finger563/binary_log](https://github.com/finger563/binary_log) to allow packer +customization as is required on embedded systems such as with ESP-IDF. + +The `binary-log` does not support all datatypes, but only some base datatypes +such as integer types, float types, and string types. + +The logger produces the following data: +1. Log data - these are indexes and the arguments which point to either the + index data or the runfile data. +2. Index data - these are static data (format strings, constant arguments, etc.) +3. Runfile data - these are indices of the log file which run multiple times in + a row. + +For more information about the logging, its format, and the types supported, +please see [p-ranav/binary_log](https://github.com/p-ranav/binary_log). + +## How to use example + +This example is designed to be run on an ESP dev board which has embedded +flash - the partitions and build are configured to match the QtPy ESP32-S3, +though if you modify the `sdkconfig.defaults` and the `partitions.csv` you could +run it on other dev boards easily. + +The example does the following: +1. Use standard `binary_log::packer` to log in a loop for three seconds to files + on the filesystem. +2. Print the contents of the log files. +3. Erase the file system. +4. Use the `binary_log::ringbuffer_packer` to log in a loop for three seconds to + into an in-memory ringbuffer. +5. Print the contents of the log buffers. + +### Unpacking the logs + +#### Getting the log data + +You can copy the text from the example output into +[write_files.py](./write_files.py), then run that script, and it will produce +the relevant `log.out`, `log.out.index`, and `log.out.runfile` on your computer. + +#### Unpacking the log data + +Once you've done that, you can unpack the log data using the `unpacker` that is +automatically built when you build the app and is located within your `build` +folder as `build/unpacker`: + +``` console +./build/unpacker log.out > log.inflated +``` + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(Replace PORT with the name of the serial port to use.) + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +![CleanShot 2025-01-31 at 14 31 23](https://github.com/user-attachments/assets/72e3c118-d5c0-4e48-b5ab-732e6b32e433) diff --git a/components/binary-log/example/main/CMakeLists.txt b/components/binary-log/example/main/CMakeLists.txt new file mode 100644 index 000000000..a941e22ba --- /dev/null +++ b/components/binary-log/example/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRC_DIRS "." + INCLUDE_DIRS ".") diff --git a/components/binary-log/example/main/binary_log_example.cpp b/components/binary-log/example/main/binary_log_example.cpp new file mode 100644 index 000000000..76e2c48b9 --- /dev/null +++ b/components/binary-log/example/main/binary_log_example.cpp @@ -0,0 +1,188 @@ +#include +#include +#include + +#include + +#include "binary-log.hpp" +#include "file_system.hpp" +#include "logger.hpp" + +using namespace std::chrono_literals; + +extern "C" void app_main(void) { + espp::Logger logger({.tag = "blog_example", .level = espp::Logger::Verbosity::INFO}); + + logger.info("Starting binary log example"); + // initialize the file system + std::error_code ec; + auto &fs = espp::FileSystem::get(); + auto root = fs.get_root_path(); + const std::filesystem::path logfile = root / std::filesystem::path{"log.out"}; + + auto print_files = [&fs, &logger, &root, &logfile]() { + logger.info("Printing log file"); + std::error_code ec; + + size_t file_size = std::filesystem::file_size(logfile, ec); + std::ifstream ifs(logfile, std::ios::in | std::ios::binary); + // read bytes + std::vector file_bytes(file_size); + ifs.read(file_bytes.data(), file_size); + ifs.close(); + logger.info("Read {} bytes from log file", file_size); + logger.info("File contents:\n{::#02x}", file_bytes); + + // now print the contents of the other two associated files + logger.info("Printing index file"); + std::filesystem::path indexfile = logfile; + indexfile.replace_extension(logfile.extension().string() + ".index"); + file_size = std::filesystem::file_size(indexfile, ec); + ifs.open(indexfile, std::ios::in | std::ios::binary); + // read bytes + file_bytes.resize(file_size); + ifs.read(file_bytes.data(), file_size); + ifs.close(); + logger.info("Read {} bytes from index file", file_size); + logger.info("File contents:\n{::#02x}", file_bytes); + + // print the contents of the runlength file + logger.info("Printing runlength file"); + std::filesystem::path runlengthfile = logfile; + runlengthfile.replace_extension(logfile.extension().string() + ".runlength"); + file_size = std::filesystem::file_size(runlengthfile, ec); + ifs.open(runlengthfile, std::ios::in | std::ios::binary); + // read bytes + file_bytes.resize(file_size); + ifs.read(file_bytes.data(), file_size); + ifs.close(); + logger.info("Read {} bytes from runlength file", file_size); + logger.info("File contents:\n{::#02x}", file_bytes); + + // print the contents of the file system + logger.info("Directory contents:\n{}", fs.list_directory(root, {})); + }; + + // first see if the file exists + if (std::filesystem::exists(logfile, ec)) { + logger.info("Removing existing log file"); + fs.remove(logfile, ec); + } + + { + //! [Binary Log example] + float num_seconds_to_run = 3.0f; + // create standard logger. This will buffer the logs in memory until the buffer is + // full or the logger is destroyed + logger.info("Creating binary log file: {}", logfile.c_str()); + static constexpr size_t log_buffer_size = 1024; + static constexpr size_t index_buffer_size = 1024; + static constexpr size_t runlength_buffer_size = 1024; + using Packer = binary_log::packer; + binary_log::binary_log log(logfile); + + logger.info("Starting binary logging for {}s", num_seconds_to_run); + auto start = std::chrono::high_resolution_clock::now(); + auto now = std::chrono::high_resolution_clock::now(); + float elapsed = std::chrono::duration(now - start).count(); + while (elapsed < num_seconds_to_run) { + now = std::chrono::high_resolution_clock::now(); + elapsed = std::chrono::duration(now - start).count(); + auto remaining = num_seconds_to_run - elapsed; + + // NOTE: use of a single log within the majority of this loop allows for + // run-length encoding of the log messages to be used to reduce the size + BINARY_LOG(log, "elapsed: {}s\nremaining: {}s", elapsed, remaining); + + // print a log each second. to track it, just get the remainder + // milliseconds and see if they're less than 15 + if (std::chrono::duration_cast(now - start).count() % 1000 < 15) { + BINARY_LOG(log, "This is a log message at {}s", elapsed) + } + + if (remaining < 0) { + BINARY_LOG(log, "You overstayed your welcome by {}s!", -remaining); + } + std::this_thread::sleep_for(10ms); + } + //! [Logger example] + } + + // now print out the logger files + print_files(); + + // now erase the file system + logger.info("Erase file system"); + fs.remove_contents(root, ec); + + { + //! [Binary Log example] + float num_seconds_to_run = 3.0f; + // create ringbuffer logger. This will not write to disk, but instead will + // only store log data in memory. The log buffer will be a ring buffer, + // discarding the oldest data, while the index and runlength buffers will be + // simple arrays which will abort if they run out of space. + logger.info("Creating ringbuffer binary log"); + static constexpr size_t log_buffer_size = 1024; + static constexpr size_t index_buffer_size = 1024; + static constexpr size_t runlength_buffer_size = 1024; + using Packer = + binary_log::ringbuffer_packer; + binary_log::binary_log log(logfile); + + logger.info("Starting binary logging for {}s", num_seconds_to_run); + auto start = std::chrono::high_resolution_clock::now(); + auto now = std::chrono::high_resolution_clock::now(); + float elapsed = std::chrono::duration(now - start).count(); + while (elapsed < num_seconds_to_run) { + now = std::chrono::high_resolution_clock::now(); + elapsed = std::chrono::duration(now - start).count(); + auto remaining = num_seconds_to_run - elapsed; + + BINARY_LOG(log, "elapsed: {}s", elapsed); + BINARY_LOG(log, "remaining: {}s", remaining); + + // print a log each second. to track it, just get the remainder + // milliseconds and see if they're less than 15 + if (std::chrono::duration_cast(now - start).count() % 1000 < 15) { + BINARY_LOG(log, "This is a log message at {}s", elapsed) + } + + if (remaining < 0) { + BINARY_LOG(log, "You overstayed your welcome by {}s!", -remaining); + } + std::this_thread::sleep_for(10ms); + } + // Since this is a memory-based logger, we must flush and read out the data + // manually + log.flush(); + + const Packer &packer = log.get_packer(); + auto log_buffer = packer.get_log_buffer(); + auto index_buffer_sv = packer.get_index_buffer(); + // convert the string view into a vector for easy printing with libfmt + std::vector index_buffer(index_buffer_sv.begin(), index_buffer_sv.end()); + auto runlength_buffer_sv = packer.get_runlength_buffer(); + // convert the string view into a vector for easy printing with libfmt + std::vector runlength_buffer(runlength_buffer_sv.begin(), runlength_buffer_sv.end()); + + logger.info("Log file size: {} bytes", log_buffer.size()); + logger.info("Index file size: {} bytes", index_buffer.size()); + logger.info("Runlength file size: {} bytes", runlength_buffer.size()); + logger.info("--------------------------------"); + logger.info("Total file size: {} bytes", + log_buffer.size() + index_buffer.size() + runlength_buffer.size()); + + logger.info("Log data:\n{::#02x}", log_buffer); + logger.info("Index data:\n{::#02x}", index_buffer); + logger.info("Runlength data:\n{::#02x}", runlength_buffer); + //! [Logger example] + } + + logger.info("Finished binary log example"); + + // now loop forever + while (true) { + std::this_thread::sleep_for(1s); + } +} diff --git a/components/binary-log/example/partitions.csv b/components/binary-log/example/partitions.csv new file mode 100644 index 000000000..d16c151be --- /dev/null +++ b/components/binary-log/example/partitions.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size +nvs, data, nvs, 0x9000, 0x6000 +phy_init, data, phy, 0xf000, 0x1000 +factory, app, factory, 0x10000, 2M +coredump, data, coredump, , 256K +littlefs, data, spiffs, , 1M diff --git a/components/binary-log/example/sdkconfig.defaults b/components/binary-log/example/sdkconfig.defaults new file mode 100644 index 000000000..e7bbbfa67 --- /dev/null +++ b/components/binary-log/example/sdkconfig.defaults @@ -0,0 +1,33 @@ +CONFIG_IDF_TARGET="esp32s3" + +# Common ESP-related +# +# binary_log requires exceptions right now... +# CONFIG_COMPILER_CXX_EXCEPTIONS=y + +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" + +CONFIG_FREERTOS_HZ=1000 + +# Clock Frequency +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 + +# Common ESP-related +# +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=10240 +CONFIG_ESP_TIMER_TASK_STACK_SIZE=4096 + +# Partition Table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" + +# Even if the environment variable MEMFAULT_DISABLE=1 is set, cli.py can retrieve SystemInfo. +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y + +# Coredump +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y +CONFIG_ESP_COREDUMP_STACK_SIZE=2048 diff --git a/components/binary-log/example/write_files.py b/components/binary-log/example/write_files.py new file mode 100644 index 000000000..992513726 --- /dev/null +++ b/components/binary-log/example/write_files.py @@ -0,0 +1,32 @@ +# python program to write some static arrays of bytes as binary data to files +# arrays contain the information for the following files: +# - log.out +# - log.out.index +# - log.out.runlength + +import os + +# NOTE: you should copy and paste from the idf monitor output into these arrays. +# I've included some example data below from various configurations / runs. + +log_content = [ + 0x0, 0x0, 0x3, 0x42, 0xb, 0x40, 0x1, 0x0, 0xf4, 0xf7, 0x52, 0x3f, 0x0, 0x0, 0x47, 0xe6, 0xb, 0x40, 0x1, 0x0, 0xe4, 0x66, 0x50, 0x3f, 0x0, 0x0, 0x8b, 0x8a, 0xc, 0x40, 0x1, 0x0, 0xd4, 0xd5, 0x4d, 0x3f, 0x0, 0x0, 0xcf, 0x2e, 0xd, 0x40, 0x1, 0x0, 0xc4, 0x44, 0x4b, 0x3f, 0x0, 0x0, 0x13, 0xd3, 0xd, 0x40, 0x1, 0x0, 0xb4, 0xb3, 0x48, 0x3f, 0x0, 0x0, 0x57, 0x77, 0xe, 0x40, 0x1, 0x0, 0xa4, 0x22, 0x46, 0x3f, 0x0, 0x0, 0x9b, 0x1b, 0xf, 0x40, 0x1, 0x0, 0x94, 0x91, 0x43, 0x3f, 0x0, 0x0, 0xdf, 0xbf, 0xf, 0x40, 0x1, 0x0, 0x84, 0x0, 0x41, 0x3f, 0x0, 0x0, 0x24, 0x64, 0x10, 0x40, 0x1, 0x0, 0x70, 0x6f, 0x3e, 0x3f, 0x0, 0x0, 0x68, 0x8, 0x11, 0x40, 0x1, 0x0, 0x60, 0xde, 0x3b, 0x3f, 0x0, 0x0, 0xac, 0xac, 0x11, 0x40, 0x1, 0x0, 0x50, 0x4d, 0x39, 0x3f, 0x0, 0x0, 0xf0, 0x50, 0x12, 0x40, 0x1, 0x0, 0x40, 0xbc, 0x36, 0x3f, 0x0, 0x0, 0x34, 0xf5, 0x12, 0x40, 0x1, 0x0, 0x30, 0x2b, 0x34, 0x3f, 0x0, 0x0, 0x78, 0x99, 0x13, 0x40, 0x1, 0x0, 0x20, 0x9a, 0x31, 0x3f, 0x0, 0x0, 0xbc, 0x3d, 0x14, 0x40, 0x1, 0x0, 0x10, 0x9, 0x2f, 0x3f, 0x0, 0x0, 0x0, 0xe2, 0x14, 0x40, 0x1, 0x0, 0x0, 0x78, 0x2c, 0x3f, 0x0, 0x0, 0x44, 0x86, 0x15, 0x40, 0x1, 0x0, 0xf0, 0xe6, 0x29, 0x3f, 0x0, 0x0, 0x88, 0x2a, 0x16, 0x40, 0x1, 0x0, 0xe0, 0x55, 0x27, 0x3f, 0x0, 0x0, 0xcc, 0xce, 0x16, 0x40, 0x1, 0x0, 0xd0, 0xc4, 0x24, 0x3f, 0x0, 0x0, 0x10, 0x73, 0x17, 0x40, 0x1, 0x0, 0xc0, 0x33, 0x22, 0x3f, 0x0, 0x0, 0x54, 0x17, 0x18, 0x40, 0x1, 0x0, 0xb0, 0xa2, 0x1f, 0x3f, 0x0, 0x0, 0x98, 0xbb, 0x18, 0x40, 0x1, 0x0, 0xa0, 0x11, 0x1d, 0x3f, 0x0, 0x0, 0xdc, 0x5f, 0x19, 0x40, 0x1, 0x0, 0x90, 0x80, 0x1a, 0x3f, 0x0, 0x0, 0x20, 0x4, 0x1a, 0x40, 0x1, 0x0, 0x80, 0xef, 0x17, 0x3f, 0x0, 0x0, 0x65, 0xa8, 0x1a, 0x40, 0x1, 0x0, 0x6c, 0x5e, 0x15, 0x3f, 0x0, 0x0, 0xaa, 0x4c, 0x1b, 0x40, 0x1, 0x0, 0x58, 0xcd, 0x12, 0x3f, 0x0, 0x0, 0xee, 0xf0, 0x1b, 0x40, 0x1, 0x0, 0x48, 0x3c, 0x10, 0x3f, 0x0, 0x0, 0x32, 0x95, 0x1c, 0x40, 0x1, 0x0, 0x38, 0xab, 0xd, 0x3f, 0x0, 0x0, 0x76, 0x39, 0x1d, 0x40, 0x1, 0x0, 0x28, 0x1a, 0xb, 0x3f, 0x0, 0x0, 0xce, 0xdd, 0x1d, 0x40, 0x1, 0x0, 0xc8, 0x88, 0x8, 0x3f, 0x0, 0x0, 0x12, 0x82, 0x1e, 0x40, 0x1, 0x0, 0xb8, 0xf7, 0x5, 0x3f, 0x0, 0x0, 0x56, 0x26, 0x1f, 0x40, 0x1, 0x0, 0xa8, 0x66, 0x3, 0x3f, 0x0, 0x0, 0x9b, 0xca, 0x1f, 0x40, 0x1, 0x0, 0x94, 0xd5, 0x0, 0x3f, 0x0, 0x0, 0xdf, 0x6e, 0x20, 0x40, 0x1, 0x0, 0x8, 0x89, 0xfc, 0x3e, 0x0, 0x0, 0x23, 0x13, 0x21, 0x40, 0x1, 0x0, 0xe8, 0x66, 0xf7, 0x3e, 0x0, 0x0, 0x67, 0xb7, 0x21, 0x40, 0x1, 0x0, 0xc8, 0x44, 0xf2, 0x3e, 0x0, 0x0, 0xab, 0x5b, 0x22, 0x40, 0x1, 0x0, 0xa8, 0x22, 0xed, 0x3e, 0x0, 0x0, 0x22, 0x0, 0x23, 0x40, 0x1, 0x0, 0xf0, 0xfe, 0xe7, 0x3e, 0x0, 0x0, 0x66, 0xa4, 0x23, 0x40, 0x1, 0x0, 0xd0, 0xdc, 0xe2, 0x3e, 0x0, 0x0, 0xaa, 0x48, 0x24, 0x40, 0x1, 0x0, 0xb0, 0xba, 0xdd, 0x3e, 0x0, 0x0, 0xee, 0xec, 0x24, 0x40, 0x1, 0x0, 0x90, 0x98, 0xd8, 0x3e, 0x0, 0x0, 0x32, 0x91, 0x25, 0x40, 0x1, 0x0, 0x70, 0x76, 0xd3, 0x3e, 0x0, 0x0, 0x76, 0x35, 0x26, 0x40, 0x1, 0x0, 0x50, 0x54, 0xce, 0x3e, 0x0, 0x0, 0xba, 0xd9, 0x26, 0x40, 0x1, 0x0, 0x30, 0x32, 0xc9, 0x3e, 0x0, 0x0, 0xfe, 0x7d, 0x27, 0x40, 0x1, 0x0, 0x10, 0x10, 0xc4, 0x3e, 0x0, 0x0, 0x42, 0x22, 0x28, 0x40, 0x1, 0x0, 0xf0, 0xed, 0xbe, 0x3e, 0x0, 0x0, 0x86, 0xc6, 0x28, 0x40, 0x1, 0x0, 0xd0, 0xcb, 0xb9, 0x3e, 0x0, 0x0, 0xca, 0x6a, 0x29, 0x40, 0x1, 0x0, 0xb0, 0xa9, 0xb4, 0x3e, 0x0, 0x0, 0x12, 0xf, 0x2a, 0x40, 0x1, 0x0, 0x70, 0x87, 0xaf, 0x3e, 0x0, 0x0, 0x56, 0xb3, 0x2a, 0x40, 0x1, 0x0, 0x50, 0x65, 0xaa, 0x3e, 0x0, 0x0, 0x9a, 0x57, 0x2b, 0x40, 0x1, 0x0, 0x30, 0x43, 0xa5, 0x3e, 0x0, 0x0, 0xde, 0xfb, 0x2b, 0x40, 0x1, 0x0, 0x10, 0x21, 0xa0, 0x3e, 0x0, 0x0, 0x24, 0xa0, 0x2c, 0x40, 0x1, 0x0, 0xe0, 0xfe, 0x9a, 0x3e, 0x0, 0x0, 0x68, 0x44, 0x2d, 0x40, 0x1, 0x0, 0xc0, 0xdc, 0x95, 0x3e, 0x0, 0x0, 0xac, 0xe8, 0x2d, 0x40, 0x1, 0x0, 0xa0, 0xba, 0x90, 0x3e, 0x0, 0x0, 0xf0, 0x8c, 0x2e, 0x40, 0x1, 0x0, 0x80, 0x98, 0x8b, 0x3e, 0x0, 0x0, 0x34, 0x31, 0x2f, 0x40, 0x1, 0x0, 0x60, 0x76, 0x86, 0x3e, 0x0, 0x0, 0x78, 0xd5, 0x2f, 0x40, 0x1, 0x0, 0x40, 0x54, 0x81, 0x3e, 0x0, 0x0, 0xcd, 0x79, 0x30, 0x40, 0x1, 0x0, 0x30, 0x63, 0x78, 0x3e, 0x0, 0x0, 0x11, 0x1e, 0x31, 0x40, 0x1, 0x0, 0xf0, 0x1e, 0x6e, 0x3e, 0x0, 0x0, 0x55, 0xc2, 0x31, 0x40, 0x1, 0x0, 0xb0, 0xda, 0x63, 0x3e, 0x0, 0x0, 0x99, 0x66, 0x32, 0x40, 0x1, 0x0, 0x70, 0x96, 0x59, 0x3e, 0x0, 0x0, 0xdd, 0xa, 0x33, 0x40, 0x1, 0x0, 0x30, 0x52, 0x4f, 0x3e, 0x0, 0x0, 0x21, 0xaf, 0x33, 0x40, 0x1, 0x0, 0xf0, 0xd, 0x45, 0x3e, 0x0, 0x0, 0x65, 0x53, 0x34, 0x40, 0x1, 0x0, 0xb0, 0xc9, 0x3a, 0x3e, 0x0, 0x0, 0xa9, 0xf7, 0x34, 0x40, 0x1, 0x0, 0x70, 0x85, 0x30, 0x3e, 0x0, 0x0, 0xa, 0x9c, 0x35, 0x40, 0x1, 0x0, 0x60, 0x3f, 0x26, 0x3e, 0x0, 0x0, 0x4e, 0x40, 0x36, 0x40, 0x1, 0x0, 0x20, 0xfb, 0x1b, 0x3e, 0x0, 0x0, 0x93, 0xe4, 0x36, 0x40, 0x1, 0x0, 0xd0, 0xb6, 0x11, 0x3e, 0x0, 0x0, 0xd7, 0x88, 0x37, 0x40, 0x1, 0x0, 0x90, 0x72, 0x7, 0x3e, 0x0, 0x0, 0x1b, 0x2d, 0x38, 0x40, 0x1, 0x0, 0xa0, 0x5c, 0xfa, 0x3d, 0x0, 0x0, 0x5f, 0xd1, 0x38, 0x40, 0x1, 0x0, 0x20, 0xd4, 0xe5, 0x3d, 0x0, 0x0, 0xa3, 0x75, 0x39, 0x40, 0x1, 0x0, 0xa0, 0x4b, 0xd1, 0x3d, 0x0, 0x0, 0xe7, 0x19, 0x3a, 0x40, 0x1, 0x0, 0x20, 0xc3, 0xbc, 0x3d, 0x0, 0x0, 0x2b, 0xbe, 0x3a, 0x40, 0x1, 0x0, 0xa0, 0x3a, 0xa8, 0x3d, 0x0, 0x0, 0x6f, 0x62, 0x3b, 0x40, 0x1, 0x0, 0x20, 0xb2, 0x93, 0x3d, 0x0, 0x0, 0xb3, 0x6, 0x3c, 0x40, 0x1, 0x0, 0x40, 0x53, 0x7e, 0x3d, 0x0, 0x0, 0xf7, 0xaa, 0x3c, 0x40, 0x1, 0x0, 0x40, 0x42, 0x55, 0x3d, 0x0, 0x0, 0x3b, 0x4f, 0x3d, 0x40, 0x1, 0x0, 0x40, 0x31, 0x2c, 0x3d, 0x0, 0x0, 0x8c, 0xf3, 0x3d, 0x40, 0x1, 0x0, 0x0, 0x1d, 0x3, 0x3d, 0x0, 0x0, 0xe6, 0x97, 0x3e, 0x40, 0x1, 0x0, 0x0, 0xd, 0xb4, 0x3c, 0x0, 0x0, 0x2a, 0x3c, 0x3f, 0x40, 0x1, 0x0, 0x0, 0xd6, 0x43, 0x3c, 0x0, 0x0, 0x6e, 0xe0, 0x3f, 0x40, 0x1, 0x0, 0x0, 0x90, 0xfc, 0x3a, 0x0, 0x0, 0xb2, 0x84, 0x40, 0x40, 0x1, 0x0, 0x0, 0xb2, 0x4, 0xbc, 0x2, 0x0, 0xb2, 0x84, 0x40, 0x40, 0x3, 0x0, 0x0, 0xb2, 0x4, 0x3c +] +log_index = [ + 0xc, 0x0, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x3a, 0x20, 0x7b, 0x7d, 0x73, 0x1, 0xc, 0x0, 0xe, 0x0, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x7b, 0x7d, 0x73, 0x1, 0xc, 0x0, 0x1c, 0x0, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x61, 0x74, 0x20, 0x7b, 0x7d, 0x73, 0x1, 0xc, 0x0, 0x23, 0x0, 0x59, 0x6f, 0x75, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x74, 0x61, 0x79, 0x65, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x77, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x62, 0x79, 0x20, 0x7b, 0x7d, 0x73, 0x21, 0x1, 0xc, 0x0 +] +log_runlength = [ + # nothing +] + +# create the log.out file +with open("log.out", "wb") as f: + f.write(bytearray(log_content)) + +# create the log.out.index file +with open("log.out.index", "wb") as f: + f.write(bytearray(log_index)) + +# create the log.out.runlength file +with open("log.out.runlength", "wb") as f: + f.write(bytearray(log_runlength)) diff --git a/components/binary-log/include/binary-log.hpp b/components/binary-log/include/binary-log.hpp new file mode 100644 index 000000000..cef67c0d6 --- /dev/null +++ b/components/binary-log/include/binary-log.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include diff --git a/components/binary-log/src/binary-log.cpp b/components/binary-log/src/binary-log.cpp new file mode 100644 index 000000000..76e935d74 --- /dev/null +++ b/components/binary-log/src/binary-log.cpp @@ -0,0 +1 @@ +#include "binary-log.hpp" diff --git a/doc/Doxyfile b/doc/Doxyfile index 395c33f96..76169d7e8 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -25,6 +25,7 @@ EXAMPLE_PATH += $(PROJECT_PATH)/components/ads1x15/example/main/ads1x15_example. EXAMPLE_PATH += $(PROJECT_PATH)/components/ads7138/example/main/ads7138_example.cpp EXAMPLE_PATH += $(PROJECT_PATH)/components/as5600/example/main/as5600_example.cpp EXAMPLE_PATH += $(PROJECT_PATH)/components/aw9523/example/main/aw9523_example.cpp +EXAMPLE_PATH += $(PROJECT_PATH)/components/binary-log/example/main/binary_log_example.cpp EXAMPLE_PATH += $(PROJECT_PATH)/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp EXAMPLE_PATH += $(PROJECT_PATH)/components/bldc_motor/example/main/bldc_motor_example.cpp EXAMPLE_PATH += $(PROJECT_PATH)/components/bldc_haptics/example/main/bldc_haptics_example.cpp @@ -103,6 +104,7 @@ INPUT += $(PROJECT_PATH)/components/as5600/include/as5600.hpp INPUT += $(PROJECT_PATH)/components/aw9523/include/aw9523.hpp INPUT += $(PROJECT_PATH)/components/base_component/include/base_component.hpp INPUT += $(PROJECT_PATH)/components/base_peripheral/include/base_peripheral.hpp +INPUT += $(PROJECT_PATH)/components/binary-log/include/binary-log.hpp INPUT += $(PROJECT_PATH)/components/ble_gatt_server/include/battery_service.hpp INPUT += $(PROJECT_PATH)/components/ble_gatt_server/include/ble_appearances.hpp INPUT += $(PROJECT_PATH)/components/ble_gatt_server/include/ble_gatt_server.hpp diff --git a/doc/en/binary_log_example.md b/doc/en/binary_log_example.md new file mode 100644 index 000000000..1c0d8bd49 --- /dev/null +++ b/doc/en/binary_log_example.md @@ -0,0 +1,2 @@ +```{include} ../../components/binary-log/example/README.md +``` diff --git a/doc/en/logger.rst b/doc/en/logger.rst index b6900dcb0..0936ba726 100644 --- a/doc/en/logger.rst +++ b/doc/en/logger.rst @@ -16,11 +16,22 @@ runtime. Code examples for the logging API are provided in the `logger` example folder. +Binary Logger +------------- + +The binary logger provides a wrapper around +https://github.com/p-ranav/binary_log for enabling compact binary logging of +basic integer, floating point, and string data types. + +Code examples for the binary logging API are provided in the `binary_logger` +example folder. + .. ------------------------------- Example ------------------------------------- .. toctree:: logger_example + binary_logger_example .. ---------------------------- API Reference ---------------------------------- @@ -28,3 +39,4 @@ API Reference ------------- .. include-build-file:: inc/logger.inc +.. include-build-file:: inc/binary-logger.inc