히스토리
- @pi-claude — 문서 리팩터링: RK3576 한정 → Android arm64 범용 가이드로 확장. NDK 빌드 7개 이슈 테이블 추가. 재현 가능 빌드 스크립트(build-otbr.sh) 반영
- @pi-claude — NDK 빌드 성공! 6번 시도, 7개 이슈 해결. otbr-agent 6.9MB + ot-ctl 12KB (arm64 stripped). dist/otbr-arm64/에 복사
- @junghan — 다른 작업하느라 내가 정신 없었음에도 멋지게 작업을 해주는 여러분께 감사!
- @pi-claude — Go ot-ctl 경로 환경변수, rk3576-thread.sh, docs/THREAD.md, NDK r28c 제거, connectedhomeip 28GB 삭제. NDK 빌드 tmux 진행 중 (SKS 네트워크 느림→집에서 이어갈 것)
- 생성 — RPi5 Thread 스택 검증 후 Android 이식 계획 수립. bd-277.1 작업 가이드.
왜 Android arm64인가 — Yocto Linux 유일한 선택지가 아닌 이유
HomeAgent의 Thread Border Router(OTBR)는 원래 RPi5(Yocto Linux) 전용이었다. 그러나 smart home hub 시장의 현실은 다르다:
- 안드로이드 SBC 시장이 더 크다. RK3576, RK3588, Amlogic S905X4, MT8395 등 — Android 탑재 보드가 가격/성능/가용성에서 RPi5보다 유리한 경우가 많다.
- Thread RCP가 UART로 연결되면 OS 독립적이다. ESP32-H2든 Silicon Labs EFR32든, Spinel HDLC over UART는 Linux/Android 공통이다.
- ot-br-posix는 POSIX 코드다. Android도 POSIX 호환. NDK로 빌드하면 돌아간다.
- 고객 프로젝트에서 Android 보드가 주어진다. K 프로젝트의 RK3576이 계기였지만, 패턴은 반복된다.
따라서 이 문서는 *특정 보드가 아닌 “Android arm64에서 OTBR 돌리기” 범용 가이드*다. 검증 보드가 RK3576일 뿐, 다른 Android arm64 보드에서도 동일하게 적용된다.
적용 가능한 보드 (요구사항)
| 요구사항 | 이유 |
|---|---|
| Android arm64 (API 30+) | NDK 빌드 타겟 |
| UART 접근 가능 | Thread RCP 연결 |
| adb root 또는 userdebug | SELinux, /dev 접근 |
| TUN 커널 모듈 | wpan0 인터페이스 |
| WiFi 또는 이더넷 | backbone 인터페이스 |
검증 보드:
- RK3576-EVB (Android 15, ESP32-H2 UART5) — 이 문서의 주요 검증 대상
- 이론적 호환: RK3588 Android, MT8395 Android, 기타 arm64-v8a userdebug 보드
RPi5 검증 완료 스택 (2026-03-10 실증) — 기준선
이식의 기준이 되는 RPi5 Yocto 스택:
ESP32-H2 (ZBDongle-E, /dev/ttyUSB0, 460800baud)
└─ otbr-agent -I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyUSB0?uart-baudrate=460800
├─ Thread: leader, ch=26, panid=0xe8e9, network=OpenThread-e8e9
├─ SRP server: running
└─ wpan0: UP, IPv6 (fd88:1bc0:d9c2:...)
└─ matterjs :5580 (fabric=1, ble=true, thread=true)
└─ Go homeagent :8080
└─ A2UI 웹 대시보드
Thread 디바이스 (Tuya DS001-T, sleepy end device, battery):
- node 1: 현관문 센서 (contact_sensor) — 여닫기 실시간 확인 ✅
- node 7: 화장실 센서 (contact_sensor) — 동작 확인 ✅
- LLM 에이전트: "현관문이 닫혔습니다" (Gemini Flash)Yocto Linux vs Android — 플랫폼 분기점
같은 ot-br-posix 소스, 같은 역할. 빌드와 배포만 다르다.
| 항목 | RPi5 (Yocto Linux) | Android arm64 | 비고 |
|---|---|---|---|
| 소스 | ot-br-posix | ot-br-posix | ✅ 동일 |
| 빌드 | bitbake (OE toolchain) | NDK r27 (cmake) | 툴체인만 다름 |
| mDNS | avahi-daemon | OT core (내장) | Android에 avahi 없음 |
| init | systemd | shell script | Android에 systemd 없음 |
| RCP | /dev/ttyUSB0 (USB) | /dev/ttyS5 (UART) | 보드 의존 |
| backbone | eth0 | wlan0 | 보드 의존 |
| baudrate | 460800 | 460800 | ✅ 동일 |
| SRP server | otbr-agent 내장 | otbr-agent 내장 | ✅ 동일 |
| Go 연동 | ot-ctl → hub.go | ot-ctl → hub.go | ✅ 동일 |
핵심: 프로토콜 계층(Spinel, Thread, SRP, matterjs)은 동일. 인프라 계층(init, mDNS, 권한)만 다르다.
NDK 크로스빌드 — 검증 완료 (2026-03-11)
소스 버전 고정
| 소스 | 커밋 | 비고 |
|---|---|---|
| ot-br-posix | c19319c7 | ~/repos/3rd/ot-br-posix |
| openthread (submodule) | 0887643bf | third_party/openthread/repo |
| NDK | r27 (27.0.12077973) | nix devShell, flake.nix |
빌드 명령
재현 가능 빌드 스크립트: homeagent-config/scripts/build-otbr.sh
# nix devShell 진입 후 실행
cd ~/repos/gh/homeagent-config
./run.sh otbr-build
# 또는 직접
nix develop .#dev --impure --command bash scripts/build-otbr.sh핵심 CMake 옵션:
cmake -B build-android \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-35 \
-DANDROID_STL=c++_static \
-DCMAKE_CXX_FLAGS="-DOPENTHREAD_CONFIG_ANDROID_NDK_ENABLE=1" \
-DCMAKE_C_FLAGS="-DOPENTHREAD_CONFIG_ANDROID_NDK_ENABLE=1" \
-DOT_ANDROID_NDK=ON \
-DBUILD_TESTING=OFF \
-DOTBR_DBUS=OFF -DOTBR_REST=OFF -DOTBR_WEB=OFF \
-DOTBR_MDNS=openthread \
-DOTBR_BACKBONE_ROUTER=OFF \
-DOTBR_SRP_ADVERTISING_PROXY=OFF \
-DOTBR_BORDER_ROUTING=ON \
-DOTBR_BORDER_AGENT=ON \
-DOT_SPINEL_RESET_CONNECTION=ON \
-DOT_TREL=OFF -DOT_MLR=ON \
-DOT_SRP_SERVER=ON -DOT_ECDSA=ON -DOT_SERVICE=ON \
-DOT_DUA=ON -DOT_BORDER_ROUTING_NAT64=OFF \
-DOTBR_INFRA_IF_NAME=wlan0 \
-DOTBR_NO_AUTO_ATTACH=17개 이슈와 해결 (빌드 6번 시도)
| # | 이슈 | 원인 | 해결 |
|---|---|---|---|
| 1 | cutils/properties.h not found | Android NDK에 없는 system 헤더 | -DOPENTHREAD_CONFIG_ANDROID_NDK_ENABLE=1 |
| 2 | Only one Discovery Proxy | OT_DISCOVERY_PROXY(기본ON) + DNSSD 충돌 | DNSSD_DISCOVERY_PROXY 제거 |
| 3 | Only one Advertising Proxy | MDNS=openthread에서 OT_SRP_ADV_PROXY 자동ON | SRP_ADVERTISING_PROXY=OFF |
| 4 | -lutil not found | glibc 전용 라이브러리, Android에 없음 | -DOT_ANDROID_NDK=ON |
| 5 | sign-compare fatal error | NDK clang -Werror | udp.cpp static_cast<unsigned int> 패치 |
| 6 | libnetfilter_queue.h not found | Android에 없는 Linux 헤더 | BACKBONE_ROUTER=OFF |
| 7 | dns_sd.h not found | mDNSResponder 미포함 | MDNS=openthread (OT core mDNS) |
패치 파일: homeagent-config/patches/ot-br-posix/0001-fix-udp-sign-compare-ndk-clang.patch 빌드 스크립트가 자동 적용.
산출물
| 바이너리 | 크기 (stripped) | 아키텍처 |
|---|---|---|
| otbr-agent | 6.9MB | ELF arm64, /system/bin/linker64 |
| ot-ctl | 12KB | ELF arm64, /system/bin/linker64 |
Yocto 빌드와의 핵심 차이
| CMake 옵션 | Yocto | Android NDK | 왜 다른가 |
|---|---|---|---|
OTBR_DBUS | ON | OFF | Android에 dbus 없음 |
OTBR_MDNS | avahi | openthread | Android에 avahi 없음 |
OTBR_BACKBONE_ROUTER | ON | OFF | libnetfilter_queue 불가 |
OT_ANDROID_NDK | (없음) | ON | -lutil 제외 |
ANDROID_NDK_ENABLE | (없음) | 1 | cutils → sys/system_properties |
OT_TREL | ON | OFF | DNS-SD 기반, 외부 mDNS 없이 불가 |
Android 보드 데이터 수집 (RK3576 기준)
특정 보드에서 실행하기 전에 수집해야 할 데이터. 다른 Android 보드에도 동일한 체크리스트.
필수 확인 항목
# 1. 아키텍처
adb shell getprop ro.product.cpu.abi # arm64-v8a
adb shell getprop ro.build.version.sdk # API level (30+)
# 2. Thread RCP UART
adb shell ls -la /dev/ttyS* /dev/ttyUSB* # UART 디바이스
adb shell cat /proc/tty/driver/serial # UART 상세
# 3. TUN 지원
adb shell zcat /proc/config.gz | grep CONFIG_TUN # =y or =m
adb shell ls -la /dev/tun /dev/net/tun
# 4. SELinux
adb shell getenforce # Enforcing/Permissive
adb shell ls -Z /dev/ttyS5 # UART의 SELinux 컨텍스트
# 5. 기존 Thread HAL (있으면 중지 필요)
adb shell pm list packages | grep thread
adb shell ps -A | grep -E "ot-daemon|threadnetwork"
# 6. IPv6
adb shell sysctl net.ipv6.conf.all.forwarding
adb shell ip -6 addr show
# 7. 네트워크 인터페이스
adb shell ip link show # wlan0/eth0 확인RK3576 수집 결과 (2026-03-10)
| 항목 | 값 |
|---|---|
| SoC | RK3576 (Cortex-A72 + A53) |
| Android | 15 (API 35) |
| Kernel | 6.1.118 aarch64 |
| ABI | arm64-v8a |
| SELinux | Enforcing (setenforce 0 가능, userdebug) |
| WiFi | SKS&GQ_TEST_2.4 (192.168.69.5) |
| ESP32-H2 | /dev/ttyS5 (UART5, 460800) |
| TUN | CONFIG_TUN=y, /dev/tun 존재 |
| Thread HAL | com.android.hardware.threadnetwork (PID 598) |
| ot-daemon | stopped |
| /system/bin/ot-ctl | 존재 (ot-daemon 전용, otbr-agent과 호환 안됨) |
배포 및 실행 (RK3576 기준)
배포
./run.sh otbr-deploy # adb push otbr-agent + ot-ctlThread 시작
./run.sh rk-thread-start # HAL 중지 → SELinux → TUN → otbr-agent → dataset → SRP상세: scripts/rk3576-thread.sh (start/stop/status)
전체 스택 시작 순서
1. stop vendor.threadnetwork_hal / ot-daemon
2. setenforce 0
3. ip tuntap add wpan0
4. sysctl IPv6 forwarding
5. otbr-agent (wpan0 + /dev/ttyS5 + wlan0)
6. ot-ctl: dataset init/commit, ifconfig up, thread start
7. ot-ctl: srp server enable
8. matterjs-server :5580
9. Go homeagent :8080 (getOTBRDataset → set_thread_dataset 자동)
10. Flutter APK (WebView localhost:8080)리스크 및 미검증 사항
| # | 리스크 | 심각도 | 상태 |
|---|---|---|---|
| 1 | MDNS=openthread 기능 제약 | 중 | 빌드 성공, 실동작 미검증 |
| 2 | BACKBONE_ROUTER=OFF로 인한 IPv6 라우팅 제한 | 중 | 실 Thread 디바이스 테스트 필요 |
| 3 | Android netd와 wpan0 TUN 충돌 | 중 | RK3576에서 실행 시 확인 |
| 4 | /dev/ttyS5 baudrate (460800 vs 115200) | 저 | HAL rc 기준 460800, RCP 로그 115200. auto-baud 의심 |
| 5 | ot-ctl 소켓 경로 | 저 | otbr-agent의 UNIX socket 위치 확인 필요 |
| 6 | SELinux re-enable 시 otbr-agent 차단 | 저 | sepolicy 패치 필요할 수 있음 |
K 프로젝트 참고 사항
K 프로젝트에서 같은 RK3576에서 Thread 검증한 경험:
| 항목 | 값 |
|---|---|
| NDK | 28.2.13676358 (homeagent은 27 사용) |
| Thread HAL | Android 기본 HAL + ot-daemon 방식 |
| 커미셔닝 | CHIPTool (우리는 matterjs 사용) |
| Thread 성공 | Nanoleaf Thread 전구 커미셔닝 완료 |
| 핵심 차이 | HAL 경유 vs POSIX 직접 — 완전히 다른 경로 |
homeagent은 HAL을 우회하고 ot-br-posix를 직접 실행한다. 이유: matterjs-server와의 통합 (ot-ctl → set_thread_dataset), 재현 가능한 빌드.
관련 문서
- HomeAgent 로드맵 — 오픈소스 스마트홈 에이전트 플랫폼 — TUI/A2UI/APK 로드맵
homeagent-config/docs/THREAD.md— Thread BR 아키텍처, 빌드 가이드homeagent-config/docs/PLATFORM-MATRIX.md— RPi5 vs RK3576 플랫폼 매트릭스homeagent-config/scripts/build-otbr.sh— 재현 가능 NDK 빌드 스크립트- durable-iot-migrate — Temporal 기반 IoT 마이그레이션 — homeagent과 세트 오픈소스 프로젝트
Comments