Skip to content

feat(power): expose factory default / min / max power target#292

Merged
b-rowan merged 4 commits into
256foundation:masterfrom
pos-ei-don:feat-bos-default-power-target-upstream
Jun 23, 2026
Merged

feat(power): expose factory default / min / max power target#292
b-rowan merged 4 commits into
256foundation:masterfrom
pos-ei-don:feat-bos-default-power-target-upstream

Conversation

@pos-ei-don

Copy link
Copy Markdown
Contributor

Surfaces the power target a miner ships with — plus the accepted min/max bounds. On BraiinsOS this is the value the tuner starts from: when you kick off a fresh tune, the autotuner anchors on this default power target and works out from there. Exposing it lets a UI offer the factory point as the natural starting step for a fresh (re-)tune, and present a realistic range around it instead of guessing.

  • Adds DefaultPowerTarget / MinPowerTarget / MaxPowerTarget data fields and matching Option<Power> fields on MinerData, wired in through the usual Get* traits (default to None) so every backend keeps compiling unchanged.
  • Braiins 26.04: reads bosminer.metadata.autotuning.powerTarget.{default,min,max} over the GraphQL client that's already there (unauth metadata, no extra auth path). On an S19k Pro this gives 2760 / 771 / 6435 W.
  • All other backends get trivial None impls. I only wired Braiins 26.04 because that's the firmware I can test against live; the other BOS backends expose the same GraphQL field, so mirroring it later is straightforward.

Happy to reshape this — e.g. group the three into a small struct, or fold it into the tuning/config model if that fits your direction better. Verified live against a BraiinsOS S19k Pro.

pos-ei-don and others added 2 commits June 23, 2026 03:47
BOS+ (and other firmwares) report the power-target the device ships with —
the value all tuning starts from — plus the accepted min/max. Surface it:

- Add DefaultPowerTarget/MinPowerTarget/MaxPowerTarget DataFields and the
  matching Option<Power> fields on MinerData, with GetDefaultPowerTarget /
  GetMinPowerTarget / GetMaxPowerTarget traits (default to None) wired into
  the GetMinerData supertrait + blanket impl.
- Braiins v26.04: read bosminer.metadata.autotuning.powerTarget.{default,min,max}
  via the existing GraphQL client and parse them in the new traits.
- All other backends get trivial (None) impls.
- Python bindings + stubs + interop fixture updated.
@b-rowan

b-rowan commented Jun 23, 2026

Copy link
Copy Markdown
Member

Did some talking, and I think we want to wire this up under a "new" trait subsection, MinerCapabilities. I believe the correct naming for this is TuningCapabilities, and I want to structure it as so -

struct PowerTuningCapabilites {
    default: Option<TuningTarget>, 
    minimum: Option<TuningTarget>, 
    maximum: Option<TuningTarget>
}

struct HashRateTuningCapabilites {
    default: Option<TuningTarget>, 
    minimum: Option<TuningTarget>, 
    maximum: Option<TuningTarget>
}

struct PresetTuningCapabilites {
    default: Option<TuningTarget>, 
    presets: Vec<TuningTarget>
}

struct TuningCapabilities {
    power: Option<PowerTuningCapabilites>,
    hashrate: Option<HashRateTuningCapabilites>,
    presets: Option<PresetTuningCapabilities>,
}

Per review feedback, replace the flat default/min/max power-target fields with
a structured MinerCapabilities-style TuningCapabilities, grouped by tuning
domain (power / hashrate / presets), each reusing the existing TuningTarget:

  TuningCapabilities {
      power:    Option<PowerTuningCapabilities>,    // default / minimum / maximum
      hashrate: Option<HashRateTuningCapabilities>, // default / minimum / maximum
      presets:  Option<PresetTuningCapabilities>,   // default / presets
  }

- new asic-rs-core/src/data/capabilities.rs with the four structs (pydantic-
  exposed like BoardData)
- single DataField::TuningCapabilities + GetTuningCapabilities trait replace the
  three power-only fields/traits
