只用 PC 和手機測試 Matter Bridge 與 Apple Home
Test a Matter Bridge with Apple Home Using Only a PC and a Phone
作者只用一部 Windows PC 和手機,端到端測試自製 Matter 閘道能否接入 Apple Home,並控制其後的藍牙裝置。閘道以 Rust 編寫,使用 PC 內置藍牙;手機上的 nRF Connect 模擬藍牙裝置,讓作者在硬件到貨前先驗證 Matter 配對、指令轉換及狀態同步。
The previous post covered the overall plan: put a Matter gateway between our Bluetooth devices and Apple Home, and let it translate messages in both directions.
Plans always look tidy on paper. Before touching any hardware, I wanted to confirm one thing first: will Apple Home actually accept a gateway we wrote ourselves, and control the Bluetooth devices behind it?
That question doesn't need hardware. The development boards were still in the mail, so I used what was already on my desk, a Windows PC and a phone, and ran the whole chain end to end.
Software first, hardware second
On hardware projects it's tempting to start by buying boards, soldering modules and flashing firmware. The trouble is that with a long chain, it's hard to tell which layer broke: did Matter pairing fail, is there a bug in the gateway, did the serial link drop bytes, or is the Bluetooth signal just weak?
Getting the top two layers working in software first shrinks the search area when real hardware arrives. It also costs almost nothing: a computer and a phone are enough.
Who plays which part
| Role | In the real product | In this demo |
|---|---|---|
| Controller | Apple Home | Apple Home (the real thing) |
| Gateway | Linux board + Bluetooth module | A Windows PC using its built-in Bluetooth |
| Bluetooth device | Switches and lights | A phone running nRF Connect |
Apple Home is real, and the gateway program is the same one that will ship in the product. Only the Bluetooth device at the bottom is played by a phone.
nRF Connect is Nordic's free Bluetooth debugging app for Android and iPhone. It can scan nearby Bluetooth advertisements and send its own, which makes it a good stand-in for a device.
Why not simulate a Bluetooth Mesh device directly?
In the real product, the devices and the gateway talk SIG Mesh. A phone can't act as a Mesh device, though: neither Android nor iOS lets apps become a Mesh node. Apps like nRF Mesh can only provision devices and act as remotes.
So the demo uses something simpler: the device and the gateway exchange plain Bluetooth advertisements. To turn a light on, the gateway broadcasts "on"; when a device's state changes, it broadcasts that back to the gateway.
This format has no encryption and no replay protection. It exists only to test the chain and will never ship. Its value is that everything in the gateway except the lowest communication layer is real: Matter pairing, the device table, command translation and state sync.
The demo advertising format
The simpler the format, the better: you should be able to type it by hand into a phone app.
Gateway → device (downlink): one Manufacturer Data entry with Company ID 0xFFFF. That ID is reserved by the Bluetooth SIG for testing and must not be used in real products.
| Bytes | Content | Example |
|---|---|---|
| 1–2 | Fixed GW
|
47 57 |
| 3–4 | Device address, little-endian |
02 00 means 0002 |
| 5 | On/off state |
01 on, 00 off |
| 6 | Sequence number, +1 each time | 05 |
Device → gateway (uplink): one format for Android, another for iPhone.
-
Android: also Manufacturer Data, Company ID
0xFFFF, data4456020001.4456isDV,0200is address 0002, and the final01means on. -
iPhone: iOS doesn't allow apps to put custom manufacturer data in advertisements, only to change the device name. So set the name to
DV0002:1, meaning address 0002, on.
Parsing on the gateway side takes only a few lines and accepts both:
pub fn uplink(sections: &[(u8, Vec<u8>)]) -> Option<(u16, bool)> {
sections.iter().find_map(|(t, d)| match (*t, d.as_slice()) {
// Android: manufacturer data FF FF 'D' 'V' address state
(0xFF, [0xFF, 0xFF, b'D', b'V', a0, a1, on, ..]) => {
Some((u16::from_le_bytes([*a0, *a1]), *on != 0))
}
// iPhone: device name DV0002:1
(0x08 | 0x09, name) => {
let s = std::str::from_utf8(name).ok()?.strip_prefix("DV")?;
let (addr, on) = s.split_once(':')?;
Some((u16::from_str_radix(addr, 16).ok()?, match on {
"1" => true,
"0" => false,
_ => return None,
}))
}
_ => None,
})
}
The gateway program
The gateway is written in Rust, using the open-source rs-matter for Matter. Bluetooth on the PC goes through Windows' built-in Bluetooth APIs, so no extra drivers are needed.
Once running, the program does three things:
- Acts as a Matter gateway: it announces itself on the local network and waits for Apple Home to pair. If it hasn't been paired yet, the pairing QR code is printed right in the terminal.
-
Maintains a device table: typing
add 0002 Living room lightin the terminal adds a light. Each device appears in Matter as a separate bridged device. - Sends and receives advertisements: commands from Apple Home become downlink advertisements; uplink advertisements from the phone update the state, which is synced back to Apple Home.
The device table and pairing data are saved to local files, so restarting the program doesn't require pairing again.
Adding it to Apple Home
Scan the terminal's QR code with the Home app on an iPhone. A few things to watch for:
- You'll see an "Uncertified Accessory" warning. During development the gateway uses the official Matter test certificates, which aren't certified, so iOS warns you. Choose "Add Anyway". Production units need real certificates issued after certification.
- The PC and the iPhone must be on the same local network, and Windows Firewall must allow the program to send and receive network traffic. If pairing times out, check this first.
- You need a home hub. Apple Home needs a HomePod or Apple TV as a home hub to control Matter accessories.
Once added, Apple Home shows a gateway with "Living room light" and "Study light" behind it, each of which can go into a different room like any other light.
Downlink: turn a light on in Apple Home
- Open nRF Connect on the phone and go to the Scanner tab.
- Tap "Living room light" in Apple Home.
- The PC terminal prints
BLE TX -> 0002, and the gateway broadcasts the command for one second. - A new device appears in nRF Connect's scan list with manufacturer data
0xFFFFand4757 0200 01 xx, which reads "gateway says: device 0002, on".
The PC may use a different Bluetooth address for each advertisement. If it's hard to spot in the list, filter by manufacturer data or signal strength.
Uplink: the device tells Apple Home
- In nRF Connect, create a new advertisement (Advertiser). On Android, enter manufacturer data
0xFFFF/4456020001; on iPhone, set the device name toDV0002:1. - Start advertising.
- The PC terminal prints
BLE RX <- 0002 (Living room light): ON. - The living room light shows as on in Apple Home.
This simulates someone pressing the switch on the wall. It matters even more than the downlink: if device state can't flow back, what Apple Home shows won't match reality.
Pitfalls along the way
None of this is complicated, but a few spots are easy to get stuck on the first time.
1. The phone's advertisement turned lights back on.
The phone keeps repeating the same packet. At first the gateway updated the state every time it received one, so after turning a light off in Apple Home, the phone's "on" packet switched it back a second later. The fix was to count a report only when its content changes. Real devices need the same thing: repeated messages must be de-duplicated.
2. The iPhone puts its device name in the scan response.
When an iPhone advertises, the device name isn't in the first advertising packet but in the scan response. The PC's default passive scanning never sees it; it has to use active scanning.
3. You can't identify devices by Bluetooth address.
Phones and PCs advertise with random addresses that change periodically. So the device identity goes inside the advertisement, in those two address bytes. That matches how Mesh works: Mesh devices are identified by their assigned unicast address, not their MAC.
4. Multiple advertisements at once interfere on Windows.
Tapping several lights in a row sent several advertisements at the same time, and they overwrote one another. Queuing them, one after another, fixed it.
5. Advertising blocked Matter.
Each advertisement on Windows has to run for a while. Calling it directly inside Matter's processing loop meant every other command from Apple Home waited in the meantime. So advertising moved to its own thread.
6. Changing the gateway's manufacturer and model doesn't require re-pairing.
Apple Home reads these from the gateway and picks up new values after a restart. It does cache them, though, and there's no telling when it refreshes. If you need to see the change right away, remove and re-add the gateway, but note that removing the gateway removes every device behind it too.
Also, the freshly compiled program was fairly large at first. With size optimization and debug symbols stripped, the release build is about 2.3 MB, which fits easily on a gateway board.
What the demo proves
Proven:
- A gateway we wrote is recognized and paired by Apple Home.
- The bridged devices can be controlled individually in Apple Home.
- Downlink commands and uplink state both work.
- After adding or removing devices, or restarting after a disconnect, Apple Home stays in sync.
Not yet proven:
- Real Bluetooth Mesh provisioning, encryption and networking.
- Whether the Silicon Labs module and Telink devices work together.
- How it runs on a Linux gateway board.
- Behavior with dozens or hundreds of devices online at once.
In other words, the Matter half is verified; the Bluetooth Mesh half has to wait for real hardware. The next step is replacing the PC's plain advertisements with a Bluetooth module connected over a serial port. In the gateway program, that's just a different adapter layer.
Final thoughts
The biggest payoff from this step was confirming the most important thing before spending money on hardware: Apple Home accepts this gateway. Whatever goes wrong later, at least the Matter layer is no longer a suspect.
If you're building a similar gateway, or want to get Matter running before you have hardware, I'd be glad to talk. Code details and lessons learned are all on the table: linktr.ee/weiyii
I'm cleaning up the demo code into a smaller version to open-source. I'll add the link to this post once it's out.
Cover image: Alejandro Escamilla, CC0 1.0.
This article was prepared for DEV with AI assistance.
來源:DEV Community · dev.to