feat(unitree): forward aes_128_key to WebRTC driver for G1 firmware >=1.5.1#2117
feat(unitree): forward aes_128_key to WebRTC driver for G1 firmware >=1.5.1#2117mihai-chiorean wants to merge 8 commits into
Conversation
…=1.5.1 Unitree G1 firmware 1.5.1 added a data2=3 WebRTC handshake that requires a per-device AES-128 key (fetched from Unitree cloud once via `unitree-fetch-aes-key --email YOU --sn <serial>`). The upstream `legion1581/unitree_webrtc_connect@v2.1.1` accepts this via the `aes_128_key=` kwarg; without it the handshake fails with `RSA key format is not supported` from pycryptodome reading ciphertext bytes. `UnitreeWebRTCConnection.__init__` now accepts an optional `aes_128_key` kwarg and falls back to the `UNITREE_AES_128_KEY` environment variable so existing call sites do not need to change. When the value is unset the call to `LegionConnection` is byte-identical to the previous behaviour, so this is a no-op for G1 firmware <1.5.1 and for Go2. Verified against a Unitree G1 EDU+ on firmware 1.5.1.1 via `dimos run unitree-g1-basic` - the WebRTC handshake on 192.168.123.161:9991 succeeds with UNITREE_AES_128_KEY exported and reproduces the `RSA key format is not supported` failure without it.
|
reason for legion client fork is that unitree-webrtc-connect-leshy had a more efficinet lidar data parser and we had some issues with aiortc package pinning and had to fork it as well legion1581/unitree_webrtc_connect@master...leshy:unitree_webrtc_connect:master for FDEs (or anyone else here in the thread:) - we need to validate this on current g1s/go2s (ensure my lidar changes are now merged to legion client, transition to legion lib, test on our robots, make sure installation works, merge this) |
| self.stop_timer: threading.Timer | None = None | ||
| self.cmd_vel_timeout = 0.2 | ||
| self.conn = LegionConnection(WebRTCConnectionMethod.LocalSTA, ip=self.ip) | ||
| # Per-device AES-128 key required by G1 firmware >= 1.5.1 (data2=3 WebRTC handshake). |
There was a problem hiding this comment.
We could also include GO2 firmware 1.1.15 as it has the same issue and this should fix it for the GO2 too !
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
I did notice a degradation in navigation performance on our go2 edu when I switched to the upstream library, might be worth checking if the changes are there. |
Address PR review feedback from dimensionalOS#2117: 1. G1Config and G1HighLevelWebRtcConfig now expose 'aes_128_key' as an optional declarative config field, forwarded to UnitreeWebRTCConnection. Users on G1 firmware >= 1.5.1 can now set it via blueprint config without resorting to the UNITREE_AES_128_KEY env var. The env-var fallback in UnitreeWebRTCConnection.__init__ is preserved as-is. 2. Adds dimos/robot/unitree/test_connection.py with five test cases that cover the kwarg-forwarding logic without hardware: - default behaviour: no kwarg, no env → aes_128_key not forwarded (byte-identical to pre-PR call) - explicit kwarg is forwarded verbatim - env-var fallback when kwarg is None - explicit kwarg beats env-var (precedence) - empty-string kwarg is treated as 'no key' (truthiness guard) Tests are pure-Python: LegionConnection is mocked, .connect() is patched to a no-op. Default pytest selector (-m 'not tool ...') will run them.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
|
I Was at a hackathon, but I'll get this sorted out shortly. |
|
Thanks! @ruthwikdasyam or @Krishna can assist with any testing here |
Mirrors the G1 wiring from this PR so Go2 firmware >= 1.1.15 (same data2=3 WebRTC handshake change) can pass the per-device AES-128 key. Adds the field to Go2's ConnectionConfig, accepts it as a kwarg on make_connection, and forwards it to UnitreeWebRTCConnection in the webrtc branch. Other branches (replay, mujoco, dimsim) are unaffected. Also fixes the test docstring greptile flagged after the 'if not aes_128_key' guard landed: the test asserting empty-string + unset env → no forwarding had a misleading docstring claiming the kwarg was 'treated as no key'. Rewrites the docstring and adds a sibling test covering the case that actually motivated the guard fix: empty-string kwarg + set env → env value wins (the YAML/JSON 'aes_128_key: ""' regression case). Addresses natcl's review comment on PR dimensionalOS#2117.
|
Force-pushed
Ran the changes through @leshy — re. the upstream legion lib transition + lidar perf, leaving that for a separate PR (also flagged on this PR thread by @natcl who noticed degraded nav on Go2 EDU after the upstream switch). Happy to scope that follow-up once you confirm the lidar parser changes have landed in legion upstream. |
|
I think ideally should bump to latest unitree_webrtc_connect for this to be usable. my lidar changes have landed upstream looks like (legion1581/unitree_webrtc_connect#46) but let's still compare perforamnce between https://github.com/leshy/unitree_webrtc_connect (what we use now) and upgraded latest official unitree_webrtc_connect because of
@ruthwikdasyam has experience with lidar data profiling so can look into this. if performance is the same, we can commit a bump in pyproject to official lib and merge all together |
want me to do that here or is that for a separate PR...? happy to update it, a little worried about the blast radius of updating a package like that since I'm new to the repo. |
Greptile SummaryThis PR adds optional
Confidence Score: 5/5Safe to merge — all call sites are updated, the new kwarg is optional with a backward-compatible default, and the truthiness guard correctly handles both The change is narrow and well-contained: a single new optional parameter threads through four config classes and the connection factory, each wired consistently. The previously reported empty-string bypass was resolved before this review, and the new test suite explicitly covers that scenario along with the no-key, explicit-kwarg, env-var-fallback, and kwarg-over-env-precedence cases. There are no logic gaps or missing call sites. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Caller provides config] --> B{aes_128_key in config?}
B -- Yes --> C[Forward kwarg to UnitreeWebRTCConnection]
B -- No --> C2[Pass None to UnitreeWebRTCConnection]
C --> D{if not aes_128_key}
C2 --> D
D -- False: kwarg is truthy --> F[Skip env-var lookup]
D -- True: kwarg is None or empty string --> E[Read UNITREE_AES_128_KEY from env]
E --> G{env var set?}
G -- Yes --> H[Use env var value]
G -- No --> I[key remains None]
F --> J{Final key truthy?}
H --> J
I --> J
J -- Yes --> K[LegionConnection called with key kwarg]
J -- No --> L[LegionConnection called without key kwarg - pre-PR behavior]
Reviews (8): Last reviewed commit: "Merge branch 'main' into feat/forward-ae..." | Re-trigger Greptile |
Motivation
Unitree G1 firmware 1.5.1 introduced a
data2=3WebRTC handshake that requires a per-device AES-128 key. Without it the connection fails insideunitree_webrtc_connectwithRSA key format is not supported(pycryptodome trying to parse ciphertext bytes as an RSA key).The per-device key is fetched from Unitree's cloud once via
unitree-fetch-aes-key --email YOU --sn <serial>and then cached locally. The upstream driverlegion1581/unitree_webrtc_connect@v2.1.1accepts it through anaes_128_key=kwarg onUnitreeWebRTCConnection. The dimos wrapper atdimos/robot/unitree/connection.pynever forwarded it, so anyone on G1 firmware >=1.5.1 cannot use the dimos Unitree integration today.Change
UnitreeWebRTCConnection.__init__now accepts an optionalaes_128_key: str | None = Nonekwarg and falls back to theUNITREE_AES_128_KEYenvironment variable. The value is forwarded to the underlyingLegionConnectiononly when non-empty, so the call is byte-identical to the previous behaviour when unset.Verification
Tested on a Unitree G1 EDU+ (model string
G1_Edu+) at firmware 1.5.1.1. WithUNITREE_AES_128_KEYexported in the shell,dimos run unitree-g1-basicproceeds past the WebRTC handshake on192.168.123.161:9991and the robot accepts motion-switcher / wireless-controller commands as before. Without the env var, the same command reproducesRSA key format is not supportedand the handshake never completes — same behaviour asmain.No breaking change
The kwarg is optional and defaults to
None. The env-var lookup is opt-in (only consulted when the kwarg isNone). Callers on G1 firmware <1.5.1 and all Go2 robots see no behavioural change — the**extrais empty and theLegionConnectioncall is byte-identical to the old one.Optional follow-up (not in this PR)
pyproject.tomlcurrently pinsunitree-webrtc-connect-leshy>=2.0.7. Theaes_128_keykwarg + the_decrypt_data1_v3path that consumes it landed inlegion1581/unitree_webrtc_connect@v2.1.1. Ifunitree-webrtc-connect-leshyis a downstream rebuild of that repo and is already on >=2.1.1, no change is needed and this PR is enough on its own. If it's still tracking 2.0.x, the dep will also need to be bumped (e.g. via[tool.uv.sources]pointing atgit+https://github.com/legion1581/unitree_webrtc_connect.git@v2.1.1). Happy to follow up in a separate PR if maintainers confirm the situation.