Garmin Varia Rearvue 820 Radar development

The new Varia Rearvue 820 radar can pair in Ant+ mode and works great with the popular MyBikeRadarTraffic data field I created. But in order to access the new lateral information, one needs to have connected the sensor via the secure BLE connection instead of Ant+. This means that the BikeRadar object part of the Ant+ MonkeyC library isn't being populated at all b/c it's not using Ant+. 

I am wondering if a ConnectIQ app or data field can intercept/access the BLE data coming from the Rearvue when it is connected via Bluetooth instead of Ant+. My guess is that it cannot, but I am wondering if there are any Garmin developers who could put this on their roadmap to extend the BLE library https://developer.garmin.com/connect-iq/api-docs/Toybox/BluetoothLowEnergy.html in some way to make it easy to access newer devices/sensors that are paired with newer Garmin devices via Bluetooth instead of Ant+.

Garmin specifically said that third parties won't be able to access the new lateral data (presumably b/c they aren't sharing the "secure" Bluetooth credentials you would need). I would like to propose that Garmin allow us Connect IQ app developers to access this extra info via some sort of Bluetooth extension to the SDK either specifically for the new Reavue 820 radar or for any of the likely upcoming BLE connected sensors (rather than Ant+). The app shouldn't be involved with the pairing at all since the Garmin device is already managing pairing with the new BLE sensor (e.g., Rearvue 820 radar). It should just be able to access the data coming from the sensor.

