Closed vChavezB closed 1 year ago
The reason this doesn't work is that you're bridging two controllers together, which isn't going to work (despite the generic "bridge" name, the HCI bridge app can only be used to bridge the transports of a Controller and a Host).
The topolgy is: [app/device]<->[host]<-{hci}->[controller]<--- (radio/link) --->[controller]<-{hci}->[host]<->[app/device]
An app/device communicates with another app/device, via the Host part of a stack, with talks to the Controller part of a stack, which then exchanges link layer data with other Controllers via a shared link (which is going to be a radio for a physical link, or a virtual link). Hosts and Controllers communicate via HCI packets.
What Bumble calls a transport is a bi-directional stream of HCI packets between a Host and a Controller.
The controllers
app creates several controllers that are all tied via a local Link. Then you can connect multiple apps, one to each controller, via their own Host.
So, if you connect the HCI side of a Controller to the HCI side of another Controller, that's a mismatch.
Also, what maybe led to confusion here is that there are two types of controllers here: The Bumble virtual controller (which is what gets instantiated by the controllers
app), and the Netsim virtual controller (with an internal component called Root Canal) which gets instantiated by the Android emulator. Netsim can create many controllers on demand (via a gRPC interface), which all can exchange packets with each other. The Bumble controllers
app does the same, but you pass in an explicit list of controllers (each with its own transport interface), rather than being created on demand. But the Bumble virtual controllers can only exchange packets with other bumble virtual controllers attached to the same local Link (that's why, for example, if you run two controllers
apps, devices attached to different instances won't see each other, you should only have one controllers
app, with multiple controllers). Same with the Netsim controllers: only controllers instantiated by the same Netsim instance can "see" each other.
But... that's Ok, you can do exactly what you want here (have your Zephyr device communicate with an emulated Android device), with the right topology:
[Zephyr app]<->[Zephyr host]<-{hci}->[TCP to gRPC bridge]<->[netsim controller]<-- (netsim internal link) -->[netsim controller]<->[Android host]<->[Android app]
.
The bridge here is used to allow the Zephyr host (BT stack of Zephyr) which can send/receive HCI packets over TCP, to reach the Netsim controller, which can send/receive packets over gRPC.
The Bumble HCI bridge from TCP to gRPC here isn't a requirement, you could have the Zephyr host communicate with Netsim directly, but that would require the Zephyr app to implement all the gRPC logic, which Bumble already has.
So, say that your Zephyr stack is configured to connect to 172.22.0.1:9000 over TCP, you would use the Bumble bridge as:
python hci_bridge.py tcp-client:172.22.0.1:9000 android-netsim
. The controllers
app isn't needed here.
NOTE: in theory you could do the same but have everything go through the Bumble virtual link instead of Netsim (there are options to tell the Android emulator to connect its Host to something other than Netsim), but since Netsim is a much more capable virtual controller/link than Bumble's own limited virtual controller, I wouldn't recommend it. (The focus of Bumble is really on the bulk of the Host + profiles stack, the virtual controller is a limited component that's useful for unit testing and some simple configurations, but it isn't designed to support all use cases. There's a plan to eventually only use the Netsim/RootCanal controller going forward, at some point in the near future)
That clears most of my questions. However, i tried your suggestion
python hci_bridge.py tcp-client:172.22.0.1:9000 android-netsim
but now the zephyr application does not start, i.e. it does not connect to 172.22.0.1:9000
.
Should it be started before the Zephyr application tries to connect to 172.22.0.1:9000
?
The IP address I am using is the localhost that is proxied between windows and the Windows Subystem for Linux (WSL) as the Zephyr application is a native linux binary.
This is what the linux zephyr binary does to connect
Sorry, typo. The bridge should be a TCP server (for Zephyr to connect to):
python hci_bridge.py tcp-server:_:9000 android-netsim
. (_
stands for listening for local connections. If you need to listen on a specific network interface, use the IP addr of that interface instead).
Ah I see ok thanks for the info. Now I get the error
INFO:bumble.bridge:[HOST->CONTROLLER] HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL_COMMAND: 01
DEBUG:bumble.transport.tcp_server:connection end
DEBUG:bumble.transport.tcp_server:connection lost: None
WARNING:bumble.transport.common:exception while waiting for packet: <AioRpcError of RPC that terminated with:
status = StatusCode.UNKNOWN
details = "Stream removed"
debug_error_string = "UNKNOWN:Error received from peer ipv6:%5B::1%5D:58215 {grpc_message:"Stream removed", grpc_status:2, created_time:"2023-07-24T07:46:54.409214084+00:00"}"
I think this is a similar error to the one from the bumble virtual controller. Do you know how I can override or fake a good reply for the command HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL_COMMAND
from the android-netsim to the tcp-server ?
Update: I read the source from the hci-bridge.py file and found out you can add a filter to "shortcircuit" commands. To filter the command HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL_COMMAND I am now running the bridge as follows
python hci_bridge.py tcp-server:_:9000 android-netsim 0x03:0x0031
where 0x03:0x0031
represents the op code for the Set Controller To Host Flow Control command.
Advertisment works! Still have to figure out to make the connection work.
As a follow up to this issue
https://github.com/google/bumble/issues/215
I am trying to connect a Zephyr App through a bumble virtual controller to an android emulator. I first executed the
run_gatt_server.py
example to verify that the grpc server from the android emulator is working. When I scan the device I can see it in the Android emulator.However at this point I am not sure if I understand how to link the
tcp-server
virtual controller to theandroid-netsim
host as I have not been able to connect a tcp-server virtual controller to the android-netsim transport.Here have been my attempts
HCI Bridge
python controllers.py tcp-server:172.22.0.1:9000 tcp-server:172.22.0.1:9001
emulator-avd Pixel_7_API_34 -packet-streamer-endpoint default -grpc 8557
Connect my zephyr app to
tcp-server:172.22.0.1:9000
Create an hci-bridge
python hci_bridge.py tcp-client:172.22.0.1:9001 android-netsim
Relay Link
python link_relay
python controllers.py tcp-server:172.22.0.1:9000 link-relay:ws://localhost:10723/test
emulator-avd Pixel_7_API_34 -packet-streamer-endpoint default -grpc 8557
Connect my zephyr app to
tcp-server:172.22.0.1:9000
Bridge android-netsim host to link relay
python hci_bridge.py android-netsim link-relay:ws://localhost:10723/test