Skip to content
GemelonPublic

About

ESP32-S3 EBC battery tester with offline charts, SD SQLite, MariaDB backup, DCIR and manual OTA

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

EBCTester

Latest release Firmware build Top language Languages License

EBCTester V2 is the current stable release line.

EBCTester logo

Test batteries and keep their measurements without running a PC for weeks.

EBCTester connects supported ZKE EBC battery testers to a small ESP32-S3. The microcontroller operates the tester, executes test plans, and records measurements on an SD card. Its local web interface lets you manage batteries, follow measurements, and view charts from a phone, even outside your home Wi-Fi network.

Install EBCTester firmware directly from your browser with the WebFlasher.

User manuals

Both manuals are in English. Translations are available on request. Sources: docs/manual.

See CHANGELOG.md for user-visible changes by firmware version.

A look at the web interface

Set up a test, close the browser, and come back to the results. The ESP32 handles test execution and SD recording; the browser is your control panel, not a requirement for keeping a test running.

Measurements at a glance

Follow voltage, current, and accumulated capacity, then revisit saved runs. The dashboard combines time-series charts, capacity per segment, and a segment timeline so you can see how a battery behaved throughout a test.

Battery tester dashboard with measurements and voltage and current charts

Click any screenshot to open the full-size image. Expand the sections below for a tour of the other pages. Screenshots show example settings and test states, not recommended battery parameters; private identifiers have been redacted.

Explore battery management and test controls

Keep your batteries organized

Save battery labels, manufacturer details, nominal capacity, and notes on the SD card. Battery details are stored with each test run, helping you identify the cell or pack behind a set of measurements. Delete battery, next to New battery, removes the saved battery currently shown in the form after confirmation. Batteries with recorded test runs cannot be deleted; remove those runs in test-run management first. Recording blocks deletion, and existing MariaDB backups are unchanged.

Battery details form with current battery settings and saved batteries

Take direct control

Start constant-voltage charging or constant-current / constant-power discharging from the browser. See live measurements, tester connection status, and recording progress together; active tests are recorded automatically.

Manual control page with live measurements, connection status, charging, and discharging controls

Let a plan do the repetitive work

Build and save test plans with up to ten steps, combining charge, discharge, and rest periods. The sequence runs on the ESP32 without an open browser or a continuous Wi-Fi connection, as long as the device remains powered.

Automatic test plan sequence, saved plan steps, and step editor

Look beyond capacity

Configure a load-pulse test to measure DC internal resistance, with separate results at 1, 5, and 10 seconds by default. Use a battery with a prepared state of charge or configure automatic preparation, and keep the results on SD alongside your other tests.

Internal resistance load-pulse test parameters, sequence status, and results

Explore storage, updates, and optional integrations

Check the device at a glance

View the installed firmware version, Wi-Fi status, access point details, and clock synchronization from the administration section.

Administration overview with device information and system status

Access your files without removing the card

Browse SD folders, upload language files, and download files through the web interface. Measurements stay in the local SQLite database on the SD card, without requiring a cloud service.

SD card manager showing folders, the SQLite database, and file actions

Update when you choose

Check for firmware updates and follow download progress in the browser. Installation requires an explicit action and confirmation; updates are never installed automatically. Use HTTPS for normal firmware distribution.

Firmware update page showing availability, download progress, and manual installation controls

Add conveniences without making them dependencies

Under Settings > LED function groups, set the total WS2812 LED count (1-16, including extensions) and select each LED's normal display: Tester mode, Message frame status, or Off. Enable OTA override per LED to show update progress instead during an update. Defaults are two board LEDs: LED1 = Tester mode + OTA; LED2 = Message frame status. Assignments apply immediately and persist across restarts, in Maker and Factory firmware alike. LED hardware enablement and GPIO remain hardware configuration settings.

Configure Wi-Fi, optional MariaDB backups, the live debug log, and optional Home Assistant MQTT integration in one place. MQTT provides live values and control, not a copy of the SD database; remote plan start is disabled by default. English and German are built in, with additional languages loadable from SD.

MariaDB checks its required schema in the background. If setup is needed, the settings page offers a one-time migration using separate elevated credentials; those credentials are not saved. Declining disables MariaDB backups only and does not interrupt device operation.

Administration settings for tester, debug log, device reset, LEDs, MariaDB, Home Assistant MQTT, language, login, and Wi-Fi

EBC model support

Select and save the tester under Administration > Settings > EBC tester before connecting. The saved model appears beside the logo and in the control headings even while disconnected. Its charge voltage/current, discharge voltage/current, and constant-power limits apply to manual commands, plans, and internal resistance settings, so plans and parameters can be prepared without a connected tester.

The selection persists across restarts. On first installation or upgrade from automatic model detection, select the model once; there is no assumed default. Changing it is blocked during an operation, plan, or recording and disconnects an idle tester. Existing plans and parameters are preserved and checked against the selected limits when saved or started.

Status-frame identifiers are normalized as the raw byte modulo 100. Firmware version is decoded from bytes 10 and 11 only for status bytes of at least 100, then cached for that connection. A mismatch between two supported selected models displays an error, disconnects the tester, discards pending commands, and blocks automatic reconnection. Recognized disabled models and unknown identifiers remain available as read-only telemetry; all control commands are blocked for them.

All ZKE models in the table below are recognized. Only EBC-A20, EBC-A40L, and EBC-A50L are currently selectable and enabled; the other known models remain read-only until their functionality has been confirmed. If you have one of these models and can verify its operation with EBCTester, please share your results so it can be considered for enablement.

Model Ident (decimal / hex) Firmware version Enabled
EBC-A05+ / EBC-A05 5 / 0x05 302 / other No
EBC-A10+ / EBC-A10H 6 / 0x06 310 / other No
EBC-A20+ / EBC-A20 9 / 0x09 311 / other Only EBC-A20
EBC-A50L / EBC-A40L 10 / 0x0A 311 / other Yes
EBD-M10 / EBD-A10H 20 / 0x14 310 / other No
EBD-M03+ / EBD-M05 / EBD-M03 25 / 0x19 310 / 315 / other No
EBD-A100L / EBC-A100L / EBD-A100 38 / 0x26 310 / 311 / other No

EBC-A40L and EBC-A50L share ident 10 and are separated by firmware version. If version is not yet known, the UI shows EBC-A40L/A50L (Version unknown) and uses conservative A40L limits until the next version-bearing frame. EBC-A20 (18 V / 5 A charge, 30 V / 20 A discharge, 85 W), EBC-A40L (5 V / 40 A, 200 W), and EBC-A50L (5 V / 50 A, 250 W) remain enabled. The existing A40L settings value 16 is retained for compatibility; the actual protocol ident is decimal 10 (0x0A).

The protocol encodes setpoints in two base-240 bytes, with current and voltage setpoints sent in 0.01-unit increments. The numeric range is sufficient for 50 A, but the 10 mA current resolution has not yet been verified on real A50L hardware. The application does not store a battery-chemistry selection; for the 5 V models, select settings appropriate for a lithium cell and verify them against the connected battery before starting.

Why this project?

ZKE devices are useful and affordable for hobbyists, but their hardware and PC software are getting older. From my perspective, the software no longer receives substantial development. Because it is proprietary, I cannot add the features I need myself.

I wanted a more convenient way to store measurements. The biggest drawback, however, was having to keep a PC connected throughout a test. Battery tests can take days or weeks, leaving my laptop tied to the tester instead of available for other work.

With EBCTester, I can implement the features I want without waiting for the manufacturer. Storing measurements in a database provides a foundation for future comparisons across batteries and additional export formats.

Optional MariaDB synchronization allows large datasets to be archived outside the SD card. After verifying a backup, local runs can be deleted deliberately without losing their external copies. The software does not delete local data automatically.

I started with ESPHome, but some of my batteries are outside the range of my home Wi-Fi. I needed a standalone solution that keeps recording there and can still be operated from a phone through its own Wi-Fi access point.

-- Thomas Stoll

Available features

  • No continuously running PC: Manual operations and automatic charge/ discharge plans run on the ESP32-S3. The browser can be closed.
  • Offline recording: SQLite on a FAT32 SD card. Recording needs a ready SD database, not a home Wi-Fi connection.
  • Browser interface: Local Bootstrap UI, battery details, charts, and separate testing and administration sections. CSS, JavaScript, and Chart.js are served by the device, without a CDN.
  • Internal resistance: Configurable load-pulse test with separate results at 1, 5, and 10 seconds by default, using measured current. Supports an already prepared state of charge or automatic preparation.
  • Optional MariaDB backup: Transfers test runs and structured resistance results to an external database.
  • Optional Home Assistant MQTT: Publishes committed measurements and accepts validated plan/battery selection and control commands. Remote plan start requires an explicit opt-in and is disabled by default. Broker connection details are entered after installation in the device web UI.
  • UI languages: English and German, with English fallback; additional translation files can be loaded from SD.
  • Optional live log over Wi-Fi: A Debug tab shows the last 500 log lines in the browser, so the device can be diagnosed without a USB cable. Disabled by default and switched on in Settings → Debug log.
  • Manual updates: New firmware is offered, but installation requires a button click and confirmation.

Current version: Release, developed with ESP-IDF 6.0.1 for ESP32-S3. EBC-A20, EBC-A40L, and EBC-A50L are currently enabled for selection and control. Other models in the table are recognized but await functional verification before they can be enabled. Additional export formats and cross-battery analysis are possible extensions, not completed features.

Architecture and reuse

The application is divided into functional components. The main program remains small and initializes services; implementation belongs in the modules.

Two packages are independent repositories so networking, updates, and SD management can be reused in other projects without rewriting them:

Repository Responsibility
EBCTester Battery control, test plans, recording, charts, DCIR, and MariaDB backup
ota-suite Wi-Fi provisioning, manual OTA, shared web UI, localization, and status LED
sd-card-manager SDMMC/SPI, card detection, shared storage locking, and file management

The packages are pinned Git submodules under external/. SD Card Manager uses OTA Suite's web interface. OTA Suite itself needs neither EBCTester nor SD.

Application component Responsibility
ebc_link UARTs, frame parser, and tester communication
test_control / test_store Controls, plans, batteries, and recording
resistance_test DCIR preparation, load pulse, and evaluation
sqlite3 / battery_database SQLite adapter, SD VFS, and schema
battery_dashboard Measurements and local charts
mariadb_sync Incremental external backup
ui_localization Additional SD language files
debug_log In-memory log ring buffer and the Debug tab

See the technical reference for endpoints, state transitions, and detailed parameters. Development content is always English; explicitly requested UI translations remain available. See AGENTS.md.

Quick start

Recorded runs can be managed under Administration → Test run management: filter/search the table, select one completed run, then rename or delete it. Running tests are protected. Names and deletions affect only the SD database; existing MariaDB backups remain unchanged. See test run management and schema upgrades before installing firmware or downgrading to an older version.

No build environment needed: download EBCTester-<version>-full-install.bin from the latest release and flash it at address 0x0. Instructions are in the release notes. To build from source, see below.

Using and compiling the project

Requirements

  • ESP32-S3 with 16 MiB flash, such as N16R8. Defaults enable optional octal PSRAM; other boards require matching settings.
  • ZKE EBC-A20 with suitable 3.3 V / 5 V TTL level shifting. ESP32 GPIOs are not 5 V tolerant.
  • FAT32 SD card, compatible wiring, and appropriate pull-ups.
  • VS Code with the ESP-IDF extension, ESP-IDF 6.0.1, and Git.
  • Internet for the first build to obtain managed components and the hash-verified SQLite archive. The installed UI works offline.