- MinerData.tuning_capabilities replaces default/min/max_power_target
- BraiinsV2604 fills power.{default,minimum,maximum} from the autotuning
  powerTarget metadata; hashrate/presets left for the backends that expose them
- python bindings (.pyi, data.py, module export) + interop test updated
@pos-ei-don

Copy link
Copy Markdown
Contributor Author

Done — reworked it into TuningCapabilities as you sketched, grouped by tuning domain and reusing the existing TuningTarget:

TuningCapabilities {
    power:    Option<PowerTuningCapabilities>,    // default / minimum / maximum
    hashrate: Option<HashRateTuningCapabilities>, // default / minimum / maximum
    presets:  Option<PresetTuningCapabilities>,   // default / presets
}

A couple of decisions where the sketch left room — happy to change either:

  • Value type: reused TuningTarget for the fields (matches your snippet), so a power envelope is TuningTarget::Power(..) etc.
  • Where it lives: I kept it on MinerData via a single DataField::TuningCapabilities + a GetTuningCapabilities trait, mirroring how tuning_target already works. If you'd rather have it as a standalone capabilities() call off the telemetry path, that's an easy move — just say the word.
  • Coverage: BraiinsV2604 fills power.{default,minimum,maximum} from the autotuning powerTarget metadata; hashrate/presets stay None until a backend exposes them (the presets arm lines up with the VNish work in feat(throttle): native manual throttle (SetThrottle + throttle_percent) #289).

CI is green. The three flat *_power_target fields/traits are gone, replaced by the single structured field.

Comment on lines +652 to +654
if power == PowerTuningCapabilities::default() {
return None;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think skipping this check is OK, since returning TuningCapabilities with any of the given keys helps indicate that a miner supports that type of tuning, EG we expect braiins to support power tuning.

Comment thread asic-rs-firmwares/braiins/src/backends/v26_04/mod.rs
@b-rowan

b-rowan commented Jun 23, 2026

Copy link
Copy Markdown
Member

FYI you can use the files in meta/ from the root as documentation for some of the APIs, if you feed them into your agent it should be able to implement this for most of the meta documented types.

…ault-guard

Address review on 256foundation#292:
- drop the `power == default => None` guard; presence of a populated key
  already signals which tuning types a miner supports
- shared helpers in backends/util.rs:
  - power_target_capabilities(): GraphQL `bosminer/metadata/autotuning/powerTarget`
    (power-only envelope), used by the GraphQL backends 21.09 / 25.03 / 25.05
  - tuner_constraints_capabilities(): BOS+ REST GET /configuration/constraints
    -> tuner_constraints, mapping PowerConstraints (watts) and HashrateConstraints
    (TH/s) to power + hashrate envelopes, used by the REST backends 25.07 / 26.04
- 26.04 switched from the GraphQL power-target query to the REST constraints
  endpoint, and now also reports the hashrate envelope
@pos-ei-don

Copy link
Copy Markdown
Contributor Author

Done — implemented across all BOS backends, CI green:

  • Dropped the == default guard.
  • Two shared helpers in backends/util.rs (instead of literal copy-paste): power_target_capabilities() for the GraphQL bosminer/metadata/autotuning/powerTarget path (21.09 / 25.03 / 25.05), and tuner_constraints_capabilities() for the BOS+ REST GET /configuration/constraintstuner_constraints (25.07 / 26.04), mapping PowerConstraints (watts) and HashrateConstraints (TH/s) onto the power + hashrate envelopes.
  • 26.04 now uses the REST constraints endpoint instead of the GraphQL metadata query, and reports the hashrate envelope as well.

And it's verified on real hardware, not just CI/schema: tested against my S19k Pro on BraiinsOS. I actually had to fire the miner up on battery to do it (not enough solar at the time 🙂), but /configuration/constraints matches exactly — power_target = { default 2760 W, min 771 W, max 6435 W } and hashrate_target = { default 120 TH/s, min 11.36, max 268.46 }, which is what the helper maps onto the power/hashrate envelopes.

Thanks for the meta/ schemas and the constraints.proto link — made the REST shapes unambiguous.

@b-rowan
b-rowan merged commit eabb2e3 into 256foundation:master Jun 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants