| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| README.md | < 19 hours ago | 27.5 kB | |
| ultimate2subsurface-0.5.tar.gz | < 19 hours ago | 649.1 kB | |
| ultimate2subsurface-0.4.tar.gz | 2026-11-04 | 526.7 kB | |
| Totals: 3 Items | 1.2 MB | 1 |
Converting Huawei Dive Logs
This project reads dive data from a Huawei Health export and writes one XML
file per recognized dive for Subsurface. The exports examined so far come from
a Huawei Watch Ultimate 2. Huawei's format is not officially documented; the
information below is based on the sample files in
testdata/ and on the converter implementation. Unknown
fields and event codes may have different meanings.
Converter version: 0.5
Authorship and disclaimer
Copyright (c) 2026 Hannes Krueger. The converter was developed with assistance from OpenAI's ChatGPT. Huawei and Subsurface are respective third-party trademarks and products.
This software is provided under the MIT License, without warranty of any kind. Dive-computer exports and their interpretation may contain missing, incorrect, or misunderstood data. Review imported dives and verify critical information against the original dive computer and other reliable records. Do not use this converter or its output for dive planning, decompression decisions, or other safety-critical purposes.
Usage
Obtaining the Huawei Health JSON Export
- Synchronize the Huawei Watch Ultimate 2 with the Huawei Health app.
- Allow the Huawei Health app to synchronize the watch data with Huawei's servers.
- In Huawei Health, use Privacy management to request a copy of your Huawei Health data.
- Huawei prepares the export for download. It usually becomes available about one day after the request; the dive data is therefore not available immediately after a watch-to-app sync.
- Download and extract the archive. The dive records used by this converter
are in
Motion path detail data & description/, in a file named likemotion path detail data*_0.json.
The archive contains many other health and sports data files. The converter can read the motion-path JSON file directly; the whole archive is not needed.
python3 huawei_dives_json_to_subsurface.py \
-o subsurface-export \
'testdata-huawei-health-export/Motion path detail data & description/motion path detail data*.json'
For command-line options and supported event rules, see the converter.
The motion-path dive records contain no surface air-pressure or verified
dive-site-altitude field. The broader archive can contain independent health
detail records of type 200003 with key ALTITUDE, but Huawei's field
description gives no unit or link to a dive. Around the 1 November dives, these
readings jump between different values and include a negative sentinel, so
they are not currently reliable enough to populate a dive's altitude. For
altitude dives, such as dives in mountain lakes, enter the site altitude
manually in Subsurface.
Huawei Format Documentation
Export File and Records
In the examined export, the file
Motion path detail data & description/motion path detail data*_0.json
contains a JSON array of sports records. A record includes fields such as:
| Field | Observed meaning |
|---|---|
startTime, endTime |
Start and end times as Unix timestamps in milliseconds |
timeZone |
Record's time-zone offset, for example +0200 |
type, subType |
Huawei record/sport identifiers; dive sport type is 291 |
deviceCode, recordId, dataId |
Device and record identifiers |
summaryData |
A JSON object stored as JSON text in the outer JSON |
detailData |
A time series stored as text, with one tp=... line per sample/event |
The converter identifies dives by sportType == 291 in summaryData, or by
certain dive fields in summaryData.mExtendTrackDataMap (for example,
divingMode, divingTime, or avgDepth). The export file may also contain
records for other sports or detail types. Free diving is identified by
sportType == 287. Huawei's sport-type table also lists 288 as
breath-hold training and 289 as a breath-hold test; neither appeared in the
examined archive.
Detail Data (detailData)
Each line contains a tp type and semicolon-separated key-value pairs. The
export contains the following types; current interpretation status is shown:
| Type | Fields / interpretation |
|---|---|
tp=alti |
Dive depth profile. k is a Unix timestamp in milliseconds; v is depth in metres. Huawei's generic field sheet calls this altitude. |
tp=ext |
Extended samples. k is an index or time value (not fully determined); timeStamp is a Unix timestamp in milliseconds. tem is water temperature in °C, po2 is PPO₂ apparently stored in hundredths of a bar (for example, 164 = 1.64 bar), cns is CNS percentage, and cel is the decompression ceiling in metres. tp=ext samples are matched to depth samples by time; differences of up to two seconds are accepted. |
tp=h-r |
Huawei documents heart-rate samples: k is exercise time in minutes and v is heart rate in beats per minute. This tag was not present in the examined dive profiles. |
tp=msg |
Dive events. t is a Unix timestamp in seconds. Huawei codes ty, e, id, msid, and msty are not generally documented; their meanings are used only where they have been investigated in this project. |
tp=sec |
Summary/configuration block with fields such as sn, sdmv (maximum depth in decimetres), sdut (duration in seconds), and sdbt (meaning unknown; -1 in the freediving sample). May contain an smap object. |
tp=rs |
Huawei's Motion path field description calls this real-time speed: k is elapsed exercise time in seconds and v is signed speed in dm/s. Negative values indicate descent and positive values ascent. The converter parses the samples and reports their range in the console, but does not export them because Subsurface has no vertical-speed sample field. |
tp=i-h-r |
Has k and v; all observed values are -1, so no usable measurement has been identified. |
The converter accepts tp=ext temperatures from -2 °C to 40 °C. It drops a
single first temperature reading when it differs by more than 3 °C from the
median of the next ten valid readings (with at least five valid readings
available). This handles observed startup outliers while allowing plausible
zero and sub-zero water temperatures.
The generic Huawei field description calls tp=alti altitude recorded every
five seconds. In the examined dive records, the same tag contains the depth
profile, with millisecond timestamps and typically one-second samples. The
converter interprets it as depth in the dive-record context.
For tp=msg, a gas change with ty=0, id=24, and a gas=O2/He field has
been confirmed (for example, 16/51 for Trimix 16/51). Values 3 and, for
warnings, 2 have been observed for e. Other event codes have not been
reliably interpreted and are not treated as confirmed Huawei events.
For id=13 and id=14 high and low PPO₂ warnings, respectively, a present
po2 field is divided by 100 and shown in bar (for example, 9 becomes
0.09 bar).
The 1 November 2026 export records id=6 and id=7 with ty=0,e=1,
identified as depth and time reminders. A real dive on 8 November 2026
confirmed the 15 m depth reminder (id=6) and 30-minute time reminder
(id=7) in the log. The same dive also contained a second id=7 event at
20 minutes; it was not configured, and the diver does not recall a device
display at that time. An unremembered display is possible, but the reason for
this event is unknown.
The diver confirmed that all eight tp=msg events in the 8 November real-dive
record were correctly captured. They include the depth and time reminders,
an NDL reminder (id=25), deco start (id=2), decostop start (id=4),
missed decostop (id=12), and a marker (id=23). This provides real-dive
confirmation for these observed event labels and for the event mappings
already listed above.
Two additional warnings were configured on the watch for that dive: depth
30 m and elapsed time 1:00:00. The diver confirms both warnings appeared on
the watch underwater, at 30 m and exactly one hour, respectively. They used
audible and vibration alerts and displayed the depth or time in red. The
reminders used yellow display text. Neither warning appears in the dive's
tp=msg events. The JSON has a depth profile
reaching 41.7 m and continues beyond one hour, so both warning conditions
occurred during the recorded profile. No corresponding warning is present in
the other detailData blocks or summaryData either. This suggests that the
watch did not include these warnings in this export, but the cause is unknown;
unfinished watch software is only a hypothesis, not an established
explanation.
Huawei event timestamps up to 15 minutes before the first depth sample are
included at profile time 0:00. The watch can begin recording depth after the
dive has already started. The original local timestamp and offset are retained
in the dive notes. Events earlier than that allowance, or after the final
depth sample, are excluded and counted in the notes; these may be stale or
belong to another session. Excluded events are also listed in the converter's
console output with their local timestamp, offset from the profile, and decoded
label. Negative event times are avoided because Subsurface import behavior for
them has not been confirmed.
For the 18 October 2026 record, 17 events are timestamped several days before the profile. One unconfirmed explanation is that they were generated while testing dive mode in simulations that were not logged, then retained by the computer and included in the next recorded dive. This has not been verified.
The 8 November 2026 dive confirms the watch displays reminders in yellow and
warnings in red, with audible and vibration alerts for the configured depth
and time warnings. The logged reminders have e=1. Because the two warnings
were absent from the JSON, their event codes and any relationship between
warning display color and e remain unknown. Earlier proposed mappings of
e=3 to reminder and e=2 to warning are not confirmed.
The converter also maps the following id values to event labels. These are
project observations/configured mappings, not an official Huawei code table;
the rules match on id alone and retain any ty and e values in the
exported bookmark for context.
id |
Label used by the converter |
|---|---|
2 |
Deco start |
4, 5 |
Decostop start / end |
6, 7 |
Reminder depth / time |
10, 16 |
CNS reminder / warning |
12 |
Missed decostop |
13 |
High PPO₂ warning |
14 |
Low PPO₂ warning |
17–20 |
Stopwatch started, paused, continued, reset |
21, 22 |
Compass direction set / cleared |
23 |
Marker |
25 |
NDL reminder |
msty separates communication event categories: msty=1 is an emoji,
msty=2 an SOS event, and other/missing values are treated as text messages.
All observed sent messages and emojis use id=26; received SOS events and
ordinary received text messages use id=27. Two ordinary received messages
tested during the simulated (“fake”) dive on 7 November 2026 confirmed that
id=27 marks received messages. The converter therefore labels id=26
events as sent and id=27 events as received. It applies the same msid
labels to received text messages as to sent text messages. Received emojis
have not yet been confirmed, so applying id=27 to that category remains
provisional.
The converter's currently known msid labels are listed separately below.
For recognized events, id, ty, and e are retained in the exported
bookmark, even when the label is recognized. For messages and emojis, these
codes are not used to look up the label. The current export has ty=6 and e=4
for all observed text messages and emojis. These are observed values, not
confirmed invariants for every Huawei export. — means that the field is not
used for that mapping.
Text messages
id |
msty |
msid |
ty |
e |
Text message |
|---|---|---|---|---|---|
26 |
0 |
1 |
6 |
4 |
Follow your buddy |
26 |
0 |
2 |
6 |
4 |
Follow instruction |
26 |
0 |
3 |
6 |
4 |
Check SPG |
26 |
0 |
4 |
6 |
4 |
Do safety stop |
26 |
0 |
5 |
6 |
4 |
Boats, watch out |
26 |
0 |
6 |
6 |
4 |
Ascend in 1 min |
26 |
0 |
7 |
6 |
4 |
Feeling unwell |
26 |
0 |
8 |
6 |
4 |
Come to me |
26 |
0 |
9 |
6 |
4 |
Take a photo |
26 |
0 |
10 |
6 |
4 |
Avoid kicking |
26 |
0 |
11 |
6 |
4 |
Stick close to me |
26 |
0 |
12 |
6 |
4 |
Keep an eye on me |
26 |
0 |
13 |
6 |
4 |
Guideline!! |
26 |
0 |
14 |
6 |
4 |
Abort the dive |
26 |
0 |
15 |
6 |
4 |
I'm hypothermic |
26 |
0 |
16 |
6 |
4 |
Calm down |
26 |
0 |
17 |
6 |
4 |
Call for help |
26 |
0 |
18 |
6 |
4 |
Need doco gas |
26 |
0 |
19 |
6 |
4 |
Deco done |
26 |
0 |
20 |
6 |
4 |
Loop flooded |
26 |
0 |
21 |
6 |
4 |
Switching to BO |
26 |
0 |
22 |
6 |
4 |
I'm not OK |
26 |
0 |
23 |
6 |
4 |
Watch CO2 |
26 |
0 |
24 |
6 |
4 |
I need help! |
26 |
0 |
25 |
6 |
4 |
I'm OK now |
26 |
0 |
26 |
6 |
4 |
Are you OK? |
26 |
0 |
27 |
6 |
4 |
Everything's OK |
26 |
0 |
28 |
6 |
4 |
Copy that |
26 |
0 |
29 |
6 |
4 |
STOP |
26 |
0 |
30 |
6 |
4 |
Head back |
26 |
0 |
31 |
6 |
4 |
Look up |
26 |
0 |
32 |
6 |
4 |
Look down |
26 |
0 |
33 |
6 |
4 |
I'm stuck |
26 |
0 |
34 |
6 |
4 |
Ascent to surface |
26 |
0 |
35 |
6 |
4 |
Cool stuff here |
26 |
0 |
36 |
6 |
4 |
That's cool |
26 |
0 |
37 |
6 |
4 |
Look at me |
Emojis
id |
msty |
msid |
ty |
e |
Emoji |
|---|---|---|---|---|---|
26 |
1 |
1 |
6 |
4 |
laughing |
26 |
1 |
2 |
6 |
4 |
hang loose, shaka |
26 |
1 |
3 |
6 |
4 |
steam from nose |
26 |
1 |
4 |
6 |
4 |
freezing |
26 |
1 |
5 |
6 |
4 |
persevering face |
26 |
1 |
6 |
6 |
4 |
unhappy |
26 |
1 |
7 |
6 |
4 |
thinking |
26 |
1 |
8 |
6 |
4 |
ok |
26 |
1 |
9 |
6 |
4 |
whale |
26 |
1 |
10 |
6 |
4 |
ray |
26 |
1 |
11 |
6 |
4 |
dolphin |
26 |
1 |
12 |
6 |
4 |
shark |
26 |
1 |
13 |
6 |
4 |
turtle |
26 |
1 |
14 |
6 |
4 |
octopus |
26 |
1 |
15 |
6 |
4 |
jellyfish |
26 |
1 |
16 |
6 |
4 |
prawn |
26 |
1 |
17 |
6 |
4 |
crab |
26 |
1 |
18 |
6 |
4 |
ocean sunfish |
26 |
1 |
19 |
6 |
4 |
sea snail |
26 |
1 |
20 |
6 |
4 |
seahorse |
26 |
1 |
21 |
6 |
4 |
seastar |
26 |
1 |
22 |
6 |
4 |
nemo |
26 |
1 |
23 |
6 |
4 |
water snake |
26 |
1 |
24 |
6 |
4 |
weird/unknown fish |
26 |
1 |
25 |
6 |
4 |
need to pee |
SOS events
id |
msty |
msid |
ty |
e |
SOS event |
|---|---|---|---|---|---|
26 |
2 |
1 |
6 |
2 |
SOS sent: alert/active |
26 |
2 |
2 |
6 |
3 |
SOS sent: ended / I'm okay |
27 |
2 |
1 |
6 |
2 |
SOS received: alert/active |
27 |
2 |
2 |
6 |
3 |
SOS received: ended / I'm okay |
The three gauge-mode dives recorded on 23 October 2026 contain the id=27
pairs above. They confirm that e=2 marks the received SOS alert and e=3
the received "I'm okay"/SOS-ended event; msid=1 and msid=2 distinguish
those two states in these samples. Two ordinary received text messages tested
during a simulated (“fake”) dive on 7 November 2026 independently confirmed
that id=27 marks received messages. All observed outgoing text messages,
emojis, and older SOS records use id=26. Received emojis have not yet been
tested. For SOS, the converter uses msty=2 to identify the category and e
for the state.
The SOS tp=msg lines contain only t, ty, e, id, msid, depth, and
msty. No sender code such as 4A23 or other sender-specific field was found
in these events. The record-level deviceCode identifies the recording
device, not the SOS sender, so the sender cannot be recovered from these
motion-path records as currently understood.
The tables list all message and emoji labels currently configured in the converter;
it has not been confirmed that they cover every option available on the watch.
msid values are reused between message and emoji categories, so they must be
interpreted together with msty. Unknown values are kept visible as unknown
message/emoji labels.
For id=26 and id=27, the converter includes available depth and ty/e
codes in the bookmark text. The precise meaning of ty and the general meaning
of e outside the observed SOS events remain uncertain.
The following smap keys have been observed. Meanings inferred from the single
freediving sample are marked as provisional:
| Key | Observed meaning |
|---|---|
2910001 |
Dive start time as a Unix timestamp in seconds |
2910002 |
Maximum CNS percentage |
2910003 |
OTU |
2910004 |
Gas definitions; technical mode uses O₂/He/N₂ triplets, while sport mode stores the selected O₂ percentage as one value (for example, 3200 = 32% O₂) |
2910005, 2910006 |
Minimum and maximum water temperature in °C |
2910012 |
Average depth in decimetres |
2910015, 2910016 |
Longitude and latitude |
2870001 |
Freediving segment start time as a Unix timestamp in seconds; displayed in the segment's local time in XML notes |
2870005, 2870006 |
Minimum and maximum water temperature for the freediving segment in °C, confirmed against Huawei Health |
2870008 |
Unknown; value 0 in all three freediving segments |
2870009 |
Unknown; values 2, 2, and 4 in the three segments |
2870012 |
Freediving segment average depth in decimetres, confirmed against Huawei Health |
2870013–2870016 |
Unknown; all are 360.000000 in the sample, probably unavailable/sentinel values; possibly position-related |
In the two simulated dives from 20 October 2026, both coordinate fields contain
360.000000, which is outside the valid latitude/longitude ranges and appears
to be Huawei's unavailable-coordinate sentinel. In Subsurface notes, invalid
coordinate values are shown as no valid data rather than as coordinates.
The code documents divingMode=0 as free diving, 1 as sport/recreational
diving, 2 as technical diving, and 3 as gauge mode. Observed water settings
in mExtendTrackDataMap are:
| Field | Meaning / Subsurface output |
|---|---|
waterType=0 |
Custom water. Read waterDensity in kg/L and convert it to Subsurface salinity in g/L (multiply by 1000); for example, waterDensity="1.130000" becomes salinity="1130 g/l". |
waterType=1 |
Fresh water; exported as salinity="1000 g/l". |
waterType=2 |
Salt water; exported using the conventional value salinity="1040 g/l". |
These mappings were checked against two simulated dives in the export from
20 October 2026. The 15:54 dive, configured with custom density 1.13 kg/L,
contains waterType="0" and waterDensity="1.130000" in
summaryData.mExtendTrackDataMap. The 16:02 dive, configured for seawater,
contains waterType="2" and no explicit waterDensity. The converter
therefore uses the recorded density for custom water and the conventional
1.04 kg/L value for seawater. Unknown or missing custom densities are not
guessed, so no salinity value is emitted for waterType=0 unless a valid
positive density is present.
For sport mode, a single smap[2910004] value is treated as the selected
oxygen percentage. For sport and tech diving, Air (21% O₂) is used when Huawei
provides no gas definition. Gauge and free-diving modes have no cylinder
output.
For technical dives, smap[2910004] appears to list gases used during the dive,
not every gas configured on the watch. In the 1 November 2026 technical dive,
it contains Oxygen, 17/34, and 50/19, but not Air (21/00), which the diver
believes was configured but not used. The JSON contains no explicit field for
the starting gas: the first gas in this list is not necessarily the one used
at the start, and gas-change events record later switches. A recorded PPO₂ may
be consistent with a particular gas, but it does not identify that gas
reliably. The converter uses a cautious workaround: if exactly one listed gas
has no matching gas-change event during the dive (including the accepted
pre-profile window), it moves that gas to the first cylinder position. The XML
notes mark this as an inference. If the data leaves multiple candidates,
Huawei's order is retained. This can still be wrong if Huawei includes a
configured but unused gas in the list.
During this dive the computer repeatedly displayed a “better gas: 21/00”
recommendation, including at around 40 m. The motion-path JSON contains neither
that gas in smap[2910004] nor a matching tp=msg event, so the recommendation
cannot be reconstructed from the examined record.
Freediving session sample
The 23 October 2026 export contains a record with sportType=287 (Huawei's
field-description sheet names this "Free diving") and divingMode=0. It is a
single logbook session containing three dives. The summary reports
divingCount=3, segmentNum=3, divingTime=15, underwaterTime=15, and
maxUnderwaterTime=6. The converter now names mode 0 as Free diving, but does
not yet interpret these session or segment metrics.
The record has 88 one-second depth, temperature, tp=rs, and tp=i-h-r
samples, plus three tp=sec blocks (sn=1..3). The blocks contain separate
maximum depth, duration, temperature, and probably average-depth values:
| Segment | sdmv maximum depth |
sdut duration |
2870001 timestamp |
2870012 average depth |
2870005..6 temperature |
|---|---|---|---|---|---|
| 1 | 1.3 m | 6 s | 22:38:22 | 1.1 m | 29–29 °C |
| 2 | 1.4 m | 6 s | 22:39:05 | 1.2 m | 29–30 °C |
| 3 | 1.7 m | 3 s | 22:39:29 | 1.5 m | 30–30 °C |
The 2870001 timestamps are the start times of the respective segments and
are now rendered as local date/time in XML notes, alongside the raw Unix value.
Huawei Health confirms 2870005 and 2870006 as each segment's minimum and
maximum water temperature. 2870012 is the segment average depth in
decimetres, confirmed against Huawei Health; XML notes display the value in
metres and retain the raw value. The session-level avgDepth=13 also appears
consistent with 1.3 m. The values 2870008 and 2870009 are not understood.
All 2870013–2870016 values are 360.000000; these may be unavailable
position-related values, but that is unconfirmed.
The session summary reports maxDescentSpeed=5 and maxAscentSpeed=1; their
relationship to the individual tp=rs samples is not fully understood.
tp=rs is zero in all examined scuba samples.
Freediving profile from 1 November 2026
The first dive in the 1 November export is a freedive (sportType=287,
divingMode=0) with 149 one-second depth samples and 149 tp=rs samples.
Here, tp=rs values match the vertical-speed plot in Huawei Health: at profile
time 00:05, v=-2 matches -0.2 m/s while descending; at 00:18, v=2
matches +0.2 m/s while ascending. This confirms that v is signed vertical
speed in decimetres per second (dm/s). The converter parses these values and
reports the converted range in its console output, but does not add them to the
XML because Subsurface has no field for vertical speed.
The session summary reports maxDescentSpeed=2 and maxAscentSpeed=1, while
the profile contains an ascent sample of v=2. The summary fields' exact
relationship to the sampled values remains unclear.
tp=i-h-r is -1 throughout the freediving record. The summary's
avgHeartRate=0, maxHeartRate=6, minHeartRate=0, and mAverageHangTime=-1
also do not provide plausible usable readings; their sentinel/default meanings
are unconfirmed. tp=ext contains temperature only, and there are no
tp=msg events. The current XML notes retain raw tp=sec values, but do not
yet decode the freediving session or segment summary fields.
Huawei's generic tag description defines tp=h-r as heart-rate data, but it
does not occur in the examined dive profiles. Separate Health detail records
also contain heart-rate measurements; none overlap either of the 1 November
dive intervals.
The sample exports also contain other detail-data types such as tp=i-h-r;
their meanings remain under investigation. Missing values are not replaced
with estimated measurements.
Output and Limitations
The converter writes the depth profile from tp=alti, temperature, PPO₂, and
decompression ceiling from tp=ext, gas definitions from smap, and confirmed
gas changes from tp=msg to Subsurface XML. Unknown Huawei events may be
exported as bookmarks; Huawei tp=sec and smap information is also included
in the notes. Free diving is identified, and the first multi-dive session
sample is documented above; dedicated freediving summary/segment handling and
other Huawei record types still need investigation.
Subsurface stores the dive mode on the <divecomputer> element using
dctype="Freedive"; the converter emits this attribute for Huawei
divingMode=0.
Every depth sample is written. Temperature and computer-supplied PPO₂ use
Subsurface's change-only sample attributes (temp and dc_supplied_ppo2). A
positive Huawei ceiling sets in_deco and stopdepth; when the ceiling
returns to zero, the converter clears the deco state and stop depth. PPO₂ is
exported as a dive-computer measurement because it is supplied by the watch.
The explanatory note about Huawei cel is included only when a positive
ceiling occurs in sport or technical mode; it is omitted for free diving,
gauge mode, and dives without deco.
The XML dive duration spans the full dive-mode profile, including the
configured surface interval before the computer closes the dive. Huawei
sdut is underwater time and is expected to be shorter. Per-sample CNS values
are parsed but are not currently exported as sample attributes; the summary
CNS value from smap is retained in the notes.
Decompression data: limits and observations
Huawei's JSON includes the recorded ceiling (cel) but not the Ultimate 2's
decompression model or settings, so those calculations cannot be independently
verified from the export. During the 8 November 2026 dive, the displayed
ceiling matched cel; the JSON records whole metres while the watch displayed
decimal values.
On that dive, the Ultimate 2 and OSTC2 were configured with one TMX 18/45 gas, GF 40/80, and a 6 m final stop. At about 119 minutes, the OSTC2 showed TTS 257 minutes with one 6 m stop; the Ultimate 2 showed TTS 137 minutes and a 6 m stop lasting 24 minutes. The shorter TTS may mean the Ultimate 2 included an unshown 3 m stop despite the 6 m setting. This is not confirmed. Check on further dives and report it to Huawei if confirmed. The setup had no deco gases and is not a realistic dive plan.
Surface-GF values also differed: near peak saturation, Ultimate 2 195% and OSTC2 220%; maximum recorded values were 179% and 208%, respectively. These observations do not establish which calculation is correct. Maybe this should be investigated in comaparison other implementations.