Three ways to get my Perdix 2 into Subsurface. Two of them are broken.

A reader emailed to ask for a few of my Perdix 2 dives alongside their Subsurface versions. I had written a whole post about what Subsurface’s UDDF exporter writes, and I had never put my dives through Subsurface. So I tried, on a Mac with Subsurface already installed and Shearwater Cloud 2.12.10 holding 146 of my dives.

Subsurface has three ways in for a Shearwater computer: open Shearwater Cloud’s database, import Shearwater Cloud’s XML export, or download straight from the computer over Bluetooth. The first two are broken, for reasons that have nothing to do with each other. The third works, once you have a build from after June 2025.

Opening the Shearwater Cloud database imports nothing

Shearwater Cloud keeps everything in a SQLite file called dive_data.db, and Subsurface can open it as a log file. I opened a copy of mine in Subsurface 6.0.5404 and again in 6.0.5771, a nightly from 23 October 2026. Both opened the file, reported no error, and showed an empty dive list. The window title said (0 dives).

Subsurface reads that database with SQL. It gets the list of dives by joining dive_details to dive_logs (line 501), and the samples from dive_log_records (line 346). Here is what my database holds:

tablerows
dive_details146
log_data146
dive_logs0
dive_log_records0

The two tables Subsurface needs are empty. Cloud keeps each dive whole in log_data, as a compressed blob of the records the computer wrote, and decodes it when it needs to show you something. With no rows to join, Subsurface’s query returns no dives, and it says nothing because nothing went wrong from its point of view.

This is known. A user reported it in September 2023 with Shearwater Cloud 2.10, and a maintainer reproduced it with their logs: “the import ‘succeeds’ without an error message, but no dives are imported.” An April 2026 issue found the same empty tables and proposed reading the blobs in log_data instead, which is the format I decode with pnf. It’s still open.

Importing Cloud’s XML export dates every dive 1 January 1970

Shearwater Cloud can export a dive as XML, and Subsurface imports that with a stylesheet, xslt/shearwater.xslt. I imported four exports. Subsurface loaded all four, at the right depths, and listed every one as starting on 1 January 1970. The 101 minute dive was listed as 1694:27 long. That column is hours and minutes.

Three separate things go wrong, and Cloud’s code shows all three. The macOS app is built with Unity, and its exporter is a .NET class, ShearwaterXMLExporter, which decompiles cleanly. The relevant lines are these:

startDate = divelog.DiveLogDetails.DiveDate.ToString(),
maxTime = diveLogFooter.DiveTimeInSeconds,
currentTime = (int)UnitConverter.SecondsToMs(diveLogSample.TimeSinceStartInSeconds),

The date. DateTime.ToString() with no format string uses whatever date format the computer’s region setting asks for. My Mac’s region is India, so my exports say 27-09-2025 11:55:43. Subsurface’s date template (convertDate) expects an English month name, Jan to Dec, as the second word. Given my format, it produces date="--", and Subsurface shows that as the start of 1970. Someone with a different region setting would get a different string from the same code, so no single parser can read these dates reliably.

The sample times. Cloud writes each sample’s time in milliseconds. In 2020, after noticing that Cloud’s exports had moved to milliseconds, Subsurface added a check whose commit message is honest about it: “Taking a wild guess, that this logic should suffice for us to be able to import old and newer XML logs. (Assuming that if the timestamp for the first sample is more than 100, timestamps are in milliseconds, otherwise in seconds.)” In all 142 of my exports, the first sample’s time is 0. So the check decides the file is in seconds, the sample at 10,000 ms becomes 10,000 seconds, and every time in the dive is 1,000 times too large. That’s how a 101 minute dive becomes 1,694 hours. The stylesheet also labels maxTime as minutes, so the dive’s header duration reads 6087 min, when Cloud wrote it in seconds.

The encoding. Every export starts with <?xml version="1.0" encoding="utf-16"?>, and every byte after it is UTF-8. The exporter serialises into a .NET StringWriter, which always reports UTF-16, and then saves the string with File.WriteAllText, which writes UTF-8. On macOS, libxml prints “Document labelled UTF-16 but has UTF-8 content” and carries on. A Fedora user’s import failed outright because of it.

A maintainer closed that Fedora issue on 17 October 2026 as a Shearwater bug, and mentioned the date problem too: “Shearwater appears to have changed date/time encoding in their exporter without bumping the format version, which causes wrong dates/durations even after the encoding is fixed”. The export does still say version="3". The date and encoding defects are Shearwater’s to fix. The first-sample check and the maxTime label are Subsurface bugs. The sample times would come out right on these files if the check looked at the second sample instead of the first.

Bluetooth works, after June 2025

Subsurface’s third route is the one most divers use. It downloads straight from the computer over Bluetooth, through libdivecomputer, which decodes the computer’s records itself and never touches Shearwater Cloud.

On 6.0.5404, it failed. The Perdix showed up in the scan, and my download attempts ended with “Unable to open” and a red banner saying “Timeout while trying to connect”. I turned on the libdivecomputer log, and on one attempt it showed the connection had worked. Subsurface asked the Perdix for its serial number and got A823C228. Then it asked for the firmware version:

Read: size=22, data=010001FF10006280115631303220436C6173736963C0
ERROR: Unexpected packet size (12 bytes).
ERROR: Failed to read the firmware version.

The bytes 5631303220436C6173736963 spell V102 Classic. That’s 12 characters, and this build only had room for 11. Shearwater’s firmware went from version 99 to version 100 in 2025, the string grew by a digit, and every Perdix 2 that updated stopped downloading into Subsurface.

A Perdix 2 owner reported it on 15 June 2025. Jef Driesen, who maintains libdivecomputer, explained it: “The firmware version is reported as the string “V100 Classic”. Because the version jumped to V100, this string became one digit longer than previous versions.” His fix accepts a variable length, and a fixed Subsurface build was out on 20 June. My 6.0.5404 was built on 10 June, ten days too early. The reporter also found that after the failed firmware read, the Perdix was left in a “Wait Cmnd” state where every further attempt timed out until they restarted its Bluetooth mode, which would explain the banner I kept seeing.

On 6.0.5771, the download went through first time and brought in every dive on the Perdix, 127 logs. My Garmin Descent Mk3i went in from a folder of its FIT files, because the macOS build has no MTP support for reading the watch over USB. Subsurface merged 70 dives that both computers logged into single dives with two computers, which you can switch between on the dive’s page.

What arrives

The Bluetooth download keeps depth, temperature, NDL, time to surface, the next stop, CNS, the in-deco flag, and on rebreather dives the setpoint. It drops GF99, the computer’s deco ceiling, @+5, battery level, average ppO2, and the tissue loadings the Perdix writes into its log every four minutes, because libdivecomputer doesn’t decode them. Subsurface calculates a ceiling and GF from the depth profile instead.

If you have a Perdix 2 on current firmware and want your dives in Subsurface, download them over Bluetooth with a build from after 20 June 2025. Shearwater Cloud’s database and its XML export won’t get you there today. The complete record of every dive is in Cloud’s log_data blobs, and the open issue about reading them could use someone who has already decoded them.

Sources

Subsurface, at commit 5e7b024:

Issues: #3958 and #4788 (empty database tables), #4671 (XML encoding and dates), #4537 (firmware V100 over Bluetooth).

Shearwater Cloud 2.12.10 for macOS, ShearwaterXMLExporter in Assembly-CSharp.dll, decompiled with ILSpy. Everything else comes from my Cloud database and the libdivecomputer log of my Bluetooth download, on 24 October 2026.

参与讨论