I would really like to extend my data field to record the "history" of what cars behind the rider are doing including what position within the lane and how close they are laterally at the last reading (when they pass). But even if that is not possible, I want my data field to work when a user pairs the radar via bluetooth instead of via Ant+. Thanks in advance for any tips, or pointers in the right direction, or for committing to put this on the development roadmap for the Connect IQ SDK.

  • In general, things like this are only available to companies that Garmin works with at some level and are only available to a limited number, even then.  You can tell by the email form you had to fill out with things like:


    Company Information:

    Brief Business Description:


    Product desired for integration with radar:

    -------

  • Hi all,

    I've been capturing raw BLE notifications from my RearVue 820 with an Android app I'm writing (eventually open source: on-phone radar overlay plus a Home Assistant bridge). The legacy 1 + 3*N threat format from harbour-tacho decodes cleanly on the 820, but every capture also contains a second stream that doesn't fit it.

    These packets are always exactly 6 bytes. Byte 0 is always 0x06, byte 2 is always 0x05, bytes 3 and 4 are always zero. Byte 1 cycles through four low values (0x30, 0x34, 0x38, 0x3c) with bit 7 toggling every single packet, and byte 5 is a variable number in the ~2..56 range. They arrive at roughly 1 Hz and appear even when no vehicles are present.

    A real 8-packet run from this evening's ride:

      06 30 05 00 00 05
      06 b0 05 00 00 09
      06 34 05 00 00 0a
      06 b4 05 00 00 0b
      06 38 05 00 00 0c
      06 b8 05 00 00 0e
      06 3c 05 00 00 14
      06 bc 05 00 00 17

    Byte 1 advances through all four "sectors" twice (once with bit 7 clear, once with it set), and byte 5 climbs monotonically as something approaches. Full sweep = 8 packets / ~8 seconds.

    My working guess: bits 2-3 of byte 1 are a sector index across the new 60° beam (the four masked values 0x30/34/38/3c = 48/52/56/60 in decimal, matching the documented beam width), bit 7 is a band selector (the 820 is the first Varia with both 24 GHz and 60 GHz V-band radar), and byte 5 is the return amplitude for that (sector, band) pair. That would give you exactly the raw signal you'd need to derive the 820's new vehicle-size and lane-position features downstream.

    Two questions for anyone else capturing the 820:

    1. Do you see the same 6-byte stream? Any firmware version differences?
    2. The reviews mention a "secured Bluetooth" channel for the new features. In my captures everything arrives on characteristic 6a4e3203 (even legacy threats, which harbour-tacho says should be on 6a4e3204). Is there a separate secured characteristic I'm missing, or has the 820 consolidated?

    Happy to share the raw capture logs and the Python decoder. Thanks to  and Wunderfitz for the prior work this all builds on.

  • I am seeing that same "second stream" of data interleaved. I've uploaded a screenshot from my log as an example b/c otherwise it will get flagged as spam/abusive by Garmin's automod system. Also, the 13 byte streams are presumably from four different vehicles on the radar during those readings. But my speed byte is always zero. Are you actually seeing legitimate speed readings? Or are you having to calculate based on change in distance?

  • Good to hear you see the same stream,  . A few updates from my end since the last post.

    On the speed byte being zero. Confirmed on my side too. Across three commute captures (28,690 valid vehicle entries on 6a4e3203) byte[2] of each 3-byte vehicle record is 0 in 96.87% of samples and 1 in the remaining 3.13%.
    No other values ever appear. Whatever that byte is, it isn't a
    metres-per-second speed - a car approaching at 30 mph would be ~13 m/s, which we'd see as 13, not 0 or 1. My current best guess is some kind of approaching/stable flag. Real velocity lives elsewhere - see below.

    On 6a4e3204 vs 6a4e3203. I got 3204 streaming today from a regular Android app (the app I am developing), no partner programme and no ConnectIQ involvement. Prerequisite on the phone is an established LE Secure Connections bond with the radar - once that bond exists, the characteristic is gated by a specific pre-handshake sequence that looks like "modern-central detection":

    Before opening the AMV session on 2821/2811, you have to do a standard BLE Battery Service READ on 0x2a19 and enable notifications on its CCCD. If you skip those two ops, the AMV handshake still completes successfully but the radar keeps streaming 3203 (V1) and 3204 stays silent. Once you include them,
    3204 starts flowing within ~100 ms of enabling its CCCD.

    Sequence I'm running (verbatim from an HCI snoop of a working reference client):

    1. connect (LESC bond must already exist phone-side)
    2. requestMtu(247)
    3. discover services
    4. CCCD-indicate on 2f11, CCCD-notify on 2811
    5. READ 0x2a19                    <-- the missing gate
    6. CCCD-notify on 0x2a19          <-- the other half of the gate
    7. AMV session open on 2821 (dynamic prefix bytes from the enumerate reply)
    8. READ 2a24 (model) -> CCCD-notify on 3204 -> READ 2a26 (firmware)
    9. 3204 notifications start


    Important detail on CCCDs: the reference client never writes the 3203 CCCD during a successful V2 session. Subscribing to 3203 early looks like it signals a legacy V1 client to the firmware and pins the radar into V1 mode. I defer that one.

  • What 3204 actually carries. Independent decode by rale
    (github.com/rale/radarble, the README has the byte layout — no licence on the repo so I reimplemented from the format description only). Each notification is [2-byte LE header] + N * [9-byte target struct]:

    byte 0    uint8   targetId      radar-assigned track ID
    byte 1    uint8   targetClass   enum: HIGH=36, NORMAL=23, NORMAL_STABLE=26,
                                           LOW=16, LOW_STABLE=13, UNKNOWN=4
    bytes 2-4 24-bit BE packed:
              top 13 bits  signed   rangeY  x0.1 m  longitudinal distance
                                              (~ +/- 409 m range)
              bottom 11 bits signed rangeX  x0.1 m  lateral offset
                                              (~ +/- 102 m range, +ve = right)
    byte 5    uint8   length        x0.25 m
    byte 6    uint8   width         x0.25 m
    byte 7    int8    speedX        x0.5 m/s  lateral velocity
    byte 8    int8    speedY        x0.5 m/s  longitudinal, +ve = approaching

    Header bits I've seen so far: bit 0 = status/ack frame (no targets), bit 2 = device-status frame (no targets). Everything else is a target-bearing frame with N = (payload_len - 2) / 9 targets.

  • All my indoor captures are 2-byte empty heartbeats (no targets), so I can't validate the decoder against a real vehicle until I ride with it. But the layout matches rale's notes and decodes without signed-bit errors on synthetic frames.

    So I'd rephrase the earlier "secured credentials" framing: 3204 isn't behind Garmin partner keys, it's behind (a) an LESC bond and (b) the pre-handshake battery dance above. Happy to share the decoded HCI snoop and the Python decoder if that helps — will publish the Android app as open source once I've got a road capture to confirm the decoder on real vehicles.

     Happy to share the decoded HCI snoop and the Python decoder (decode_3204.py, stdlib only) with anyone who wants to cross-check. Two open questions I'd welcome input on:

    1. Has anyone captured 3204 with actual vehicle targets? Every frame I've seen indoors is a 2-byte heartbeat, so the per-target decoder is only validated against synthetic frames so far.
    2. Does anyone have a confirmed interpretation of 3203 byte[2]? My best guess is an approaching/stable flag but I can't rule out something more interesting.

    Plan from here: Android overlay app going open source once I've got a road capture that confirms the 9-byte target decode on real traffic. Will link back when it's up.

    (Aside for any Android devs in the thread: if you've hit SMP issues establishing the LESC bond from a non-system app on recent Android versions, drop me a note — curious whether what I'm seeing is Pixel-specific or wider.)

  • Yes if you could share your decoder ... I'm probably going to convert it to Swift and try the pre-handshake battery strategy formula to see if I can messages on the 3204 characteristic and will definitely try it on my next ride (likely Monday at earliest before I can get the code in place). 

  • Pushed everything to a public repo: https://github.com/partymola/bike-radar-docs

    • PROTOCOL.md writes up the full wire format for both the V1 stream on 6a4e3203 and the V2 stream on 6a4e3204, plus the "Unlocking V2" section with the LESC bond + Battery Service pre-handshake that seems to gate V2 emission on the RearVue 820.
    • Reference decoders in Python (stdlib-only) and Kotlin (pure JVM, no Android imports), with unit tests on both sides.
    • samples/3203-sample.log and samples/3204-sample.log are scrubbed captures from my 820 you can feed straight into the decoders.

    GPLv3 licence. Happy for corrections / feedback if anything looks off on your device. Good luck with the Swift port.