BM Sensor Integration - SDI-12 Multiparameter Sonde EXO3s

Connecting the Dev Board to the Spotter

Spotter + Dev board Setup

I disconnected to 24V power supply to the Dev Board stack and instead wired it to the spotter using the 2 conductor cable.
To set up the Spotter, I needed to adjust some configurations to ensure it could continuously power the Dev board stack for development purposes.

Screened into the Spotter via pyserial-miniterm and viewed the configs by typing bm cfg status 0 s (0 is the node ID) –

bm cfg status 0 s
Succesfull status request send
2024-11-04T19:17:56.179Z [BRIDGE_CFG] [INFO] Response msg -- Node Id: 0000000000000000, Partition: system, Commit Status: 0
2024-11-04T19:17:56.179Z [BRIDGE_CFG] [INFO] Num Keys: 15
2024-11-04T19:17:56.179Z [BRIDGE_CFG] [INFO] Key 0: bridgePowerControllerEnabled
2024-11-04T19:17:56.179Z [BRIDGE_CFG] [INFO] Key 1: sampleIntervalMs
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 2: sampleDurationMs
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 3: dfu_confirm
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 4: subsampleIntervalMs
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 5: subsampleDurationMs
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 6: subsampleEnabled
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 7: alignmentInterval5Min
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 8: samplesPerReport
2024-11-04T19:17:56.183Z [BRIDGE_CFG] [INFO] Key 9: transmitAggregations
2024-11-04T19:17:56.187Z [BRIDGE_CFG] [INFO] Key 10: currentReadingPeriodMs
2024-11-04T19:17:56.187Z [BRIDGE_CFG] [INFO] Key 11: softReadingPeriodMs
2024-11-04T19:17:56.187Z [BRIDGE_CFG] [INFO] Key 12: rbrCodaReadingPeriodMs
2024-11-04T19:17:56.187Z [BRIDGE_CFG] [INFO] Key 13: ticksSamplingEnabled
2024-11-04T19:17:56.187Z [BRIDGE_CFG] [INFO] Key 14: turbidityReadingPeriodMs
2024-11-04T19:17:56.195Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 0
2024-11-04T19:17:56.203Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 3600000
2024-11-04T19:17:56.210Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 310000
2024-11-04T19:17:56.214Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 0
2024-11-04T19:17:56.222Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 60000
2024-11-04T19:17:56.230Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 30000
2024-11-04T19:17:56.238Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 0
2024-11-04T19:17:56.242Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 1
2024-11-04T19:17:56.250Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 1
2024-11-04T19:17:56.257Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 1
2024-11-04T19:17:56.261Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 60000
2024-11-04T19:17:56.269Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 500
2024-11-04T19:17:56.277Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 500
2024-11-04T19:17:56.281Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 0
2024-11-04T19:17:56.289Z [BRIDGE_CFG] [INFO] Node ID: 0000000000000000 Partition: system Value: 1000

We need to set bridgePowerControllerEnabled to be 0 to constantly power the dev board stack -
bm cfg set 0 s u bridgePowerControllerEnabled 0

Retrieving raw data

I used the curl command to query raw data from the API

curl "https://api.sofarocean.com/api/raw-messages?spotterId=SPOT-30824C&startDate=DATET00:00:00Z" -H 'token: YOUR-API-TOKEN' | jq .

I installed the jq package to display the raw data in a more readable format. Fill out the YOUR-API-TOKEN and DATE before running this command.

Raw data from the BM payload will have a header de and an example will look like this —

{
        "momsn": null,
        "transmitTime": "2024-11-04T18:40:51.000Z",
        "approxLon": "-122.39",
        "approxLat": "37.79",
        "cep": null,
        "message": "de672915349f7ca0123536d80006d40000caf3e2ef0ef2e488fabb7c18ba49a54185ebd1407b14e640b81ec7c1c375cd421f851341713d064148e19a3f3d0a573e85eb4141ee7ca5417b14ce40f628e4405c8facc1a470cd421f85134152b8024148e19a3f6210583e85eb4141fca9a541ae47c9400ad7e3406666a8c1c375cd42295c13419a990d41f6289c3fac1c5a3e85eb4141",
        "createdAt": "2024-11-04T18:41:13.396Z",
        "messageHeader": 222,
        "counter": null,
        "partNo": null,
        "processed": true,
        "commSource": "cellular",
        "processingSource": "embedded"
      }

Here the raw data is de672915349f7ca0123536d80006d40000caf3e2ef0ef2e488fabb7c18ba49a54185ebd1407b14e640b81ec7c1c375cd421f851341713d064148e19a3f3d0a573e85eb4141ee7ca5417b14ce40f628e4405c8facc1a470cd421f85134152b8024148e19a3f6210583e85eb4141fca9a541ae47c9400ad7e3406666a8c1c375cd42295c13419a990d41f6289c3fac1c5a3e85eb4141

Decoding the raw data

I made a simple script to interpret and decode the raw data. Here is the script - exo3_sdi12_decoder.py.
I have an example raw data stored in a variable called payload in the script. The raw data is decoded and displayed –

(bristlemouth) uma@Umas-MacBook-Pro-2 sdi12_example % python3 exo3_sdi12_decoder.py
- Detection data:
	temp_sensor: 22.9689998626709
	sp_cond: 5.769999980926514
	pH: 7.090000152587891
	pH_mV: -19.649999618530273
	dis_oxy: 103.73999786376953
	dis_oxy_mg: 8.899999618530273
	turbidity: 13.399999618530273
	wiper_pos: 1.2100000381469727
	depth: 0.30399999022483826
	power: 12.119999885559082
---------------------------------

- Detection data:
	temp_sensor: 22.97800064086914
	sp_cond: 5.829999923706055
	pH: 7.090000152587891
	pH_mV: -19.670000076293945
	dis_oxy: 103.73999786376953
	dis_oxy_mg: 8.899999618530273
	turbidity: 13.220000267028809
	wiper_pos: 1.2000000476837158
	depth: 0.30399999022483826
	power: 12.119999885559082
---------------------------------

- Detection data:
	temp_sensor: 22.98699951171875
	sp_cond: 5.650000095367432
	pH: 7.090000152587891
	pH_mV: -19.579999923706055
	dis_oxy: 103.7300033569336
	dis_oxy_mg: 8.899999618530273
	turbidity: 13.619999885559082
	wiper_pos: 1.2100000381469727
	depth: 0.3050000071525574
	power: 12.119999885559082
---------------------------------
5 Likes