Skip to main content

Crate bhtune_cli

Crate bhtune_cli 

Source
Expand description

bhtune — the headless adapter (Rust library target bhtune_cli).

Builds the bhtune binary: a scriptable, no-GUI way to run an MRFT tune and inspect its history, intended for scheduled/unattended use (cron, CI, batch tuning campaigns) as well as interactive terminal use.

  • args — the clap derive Cli/Command definitions and the wrapper enums adapting bhtune-core’s domain enums to clap::ValueEnum (required by Rust’s orphan rule).
  • config, db, driver, logging, and retention — re-exports of bhtune-runtime services used by CLI command handlers. Configuration precedence, database bootstrap/seeding, driver construction, logging, and retention behavior are shared with the HTTP adapter rather than implemented here.
  • commands — one module per subcommand family: check, tune/simulate, template, history, export, opc.
  • output — CLI-specific --output table|json formatting and error presentation; shared sample export serialization is provided by bhtune-runtime.

main.rs stays a one-line delegator to run; run_with_cli is the internal entry point, kept separate so tests can exercise it against an already-parsed args::Cli without needing to control std::env::args() — mirroring opcda-bridge-client’s run/run_with_cli split. Logging is initialized in run, not run_with_cli, for the same reason: it keeps tracing setup (and its process-global, only-succeeds-once subscriber installation) entirely out of run_with_cli’s own large, injection-based test suite – see logging’s test module doc comment.

Non-interactive/scheduled use (cron, CI, batch campaigns) is tune/simulate’s --yes/--write-pid <level> flags (bypassing the interactive write-back prompt) plus the global [tuning] timing configuration, which mandatorily bounds unattended runs and caps individual driver operations, and this module’s distinguished exit codes (EXIT_ABORTED, EXIT_TIMED_OUT, EXIT_POOR_QUALITY, EXIT_ACTUATION_FAILED, EXIT_WRITE_BACK_FAILED, EXIT_RESTORE_INCOMPLETE), so a scheduler can tell “aborted”, “timed out”, “the plant data couldn’t be trusted”, “test ran but the write-back failed”, “the loop may not have been fully restored”, and “never ran at all” apart without parsing stdout. See AGENTS.md’s cli-automation/cli-safety sections.

Modules§

args
Command-line argument definitions (clap derive) and the small wrapper enums that adapt bhtune-core’s domain enums to clap::ValueEnum.
cancel
A single, process-wide Ctrl+C listener shared by every await point in a tune. Registering the signal exactly once, as early in the process as possible, closes the gap where a Ctrl+C delivered while no listener happens to be alive is silently swallowed – tokio installs a process-wide SIGINT handler the first time ctrl_c() is polled and never reverts to the OS default, so a lost signal isn’t merely unhandled, it’s gone.
commands
One module per subcommand family.
config
Global bhtune configuration, including the shared [tuning] timing policy and the CLI flag > env var > TOML config file > built-in default precedence used by settings that expose command-line or environment overrides.
db
Opens the CLI’s database for mutating commands, seeds the built-in and user-catalog DCS/PLC templates, and runs the retention sweep. Read-only commands such as bhtune check use a separate connection that skips bootstrap and retention.
driver
Constructs the selected bhtune_driver::Driver implementation from a TuneRequest.
gateway
Shared opcda-bridge compatibility checks for live mutations and inspection surfaces.
logging
Shared structured application logging, matching opcda-bridge-gateway’s own tracing stack and log.* configuration conventions (level/directory/format/rotation, resolved with the same CLI flag > env var > config file > default precedence as every other bhtune setting) – see crate::config::LogConfig/resolve_log_settings.
output
Output format selection for history list, history show, tune, and simulate. These commands support --output json; other commands keep their existing human-readable output.
retention
Age-based deletion of old tune runs.

Constants§

EXIT_ABORTED
A tune/simulate run was aborted (Ctrl+C) before it finished; the loop was restored to its pre-test mode. Distinct from EXIT_FAILURE so a scheduler can tell “someone intentionally stopped this” apart from “this broke”.
EXIT_ACTUATION_FAILED
A live OPC DA tune was aborted because an accepted MV command could not be confirmed at the controller before its deadline or before a replacement relay command was required. The ordinary restore path still ran; EXIT_RESTORE_INCOMPLETE takes precedence if that restore could not itself be confirmed.
EXIT_CHECK_FAILED
A check preflight completed, but one or more checks failed or --strict rejected a warning. The command never starts a tune.
EXIT_FAILURE
A setup problem (bad flags, an unreadable config file, a database error, an unexpected driver error) prevented the command from running to completion at all. Equal to ExitCode::FAILURE.
EXIT_POOR_QUALITY
A tune/simulate run was aborted because a driver reported a non-Good OPC quality for a tuning-critical reading (finding 5 of the live-plant safety review): an initial reading, the transition-to-manual setpoint capture, or an in-flight PV poll sample, and (for the in-flight case) the global Config > OPC quality policy rejected Uncertain, or the quality was Bad rather than merely Uncertain. The loop was restored to its pre-test mode, exactly like EXIT_ABORTED/EXIT_TIMED_OUT. Distinct from both so a scheduler’s alerting can tell “the plant data itself couldn’t be trusted” apart from a user-initiated stop or a run that simply took too long. See commands::tune::TuneOutcome::PoorQuality and AGENTS.md’s safety-quality section.
EXIT_RESTORE_INCOMPLETE
A tune/simulate run ended (via normal completion, Ctrl+C, or a timeout) without being able to confirm the loop was fully restored to its pre-test mode/MV/setpoint – either a second Ctrl+C was received while the restore was in flight, or [tuning].restore_timeout_secs elapsed first. Distinct from every other exit code because it means the loop may have been left mutated with no further attempt made to fix it: an operator must check it by hand, using the tag/value named in the warning printed to stderr. See commands::tune::TuneOutcome::RestoreIncomplete and AGENTS.md’s safety-cancellation section.
EXIT_SUCCESS
Process exited normally, and if this was tune/simulate, any PID write-back either succeeded or was cleanly skipped. Equal to ExitCode::SUCCESS.
EXIT_TIMED_OUT
A tune/simulate run was aborted because [tuning].timeout_secs elapsed before the engine reported completion; the loop was restored to its pre-test mode, exactly like EXIT_ABORTED. Distinct from it so a scheduler’s alerting can tell “this run had to be killed for running too long” (possibly a stuck relay, a misconfigured tag mapping, or a stalled driver read – worth investigating) apart from “an operator stopped it on purpose” (routine). See commands::tune::TuneOutcome::TimedOut and AGENTS.md’s cli-safety section.
EXIT_WRITE_BACK_FAILED
A tune/simulate run completed the MRFT test itself, but writing the selected PID constants back to the DCS failed (the write was rejected, errored, or its confirmation readback didn’t match). Distinct from both EXIT_SUCCESS (nothing to report) and EXIT_FAILURE (the test itself never produced a result) so an unattended --write-pid/--yes run can tell “the test ran fine but the loop was NOT updated” apart from either of those. See commands::tune::TuneOutcome and AGENTS.md’s cli-automation section.

Functions§

run
Parses real CLI arguments, initializes structured logging, and runs, returning a process exit code.