Download

The three repositories are public. Include their submodules; a ZIP download alone does not contain the package checkouts:

git clone --recurse-submodules https://github.com/Gemelon/EBCTester.git

For an existing checkout:

git submodule update --init --recursive

Do not use git submodule update --remote without reviewing the changes. The parent repository records the tested package commits.

Configure hardware and build

  1. Open the project in VS Code and select the ESP-IDF environment.
  2. Select target esp32s3.
  3. Review board, flash, PSRAM, SD mode, and UART pins in menuconfig.
  4. Compile using ESP-IDF: Build your project.
  5. For initial installation, flash bootloader, partition table, and application over USB. The partition table requires 16 MiB flash.

The optional dev container also uses IDF 6.0.1. sdkconfig is the effective local build configuration and takes priority over sdkconfig.defaults. It is generated by ESP-IDF and is not tracked in Git. Change settings through menuconfig; deleting a setting from sdkconfig only restores its Kconfig default. Every application build automatically runs ESP-IDF's save-defconfig target to synchronize sdkconfig.defaults with the effective local configuration. Commit the resulting defaults changes with the source changes: fresh checkouts and GitHub builds reconstruct their configuration from this file, including the board's UART pins, SD bus mode and pins, RTC pins, flash and PSRAM settings. Defaults are a minimal configuration, not a byte-for-byte copy of sdkconfig. Changes to defaults do not override an existing local configuration. Review exported settings before committing; keep private credentials in device settings rather than build configuration. dependencies.lock pins managed dependencies. OTA_SUITE_DIR and SD_CARD_MANAGER_DIR can select alternative component checkouts.

Building does not flash the device or start a battery test. A changed partition table cannot be installed through OTA. Back up settings and data before repartitioning.

Board schematic and main components

The diagram is a functional overview, not a pin-level drawing. The complete circuit schematic is included as a PDF; the bill of materials lists all 26 line items and 57 components, including manufacturer part numbers and LCSC references (53 SMD, 4 THT).

flowchart LR
  P19["19 V input"] --> B5["U2: 19 V to 5 V buck"]
  P19 -. "input clamp" .-> TVS["D3 input TVS"]
  TVS --> GND["GND"]
  B5 --> OR["D1/D2: Schottky power OR"]
  USB["USB-C VBUS"] --> OR
  OR --> V5["+5 V rail"]
  V5 --> B33["U3: 5 V to 3.3 V buck"]
  B33 --> MCU["U4: ESP32-S3"]
  USB --> ESD["D4: USB ESD protection"]
  ESD --> MCU
  MCU --> SD["J1: microSD"]
  MCU --> RTC["U1: RTC"]
  RTC --> CELL["BT1: backup cell"]
  MCU --> SHIFT["U5: UART level shifter"]
  SHIFT --> UART["J4: UART connector"]
  MCU --> EXP["J3: expansion connector"]
Loading
Board section Key components Purpose
Power AP63205 19 V-to-5 V and AP63203 5 V-to-3.3 V converters; SS34 diodes; SMBJ20A TVS Powers the board from the 19 V input or USB VBUS and protects the input
Controller and USB ESP32-S3-WROOM-1U-N16R8; USB-C receptacle; USBLC6-2SC6 Runs the firmware and provides the USB connection with ESD protection
Storage and clock microSD socket; DS3231 RTC; CR2032 holder Stores measurements and keeps time when main power is removed
Serial and expansion TXS0104E level shifter; 6-pin UART and 14-pin expansion headers Connects serial signals and provides a reserved expansion header

PCB views

These KiCad renderings show the board layout and assembled-board previews; they are design views, not photographs of a manufactured board. Click an image to open it at full size.

PCB layout view showing tracks, pads, and component labels Three-dimensional top view of the assembled EBCTester PCB Angled three-dimensional view of the EBCTester PCB

