Skip to content

CCR import with two transmitters: O2 cylinder gets the diluent mix, diluent end pressure skips the surfacing trim (Shearwater) #2318

Description

@alpheios-one

Summary

On a Shearwater CCR dive with two AI transmitters (diluent + O2), the Bluetooth import assigns wrong gas mixes, wrong roles and a wrong diluent end pressure. All of it traces back to one assumption in parsed_tank_resolver.dart: that a profile sample carries at most one transmitter reading. In practice both transmitters report in the same sample, and ProfileSample.pressureBar / tankIndex only hold the last one reported (always the O2 transmitter on the Petrel 3), even though every transmitter's reading is already available in ProfileSample.tankPressuresBar (#1316).

Setup

  • Shearwater Petrel 3, CCR mode, log version 17, AI mode 5
  • Transmitter T1 named D1 (diluent), T2 named O2 (oxygen)
  • Transmitter registry entries assign role Diluent / O2 Supply
  • Enabled gases, e.g. OC1 99/0, OC5 15/55 (bailout), DIL2 15/55; the whole dive is on the loop

What happens

Decoded from the raw download of eight real dives and cross-checked against the stored cylinders and Shearwater Cloud:

Expected Imported
O2 cylinder 100/0 the diluent mix, on every dive
Diluent cylinder the breathed diluent the breathed diluent only if the O2 transmitter missed at least one sample; otherwise the first gas in the list (OC1 99/0)
Bailout gas (no transmitter) Bailout Back Gas
Diluent end pressure reading at surfacing last reading of the post-surfacing tail (e.g. 13.4 bar instead of 77.6 bar)

Per-sample "last reporter" counts show how fragile the diluent result is: across the analyzed dives the diluent transmitter was the last reporter in 0 to 23 of 289 to 805 samples. One dive got the right diluent from a single sample; the dive with zero such samples imported the diluent cylinder as 99/0.

Root causes

  1. Gas per transmitter (_resolveTankGasIndex, rule 1): the cylinder gets the gas that was active while its transmitter was the sample's tankIndex. On CCR the active gas is always the diluent, and the O2 transmitter owns almost every sample, so the O2 cylinder gets the diluent. The oxygen default added in fix(dive-log): auto-assign 100% O2 when a cylinder's role is set to oxygen supply #1972 only runs after rule 1 found nothing, so it never applies here (its test builds the dive without samples). The diluent transmitter rarely owns a sample and falls through to rule 3 (return 0), the first gas mix, which on Shearwater is OC1.
  2. Roles of gases without a transmitter: once tank records exist, synthesized cylinders use _inferRole(null, ...), which ignores GasMix.usage and the CCR bailout ranking from feat(dive-computer): rank sensorless CCR bailout gases against each other #1752 (scoped to sensorless dives only).
  3. Surfacing trim (Dive import - too long #1092 / Read cylinder end pressure at surfacing, not at the end of the recording #1290): _surfacingPoints() builds one entry per sample from pressureBar / tankIndex, so only the O2 transmitter gets a reading at surfacing. The diluent keeps its untrimmed tail value. The trim itself is correct and needed; it just never sees the diluent.
  4. Dive-level diluent (fix(dive-computer): derive the CCR diluent gas mix from the resolved Diluent cylinder #2034) is derived from the diluent cylinder and inherits its wrong mix.

Shearwater Cloud's own TankProfileData also labels every transmitter with the breathed gas (including O2), so the tank role has to come from usage / the transmitter name, not from the gas timeline.

Suggested fix

  • On a CCR dive, resolve a transmitter tank tagged DC_USAGE_OXYGEN to 100/0 (or an oxygen-tagged gas mix) before rule 1.
  • Resolve a transmitter tank tagged DC_USAGE_DILUENT to the breathed gas mix with usage == 2, never to gas index 0.
  • Attribute gas per transmitter and build surfacing points from tankPressuresBar (all transmitters per sample) instead of pressureBar / tankIndex.
  • Apply the sensorless role logic (usage, CCR bailout ranking) to gases without a transmitter as well.
  • Regression test with realistic samples: both transmitters in each sample, O2 reported last, OC1 99/0 as the first gas mix.

Related

#1092, #1290, #1316, #1752, #1879, #1972, #2034, #2224

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions