Brinkhaus-Tools

Library for connecting your own applications to FleetManagement — available for Python, Rust, C++, and JavaScript.

Installation

Brinkhaus-Tools is available in four languages. All variants share the same version number and speak the same fleet protocol — see the API reference for details.

Python

pip install brinkhaustools

Rust

# Cargo.toml
[dependencies]
brinkhaustools = { git = "https://gitlab.com/brinkhaus/brinkhaustools.git", tag = "0.17.0" }

# With fleet management client:
brinkhaustools = { git = "https://gitlab.com/brinkhaus/brinkhaustools.git", tag = "0.17.0", features = ["fleet"] }

The crate is deliberately consumed as a git dependency from the public repository — publishing to crates.io is not planned for the medium term.

C++

# CMakeLists.txt
include(FetchContent)
FetchContent_Declare(
    brinkhaustools
    GIT_REPOSITORY https://gitlab.com/brinkhaus/brinkhaustools.git
    GIT_TAG        0.17.0
    SOURCE_SUBDIR  cpp
)
FetchContent_MakeAvailable(brinkhaustools)
target_link_libraries(myapp PRIVATE brinkhaustools::brinkhaustools)

JavaScript

git clone https://gitlab.com/brinkhaus/brinkhaustools.git
# Copy js/src/brinkhaus-tools.js into your project — zero dependencies, browser-compatible

The examples below show the Python variant; the API has the same shape in all languages.

Create an App

The App class is the central entry point. It automatically initializes settings, logging, self-diagnosis, status reporting, and the fleet connection.

from brinkhaustools.common import App

app = App("MyApplication", "1.0.0")
app.start()

# ... application logic ...

app.wait()  # Blocks until shutdown signal

Self-Diagnosis

Use the SelfDiagnosisEngine to report errors and resolve them. Messages appear in the FleetManager dashboard as traffic-light status.

from brinkhaustools.common import App

app = App("MyApplication", "1.0.0")
diag = app.self_diagnosis

MQTT_ERROR_CODE = 1001

try:
    mqtt_client.connect(host, port)
    diag.clear(MQTT_ERROR_CODE)
except Exception as e:
    diag.notify(MQTT_ERROR_CODE, f"MQTT connection failed: {e}",
                critical=True)

notify() sets a diagnostic message, clear() resolves it. While a critical message is active, the traffic light shows red.

Status Reporting

Register custom StatusSource objects to send runtime information to the FleetManager.

from brinkhaustools.common import App
from brinkhaustools.common.status import StatusSource

class MqttStatus(StatusSource):
    def get_status(self):
        return {
            "MQTT-Host": f"{self.host}:{self.port}",
            "Connected": self.connected,
        }

app = App("MyApplication", "1.0.0")
app.status_engine.register_source(MqttStatus())

The StatusEngine periodically collects all registered sources and sends the snapshot to FleetManager.

Configure Fleet Connection

Create a configuration file at fleetManagementData/config.json:

{
  "base_url": "https://fleet.brinkhaus-gmbh.de",
  "token": "fmt_YOUR_TOKEN",
  "customer_name": "your-customer",
  "machine": "your-server",
  "heartbeat_interval_sec": 60
}

The App automatically detects this configuration and starts sending heartbeats, diagnostic messages, and status snapshots to FleetManager.

Changelog

0.17.0 2026-07-01

Added

  • [Python, Rust, C++] StatusValue: self-describing status leaves with type, optional unit, label, and hint — constructors include boolean, integer, number, text, enum, timestamp, duration, bytes, percent, and temperature
  • [Python, Rust, C++] StatusSource sources may return StatusValue anywhere a plain value would go — existing sources returning plain scalars keep working unchanged, no migration required
0.16.0 2026-06-19

Added

  • [Rust] LoggingHelper::install(config) registers the helper as the global log backend — log::info!/warn!/error! now reach the rotating log file, ring buffer, and console instead of being silent no-ops
  • [Rust] LoggingConfig.console (default on) mirrors each formatted log line to stdout — can be disabled for headless or service operation
0.15.0 2026-06-16

Added

  • [Python] register_command(): commands with a parameter spec and dynamic options provider (parameter_options) — the option list is re-evaluated for every status snapshot, e.g. a firmware deployment with a live version dropdown instead of one fixed button per version
  • [Python] Command callbacks may accept one argument to receive the operator's choice as payload — zero-argument callbacks keep working unchanged
0.14.0 2026-06-12

Added

  • [Rust] HeartbeatEngine::expired(): names the heartbeats whose deadline has passed, so watchdogs can act on the specific offenders (diagnosis codes, restart paths)
  • [Rust] Configurable StatusSource node names: with_status_name() on SelfDiagnosisEngine and HeartbeatEngine — for consumers composing their own status trees
  • [Rust] StatusEngine::start_background(): working background collection loop that ends cleanly on shutdown or stop()

Changed

  • [Rust] StatusEngine::start() is deprecated (was an accidental no-op) — use start_background() or run_status_loop() instead
0.13.0 2026-06-10

Added

  • [C++] Settings: integrity check on load, persistent data-loss breadcrumb (__data_loss__), and recoveredFrom() tracking — parity with the Python/Rust power-off hardening (new API: recoveredFrom(), hasDataLossFlag(), dataLossInfo(), clearDataLossFlag())

Changed

  • [All] Status payload: the message field is now optional and omitted when empty
0.12.0 2026-06-10

Added

  • [Rust, C++] Fleet-hierarchy parity with Python: heartbeats now carry the optional location plus group/group_priority/sort_priority — configurable via the App builder, each field is sent only when set, packet format stays backward-compatible
0.11.0 2026-06-10

Added

  • [All] FLEET_TOKEN environment variable overrides the fleet token from the config file — containers can inject the secret via the environment instead of baking it into the mounted config (Python, Rust, and C++)
0.10.0 2026-06-10

Fixed

  • [C++] Fleet client never transmitted: FleetMonitorClient::start() / StatusMonitor::start() now spawn the heartbeat and controller threads, so heartbeats, diagnostics, and status reach the FleetManager
  • [C++] TLS peer/host verification is now explicitly enforced on fleet HTTPS requests, with an optional CA bundle (FleetClientConfig::ca_bundle or FLEET_CA_BUNDLE)
  • [Rust] Same latent bug in the fleet monitor: run_fleet_loops() now drives the heartbeat + controller loops; connection diagnosis (code 7002) and config retry were previously dead code

Added

  • [C++] HeartbeatEngine (watchdog for hung components), LoggingHelper (rotating log file + ring buffer, opt-in), and Settings with crash-safe atomic save — parity with Python/Rust
  • [C++] App builder: opt-in settingsFile(), logging(), and heartbeatTimeout(); HeartbeatEngine registered as a status source
  • [Rust] Switchable fleet reporting in App via AppBuilder::fleet_config() (behind the fleet feature) — auto-starts the loops on App::start()
0.5.0 2026-05-19

Added

  • [Python] register_command(): applications can expose remotely-invocable commands (e.g. reboot-edge) to the FleetManager — the catalog is advertised in each status snapshot, callbacks run in a worker thread, ACK either after completion (post) or up-front (pre) for destructive commands like host reboots
  • [Python, Rust] Settings: integrity trailer (SHA-256 over canonical JSON) written on every save and verified on load — a mismatch triggers the existing .bak/.bak2 recovery chain
  • [Python, Rust] Settings: recovered_from tracking (primary/bak/bak2/fresh/…) plus a self-heal save after a successful fallback, rebuilding the main + backup chain
  • [Python, Rust] Settings: persistent __data_loss__ breadcrumb when all three files are unusable — survives reboots and drives application-level self-diagnosis until explicitly cleared (has_data_loss_flag(), data_loss_info(), clear_data_loss_flag())

Fixed

  • [Python, Rust] Power-off robustness: after a power cut, settings used to be silently rebuilt from code defaults and the backups overwritten — the data loss is now visible and persists across reboots
0.4.0 2026-04-22

Fixed

  • [Python] FleetMonitorClient now treats any 2xx status as success — the 202 response from /diagnostics was previously misclassified as a connection error, showing a permanent "FleetManager: Not connected" (diag code 7002) even though the data arrived

Added

  • [C++] Initial C++ variant: SelfDiagnosisEngine, StatusEngine, ShutdownHandler, VersionInformation, FleetMonitorClient, StatusMonitor, and App builder — pure C++17 with nlohmann/json and libcurl, no Qt dependency
  • [Rust] Merged core and fleet crates into a single crate with a fleet feature flag
  • [All] Auto-generated API reference documentation for Rust (rustdoc), JavaScript (jsdoc2md), and C++ (Doxygen)

Changed

  • [JS] Distribution via git dependency instead of the npm registry
0.3.0 2026-03-11

Added

  • FleetMonitorClient: Receive agent commands via ingest response body (piggyback)
  • FleetMonitorClient: Register callback for incoming commands
  • FleetMonitorClient: Acknowledge executed commands to FleetManager
0.2.5 2026-03-07

Fixed

  • Settings: Atomic writes now crash-safe — fsync on file and directory
  • Settings: Second backup generation prevents data loss on two consecutive crashes
0.2.4 2026-03-06

Added

  • CHANGELOG.md and RELEASING.md for unified release process
0.2.2 2026-03-01

Added

  • Config retry and client reconfiguration for late fleet config availability
  • Tests for send_snapshot and StatusSource ABC compliance
0.2.1 2026-03-01

Added

  • Full status snapshot reporting to Fleet Management
0.2.0 2026-03-01

Changed

  • StatusSource implementations now inherit from ABC
0.1.1 2026-02-28

Added

  • Fleet Management documentation: config format, tokens, endpoints

Changed

  • MQTT references replaced with HTTPS

Start for free — 5 devices included

Fleet monitoring and security compliance in under 10 minutes. No credit card required.

Want to talk to an expert?

Click the link and we'll have a quick chat.

Schedule a Call →