The editable KiCad schematic, PCB layout, and design files are maintained with the separate hardware project and are not included here. The PDF, BOM, images, and service-specific assembly BOMs in this repository are the published board-documentation snapshot.

Default connections

The following assignments match the V2 sdkconfig in this workspace. Check your build's sdkconfig and saved Maker Settings before wiring; either can override them.

Connection TX RX Settings
UART1 to tester 10 11 9600 baud, 8O1
UART2 to PC dongle 8 9 9600 baud, 8O1

The dongle bridge is not implemented yet. UART2 is initialized, but traffic is not forwarded to the manufacturer's software.

The current V2 configuration selects SPI for the SD card:

SD signal SPI GPIO 4-bit SDMMC GPIO
CLK 6 6
MOSI / CMD 7 7
MISO / D0 5 5
CS / D1 17 4
— / D2 — 18
— / D3 — 17
Card detect 13 13

Both bus modes are configured for 10 MHz. Card detection defaults to active low, matching the original board's switch. Enable Card detect active high (off: active low) in Maker Settings or CONFIG_SD_CARD_MANAGER_CARD_DETECT_ACTIVE_HIGH in menuconfig for active-high wiring. Existing saved configurations retain active-high detection after an upgrade; clear the Maker checkbox for an active-low switch. Use GPIO -1 only when no card-detect switch is connected. Changes take effect after restart. Cards are never formatted automatically; exFAT is unsupported. The RTC uses INT/SDA/SCL GPIO 14/15/16. The optional WS2812 LED uses GPIO 48.

First access and daily operation

The hardware configuration is stored in NVS. On a new or invalid configuration, GPIO47 selects the initial mode: externally HIGH selects FactoryMode with peripherals enabled; LOW, open, or inconsistent readings select MakerMode with peripherals disabled. A valid saved configuration bypasses GPIO47.

Maker Settings is available only in MakerMode; the existing Settings tab remains available in both modes. Configure UARTs, SD bus/pins, networking, OTA, LED, recording, optional RTC and MQTT defaults here, enable ConfigAktive, and save. The device restarts before enabling the hardware. While inactive, only the AP and web interface run: no tester/dongle UART, SD, LED, station Wi-Fi, SNTP, update checking, RTC, recorder, or MQTT starts. Flash/PSRAM and the SDK console are outside this application-peripheral guarantee.

Optional DS3231 clock

The RTC is always enabled in FactoryMode, including existing installations after an update. FactoryMode also enforces the original-board RTC pin mapping INT/SDA/SCL = GPIO14/GPIO15/GPIO16. Normal users do not need access to Maker Settings. In MakerMode, it is disabled by default; use Maker Settings → Real-time clock to enable it and configure the I2C pins before saving and restarting. SDK and original-board defaults are RTC INT GPIO14, SDA GPIO15, SCL GPIO16. INT is a reserved input (or -1 when disconnected); alarms and wakeup are not implemented. Use external I2C pull-ups to 3.3 V (the original board has them). GPIO conflicts with enabled peripherals are rejected.

With RTC enabled, startup reads a valid RTC immediately, then a successful NTP response synchronizes device time and the RTC. NTP synchronization repeats every six hours. Without a new NTP response, device time is refreshed from the RTC every six hours. A stopped oscillator, invalid calendar, or missing RTC is logged and never replaces device time with an invented timestamp. NTP remains usable even when RTC hardware is missing.

RTC and device time use UTC. When RTC is enabled or synchronized time is available, the header shows time above date immediately beside EBC RX. Display conversion uses the browser's current time zone, including daylight saving time, not the browser's clock. Unavailable or stale device time is shown as placeholders. With RTC disabled, existing NTP behavior is unchanged. Configuration upgrades preserve existing settings: FactoryMode enables RTC, while MakerMode preserves its saved selection (off when migrating from v1). An inactive configuration still disables all peripherals, including RTC.

If an enabled RTC is physically missing, bounded I2C failures are logged and NTP continues to provide device time. UI, recording and other services remain available; RTC operations retry on subsequent synchronization attempts. Without either NTP or a valid RTC, calendar time stays unavailable and recording continues using the existing uptime-based behavior.

Hardware validation on the original PCB is pending; no hardware is flashed or battery test started by the host checks.

Connecting to the device

  1. Start the device using the setup AP password configured for the firmware. The standard project default is ebctester; change it before deployment.
  2. Connect a phone or computer to ebct-XXXXXX.
  3. Open http://ebct-XXXXXX.local/ (using the suffix from your device's AP name), or http://192.168.4.1, and log in as admin with the initial web password ebctester. SDK configuration supplies initial defaults only; subsequent starts use the saved NVS configuration.
  4. Optionally configure home Wi-Fi. Local operation and recording do not require that connection.
  5. Insert a FAT32 card, check database readiness, create a battery, and connect the tester. Only then start a measurement or plan.

The six hexadecimal suffix characters come from the device's SoftAP MAC address, not the SD card, and remain stable across reboots and firmware updates. The same .local address works through the setup AP and on the router WLAN; mDNS also advertises the HTTP service on port 80. Your phone/computer must support mDNS and be on the same local network; guest isolation, VPNs or blocked multicast can prevent resolution. In that case, use the device's station IP or, while directly connected to its AP, 192.168.4.1. Updating this firmware changes the default AP prefix from BatteryTester to ebct; reconnect to the new SSID. Saved passwords and router credentials are unchanged. Custom firmware AP prefixes are also used as the mDNS hostname and must form a valid DNS label together with the MAC suffix.

The Battery tester section contains Measurements, Battery, Manual, Automatic, and Internal resistance. Administration contains Device information, SD card, Updates, and Settings.

Under Administration → Settings → Login Settings, choose Daily (24 hours) or Weekly (7 days). Daily is the default. The duration starts at login, does not renew with activity, and applies to new logins after saving. The browser remembers the session across browser restarts unless cookies are cleared. A device restart or Log out ends the session; recording and test plans continue independently of browser login.

Change the login password here using 8-63 printable ASCII characters without leading or trailing spaces; leave the password fields empty to keep it. The saved password survives restarts and firmware updates and is independent of the setup AP password. Existing devices without a saved web password also start with ebctester after updating. Change this shared default on first use.

Uncheck Require browser login to open the interface without logging in. Anyone on the network can then view data and use the controls. Settings changes still require the configured login password. Password changes and toggling login invalidate existing sessions; the interface reloads automatically.

Saving device settings asks for the configured login password by default, including Wi-Fi, login settings, debug logging, MariaDB and MQTT settings. Canceling the prompt or entering an incorrect password does not save changes. Disable this additional confirmation in Maker Settings on Maker devices. The SDK option sets only the first-start default. CSRF protection remains mandatory, as does a valid session when browser login is enabled. Test controls, OTA actions, SD operations, and the browser-only language selection do not require this additional password.

Settings → Device reset offers two confirmed resets. Reset device configuration erases only ebc_cfg; saved station Wi-Fi and other namespaces remain. Erase all NVS settings including Wi-Fi clears the complete NVS partition. Both restart and repeat GPIO47 detection; neither erases SD data. Stop running tests and wait for pending recordings before saving hardware configuration or resetting.

The first installation of this configuration format seeds the listed hardware and OTA values from SDK defaults, not older per-module settings. Verify those defaults before updating an existing device. In particular, keep GPIO47 HIGH on original boards that should start immediately.

Plans support D-CC, D-CP, C-CV, waits, and repetitions. After a restart, an interrupted plan is not resumed blindly. Stop and Abort remain available; conflicting start actions are blocked.

Data, backup, and languages

The local database is /sdcard/ebc_a20.db. Schema and integrity are checked when opened. A missing card does not block the web interface, but recording requires a ready database. Invalid database files are preserved, not silently overwritten.

MariaDB is optional and initially disabled. Configure host and credentials under Settings; transfer requires network access. Base tables from migrations 001-005 must already exist. This repository includes migration 006 for DCIR results, not a complete initial MariaDB schema. Delete local runs only after verifying their backup; external copies remain.

English and German are built in. Copy the English template or Filipino test catalog to /languages/ on the SD card, reload languages, and select one. Missing keys fall back to English. Switching language reloads the page and loses unsaved forms, but does not stop a running test.

Updates and publishing firmware

Automatic availability checks download only the manifest. Installation is manual after confirmation. HTTPS validates certificates; HTTP requires explicit opt-in for a trusted test network. Size, SHA256, and image metadata are checked before boot selection. Rollback protects a pending image that does not survive its startup window.

The default manifest address is a placeholder. Set your HTTPS URL in menuconfig under OTA Suite update checks.

Public OTA deployment is handled exclusively by GitHub Actions. Do not upload firmware to the update server from local builds or manual SFTP commands. Local firmware packaging is disabled in a fresh checkout. To prepare packages without uploading them, create the Git-ignored CMakeUserConfig.cmake:

set(EBCTESTER_PUBLISH_FIRMWARE ON)
set(EBCTESTER_PUBLISH_DIR "${CMAKE_BINARY_DIR}/firmware-publication")
set(EBCTESTER_PUBLISH_ORIGIN "https://ebctester.gemelon.de")
set(EBCTESTER_PUBLISH_URL_PATH "")
set(EBCTESTER_SFTP_UPLOAD OFF)

After reconfiguration, successful builds prepare a versioned image, the compatibility name, and finally an atomic firmware.json locally in build/firmware-publication. The destination directory must already exist; no NAS or network drive is needed. Published versions cannot be replaced with different bytes: increase the version first. Publication errors fail the step.

Publishing copies license documentation before the image to licenses/EBCTester-<version>/. Missing documents fail the step. Distribute the complete license directory with firmware, not just .bin. The OTA manifest format is unchanged. See third-party notices.

On GitHub, a push to main automatically builds a release when the version in CMakeLists.txt is newer than the latest release and has not already been published. The release includes the OTA image, full-install image, update manifest, and license bundle; the public OTA server receives the versioned image, compatibility image, license bundle, and manifest. Existing versions are never replaced. Update CHANGELOG.md and PROJECT_VER before publishing a new version.

To enable public OTA deployment from GitHub Actions, add these repository secrets: OTA_SFTP_HOST, OTA_SFTP_USER, OTA_SFTP_REMOTE_DIR, OTA_SFTP_PRIVATE_KEY, and OTA_SFTP_KNOWN_HOSTS. Set the optional OTA_SFTP_PORT secret only when the server does not use port 22. The deploy job uses strict host-key checking and refuses to replace an existing version with different firmware bytes. After adding or rotating the secrets, run the Firmware workflow manually on main to publish the existing release to the OTA server.

Limitations, safety, and contributions

  • Independent hobby project, not an official ZKE product or a claim of manufacturer support.
  • Battery settings and protection limits must match chemistry, wiring, and equipment ratings. Software does not replace hardware protection. Long-running tests are not automatically safe to leave unattended.
  • The local server uses cookie-based sessions over unencrypted HTTP. Use only a trusted LAN or protected AP; never expose it to the internet. HTTP exposes both passwords and session cookies to network interception.
  • MariaDB uses unencrypted TCP. NVS/flash are not encrypted by default; protect passwords and serial access.
  • SHA256 is not a signature. Secure Boot, signed firmware, and flash/NVS encryption are separate deployment decisions.
  • UTC timestamps need valid device time. Without it, uptime-based recording is available; timestamps are not fabricated.
  • Check SD cards, power, and backups. No guarantee of measurement accuracy, loss-free storage, or fitness for a particular purpose.

Reports and contributions are welcome. Include board, firmware version, reproduction steps, and sanitized logs. Never publish passwords, tokens, or private measurements in issues or commits. Test changes to protocol, schema, and safety limits. Mark redistributed modified Apache-covered files and preserve copyright/license notices.

Tests

Host tests require Node.js, Python, and CMake for publishing; no additional Node packages:

node --test tests\dashboard.test.js tests\web_interface.test.js tests\web_auth_ui.test.js tests\publication.test.js tests\ui_languages_test.js
python tests\resistance_schema_test.py
python tests\web_auth_test.py
python tests\license_metadata_test.py

Set CMAKE_EXE, OTA_SUITE_DIR, and SD_CARD_MANAGER_DIR if needed. Authentication tests require restored managed dependencies and a host C compiler (CC, cl in a Visual Studio developer shell, or cc). They run with password confirmation both enabled and disabled, without contacting or flashing hardware. Native manifest/DCIR tests and hardware checks are described in the technical reference. python tests\ui_language_fixture.py serves simulated browser data only; it does not operate hardware.

License and authorship

Copyright 2026 Thomas Stoll. Original code and documentation in EBCTester, OTA Suite, and SD Card Manager are licensed under Apache License 2.0. Commercial use, changes, and sale are permitted under its terms. Its warranty and liability disclaimers apply. It does not grant rights to third-party trademarks.

NOTICE contains project attribution. Source files have SPDX copyright/license headers; commentless formats are covered by .reuse/dep5. This does not relicense third-party code.

Third-party components and licenses

This project builds on others' work. Their copyrights, license texts, and disclaimers remain intact; dependencies are not presented as original project code or blanket-relicensed.

Component Author / origin License and supplied notices
Bootstrap 5.3.3 The Bootstrap Authors MIT - original text
Chart.js 4.4.9 Chart.js Contributors MIT - original text
@kurkle/color 0.3.2, included in Chart.js Jukka Kurkela MIT - original text
SQLite 3.53.4 SQLite authors Public Domain; separately downloaded amalgamation
ESP-IDF 6.0.1 Espressif Systems and contributors Apache-2.0 for original Espressif code; SDK license; other SDK parts below
cJSON 1.7.19~2 Dave Gamble and cJSON contributors MIT - original text
led_strip 3.1.0~1 Espressif Systems Apache-2.0 - original text
FreeRTOS-Kernel Amazon.com and contributors MIT - original text
lwIP Swedish Institute of Computer Science and other authors BSD-3-Clause - original text
FatFs ChaN Custom permissive terms - original notice
Mbed TLS / TF-PSA-Crypto Upstream authors Apache-2.0 option where dual-licensed; Mbed TLS, TF-PSA-Crypto; file-specific notices apply
wpa_supplicant Jouni Malinen and contributors BSD-3-Clause - license, copyright
http_parser Igor Sysoev, Joyent, and Node contributors MIT - original text
C runtime: Newlib / Picolibc Multiple authors Collection of mostly permissive terms - Newlib, Picolibc
GCC runtime: libgcc / libstdc++ Free Software Foundation and contributors GPL-3.0 with GCC Runtime Library Exception 3.1 - GPL, exception
TLSF allocator Matthew Conte BSD-3-Clause - original notice
Argtable3 / linenoise Stewart Heitmann; Salvatore Sanfilippo and Pieter Noordhuis BSD terms - Argtable3, linenoise
protobuf-c / SPIFFS, SDK components Dave Benson and protobuf-c authors; Peter Andersson BSD-2-Clause / MIT; configuration-dependent
Other file-specific SDK notices Authors credited in original headers Collected notices, including BSD, MIT, and CC0; standard texts

Additional unmodified SDK texts are in third_party/licenses/. dependencies.lock records managed versions. See THIRD_PARTY_NOTICES.md for provenance and source/ firmware distribution obligations. Review this inventory for different SDK versions or new components; it does not replace actual upstream license texts.

About

ESP32-S3 EBC battery tester with offline charts, SD SQLite, MariaDB backup, DCIR and manual OTA

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages