1. Trước khi bắt đầu
Trong lớp học lập trình Bộ định tuyến đường viền luồng (TBR), chúng tôi sẽ hướng dẫn cách xây dựng Bộ định tuyến đường viền luồng dựa trên Raspberry Pi. Trong lớp học lập trình đó, chúng ta
- Thiết lập khả năng kết nối IP hai chiều giữa mạng Thread và mạng Wi-Fi/Ethernet.
- Cung cấp dịch vụ khám phá hai chiều qua mDNS (trên liên kết Wi-Fi/Ethernet) và SRP (trên mạng Thread).
Lớp học lập trình này được xây dựng dựa trên lớp học trước, đề cập đến cách bộ định tuyến biên của riêng bạn và ứng dụng của bạn có thể tương tác với các API của Google để tạo một mạng Thread duy nhất. Việc hội tụ thông tin xác thực Thread rất quan trọng vì nó giúp tăng cường độ mạnh của mạng và đơn giản hoá các hoạt động tương tác của người dùng với các ứng dụng dựa trên Thread.
Điều kiện tiên quyết
- Hoàn thành Lớp học lập trình OTBR
- Kiến thức cơ bản về Linux, Android/Kotlin và kết nối mạng Thread
Kiến thức bạn sẽ học được
- Cách sử dụng Thread Share API (API Chia sẻ luồng) để tải và thiết lập nhóm thông tin xác thực
- Cách thiết lập Bộ định tuyến biên OpenThread của riêng bạn bằng cùng thông tin đăng nhập với mạng của Google
Bạn cần có
- Bảng Raspberry Pi 4 hoặc một bảng dựa trên Linux khác chạy Bộ định tuyến đường viền luồng mở (OTBR)
- Bảng cung cấp kết nối IEEE 802.15.4 dưới dạng Bộ đồng xử lý vô tuyến (RCP). Xem danh sách kho lưu trữ của các nhà cung cấp SoC khác nhau và hướng dẫn của họ trên trang OpenThread GitHub
2. Thiết lập dịch vụ HTTP
Thành phần đầu tiên mà chúng tôi cần là một giao diện cho phép chúng tôi đọc Thông tin xác thực đang hoạt động và ghi Thông tin xác thực đang chờ xử lý vào OTBR của bạn. Khi xây dựng TBR, hãy sử dụng các cơ chế độc quyền của riêng bạn, như được trình bày ở đây với hai ví dụ. Tuỳ chọn đầu tiên trình bày cách giao diện với tác nhân OTBR cục bộ thông qua DBUS, trong khi tuỳ chọn thứ hai sử dụng API Nghỉ ngơi có thể được xây dựng trên OTBR.
Cả hai phương pháp này đều không an toàn và không nên được sử dụng trong môi trường phát hành chính thức. Tuy nhiên, nhà cung cấp có thể xây dựng tính năng mã hoá cho một trong hai phương thức để sử dụng trong môi trường phát hành chính thức, hoặc bạn có thể mở rộng dịch vụ giám sát của riêng mình để phát hành HTTP lặp lại hoặc lệnh gọi DBUS cục bộ vốn có.
Cách 1: API DBUS và HTTP trên Python Script
Bước này tạo ra một dịch vụ HTTP đơn giản để hiển thị hai điểm cuối để đọc và thiết lập thông tin xác thực, cuối cùng là gọi các lệnh DBUS.
Trên RPi sẽ đóng vai trò là OTBR của bạn, hãy cài đặt các phần phụ thuộc Python 3:
$ pip install dbus-python shlex json
Chạy tập lệnh dưới dạng:
$ sudo python credentials_server.py 8081 serving at port 8081
Mẫu này thiết lập một máy chủ HTTP trên cổng 8081 và theo dõi trên đường dẫn gốc để yêu cầu GET để truy xuất thông tin xác thực Thread hoặc yêu cầu POST để đặt thông tin xác thực Thread. Tải trọng luôn là một cấu trúc JSON có TLV.
Yêu cầu PUT sau đây đặt Thông tin đăng nhập luồng đang chờ xử lý mới thành OTBR thông qua đường dẫn /node/dataset/pending
. Trong trường hợp này, thông tin đăng nhập đang chờ xử lý sẽ được áp dụng sau 10 giây:
PUT /node/dataset/pending Host: <IP>:8081 ContentType: "application/json" acceptMimeType: "application/json" ... { "ActiveDataset": "<TLV encoded new Thread Dataset>" "PendingTimestamp": { "Seconds": <Unix timestamp in seconds>, "Ticks": 0, "Authoritative": false }, "Delay": 10000 // in milliseconds }
Yêu cầu GET đến /node/dataset/active
sẽ tìm nạp Thông tin xác thực đang hoạt động.
GET /node/dataset/active Host: <IP>:8081 ContentType = "application/json" acceptMimeType = "text/plain" ... <TLV encoded Thread Dataset>
Tập lệnh gọi các lệnh DBUS R/W đến đường dẫn xe buýt io.openthread.BorderRouter.wpan0
, đường dẫn đối tượng /io/openthread/BorderRouter/wpan0
# D-BUS interface def call_dbus_method(interface, method_name, *arguments): bus = dbus.SystemBus() obj = bus.get_object('io.openthread.BorderRouter.wpan0', '/io/openthread/BorderRouter/wpan0') iface = dbus.Interface(obj, interface) method = getattr(iface, method_name) res = method(*arguments) return res def get_dbus_property(property_name): return call_dbus_method('org.freedesktop.DBus.Properties', 'Get', 'io.openthread.BorderRouter', property_name) def set_dbus_property(property_name, property_value): return call_dbus_method('org.freedesktop.DBus.Properties', 'Set', 'io.openthread.BorderRouter', property_name, property_value)
DBUS cho phép xem xét các khả năng của mình. Bạn có thể làm việc này như:
$ sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ org.freedesktop.DBus.Introspectable.Introspect
Bạn cũng có thể xem các chức năng được hỗ trợ trong tài liệu tại đây.
Cách 2: API Nghỉ ngơi HTTP gốc của tác nhân OTBR
Bộ định tuyến đường biên OpenThread tạo theo mặc định bằng cờ REST_API=1
, bật API REST. Trong trường hợp bản dựng của bạn trong lớp học lập trình trước không bật API REST, hãy nhớ tạo OTBR trên RPi bằng cờ đó:
$ REST_API=1 INFRA_IF_NAME=wlan0 ./script/setup
Bạn có thể khởi động lại tác nhân OTBR bằng cách chạy:
$ sudo systemctl restart otbr-agent.service
Tác nhân này khởi động một máy chủ HTTP trên cổng 8081. Máy chủ này cho phép người dùng hoặc chương trình giám sát thực hiện nhiều tác vụ trong OTBR (được ghi tại đây). Bạn có thể sử dụng trình duyệt curl
hoặc wget
để kiểm tra nội dung của trình duyệt. Trong số nhiều đường dẫn được hỗ trợ, có thể kể đến các trường hợp sử dụng mô tả ở trên, với động từ GET
trên /node/dataset/active
và động từ PUT
trên /node/dataset/pending
3. Thiết lập Khung thông tin xác thực trên Android
Thông tin đăng nhập ưu tiên
Dịch vụ Google Play trên Android cho phép và dự kiến đăng ký thông tin đăng nhập cho tất cả TBR trong mạng của bạn. Mỗi bộ lọc được xác định bằng Mã tác nhân bộ định tuyến biên (BAID). Bạn sẽ sử dụng phương thức addCredentials()
của giao diện ThreadNetworkClient
để thực hiện tác vụ này. TBR đầu tiên được thêm vào bộ nhớ Dịch vụ Google Play sẽ xác định Thông tin đăng nhập ưu tiên cho thiết bị di động này.
Ứng dụng thêm một bộ thông tin đăng nhập mạng Thread vào BAID của mình sẽ trở thành chủ sở hữu của thông tin đăng nhập đó và có toàn quyền truy cập vào các thông tin đó. Nếu cố truy cập vào thông tin xác thực do các ứng dụng khác thêm, bạn sẽ gặp lỗi PERMISSION_DENIED. Tuy nhiên, thông tin đăng nhập ưu tiên sẽ luôn được cung cấp cho mọi ứng dụng khi người dùng đồng ý. Bạn nên cập nhật thông tin đăng nhập được lưu trữ trong Dịch vụ Google Play khi mạng Bộ định tuyến đường biên luồng được cập nhật. Mặc dù thông tin đó hiện không được sử dụng, nhưng chúng tôi có thể cung cấp các hành trình nâng cao trong tương lai.
Ngay cả khi TBR đầu tiên bị loại trừ sau đó, Thông tin xác thực ưu tiên sẽ vẫn tồn tại trên thiết bị Android. Sau khi bạn đặt chính sách này, các ứng dụng khác quản lý thông tin xác thực Thread có thể lấy thông tin xác thực qua lệnh gọi getPreferredCredentials()
.
Google TBR Sync
Các thiết bị Android tự động đồng bộ hoá với Google TBR. Nếu không có thông tin đăng nhập nào trên Android, các thiết bị sẽ trích xuất thông tin đăng nhập đó từ các TBR của Google trong mạng của bạn và những thông tin đăng nhập đó sẽ trở thành Thông tin đăng nhập ưu tiên. Quá trình đồng bộ hoá giữa TBR và thiết bị Android chỉ xảy ra nếu TBR được ghép nối với một người dùng duy nhất hoặc nếu TBR được ghép nối với 2 người dùng trong cùng một Nhà thông minh ( Structure).
Quá trình này cũng sẽ xảy ra khi một người dùng khác của Google sử dụng GHA cho Android hoặc GHA cho iOS khi người dùng đó có cùng cấu trúc. Đối với GHA cho iOS, thông tin đăng nhập ưu tiên sẽ được thiết lập trên bộ nhớ iOS nếu không có thông tin đăng nhập ưu tiên nào.
Nếu hai thiết bị Android (hoặc Android + iGHA) tồn tại trong cùng một mạng với các bộ thông tin đăng nhập ưu tiên khác nhau thì thiết bị ban đầu đã định cấu hình TBR sẽ chiếm ưu thế trên TBR.
Giới thiệu về TBR của bên thứ ba
Bộ nhớ của thông tin đăng nhập hiện không nằm trong phạm vi của Nhà thông minh của người dùng ( Cấu trúc). Mỗi thiết bị Android sẽ có bộ nhớ BAID riêng, nhưng sau khi có Google TBR trong mạng, các thiết bị Android và thiết bị iOS khác chạy ứng dụng Google Home dành cho iOS sẽ đồng bộ hóa với TBR đó và cố gắng thiết lập thông tin đăng nhập cục bộ trên bộ nhớ điện thoại.
Trước khi OOB TBR mới tạo một mạng, bạn cần kiểm tra xem có mạng ưu tiên nào trong bộ nhớ của Android hay không.
- Nếu có một mạng ưu tiên, thì nhà cung cấp sẽ sử dụng mạng đó. Điều này đảm bảo rằng các thiết bị Thread được kết nối với một mạng Thread khi có thể.
- Khi không có mạng ưu tiên nào, hãy tạo bộ thông tin xác thực mới và chỉ định bộ thông tin đó cho TBR của bạn trong Dịch vụ Google Play. Android sẽ coi những thông tin đăng nhập đó là thông tin đăng nhập tiêu chuẩn được thiết lập trên tất cả các TBR dựa trên Google, đồng thời các nhà cung cấp khác sẽ có thể nâng cao phạm vi tiếp cận lưới và độ mạnh mẽ của bạn bằng các thiết bị bổ sung
4. Sao chép và sửa đổi ứng dụng Android
Chúng ta đã tạo một ứng dụng Android hiển thị các lệnh gọi chính có thể thực hiện đến Thread API. Bạn có thể sử dụng các mẫu này trong ứng dụng của mình. Trong lớp học lập trình này, chúng ta sẽ sao chép Ứng dụng mẫu Google Home cho Matter từ GitHub.
Tất cả mã nguồn hiển thị ở đây đều đã được mã hoá trong ứng dụng mẫu. Bạn được mời sửa đổi theo nhu cầu của riêng mình. Tuy nhiên, bạn chỉ cần sao chép ứng dụng hoặc chạy các tệp nhị phân được tạo sẵn để kiểm tra chức năng.
- Sao chép hình ảnh bằng cách sử dụng:
$ git clone https://github.com/google-home/sample-apps-for-matter-android.git
- Tải xuống và mở Android Studio.
- Nhấp vào Tệp > Mở và trỏ đến kho lưu trữ đã sao chép của bạn.
- Bật chế độ nhà phát triển trên điện thoại Android.
- Kết nối thiết bị với máy tính qua cáp USB.
- Chạy ứng dụng trong Android Studio qua <Cmd+R> (OS X) hoặc <Ctrl+R> (Win, Linux)
- Di chuyển đến Vòng quay -> Tiện ích dành cho nhà phát triển -> Mạng Thread
- Tương tác với những lựa chọn có sẵn. Trong các phần dưới đây, chúng ta sẽ giải nén mã được thực thi trên mỗi nút.
Có thông tin đăng nhập ưu tiên nào không?
Câu hỏi đầu tiên mà nhà sản xuất TBR nên hỏi Google là liệu một bộ thông tin đăng nhập ưu tiên đã tồn tại trong thiết bị hay chưa. Đây nên là điểm bắt đầu trong luồng của bạn. Mã bên dưới truy vấn GPS về sự tồn tại của thông tin đăng nhập. Ứng dụng này không nhắc người dùng đồng ý vì không có thông tin đăng nhập nào được chia sẻ.
/** * Prompts whether credentials exist in storage or not. Consent from user is not necessary */ fun doGPSPreferredCredsExist(activity: FragmentActivity) { try { // Uses the ThreadNetwork interface for the preferred credentials, adding // a listener that will receive an intentSenderResult. If that is NULL, // preferred credentials don't exist. If that isn't NULL, they exist. // In this case we'll not use it. ThreadNetwork.getClient(activity).preferredCredentials.addOnSuccessListener { intentSenderResult -> intentSenderResult.intentSender?.let { intentSender -> ToastTimber.d("threadClient: preferred credentials exist", activity) // don't post the intent on `threadClientIntentSender` as we do when // we really want to know which are the credentials. That will prompt a // user consent. In this case we just want to know whether they exist } ?: ToastTimber.d( "threadClient: no preferred credentials found, or no thread module found", activity ) }.addOnFailureListener { e: Exception -> Timber.d("ERROR: [${e}]") } } catch (e: Exception) { ToastTimber.e("Error $e", activity) } }
Nhận thông tin đăng nhập ưu tiên GPS
Nếu có, bạn nên đọc thông tin đăng nhập. Điểm khác biệt duy nhất so với mã trước đó là sau khi nhận được intentSenderResult
, bạn muốn tạo và khởi chạy một ý định bằng cách sử dụng kết quả đó từ người gửi.
Trong mã nguồn của chúng ta, để tổ chức/kiến trúc, chúng ta dùng MutableLiveData<IntentSender?>
vì mã gốc nằm trong ViewModel (ThreadViewModel.kt) và trình quan sát ý định nằm trong Mảnh hoạt động ( ThreadFragment.kt). Do đó, sau khi intentSenderResult được đăng lên dữ liệu trực tiếp, chúng ta sẽ thực thi nội dung của trình quan sát này:
viewModel.threadClientIntentSender.observe(viewLifecycleOwner) { sender -> Timber.d( "threadClient: intent observe is called with [${intentSenderToString(sender)}]" ) if (sender != null) { Timber.d("threadClient: Launch GPS activity to get ThreadClient") threadClientLauncher.launch(IntentSenderRequest.Builder(sender).build()) viewModel.consumeThreadClientIntentSender() } }
Thao tác này sẽ kích hoạt sự đồng ý của người dùng thông qua việc chia sẻ thông tin đăng nhập và nếu được phê duyệt, tính năng này sẽ trả về nội dung thông qua:
threadClientLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> if (result.resultCode == RESULT_OK) { val threadNetworkCredentials = ThreadNetworkCredentials.fromIntentSenderResultData(result.data!!) viewModel.threadPreferredCredentialsOperationalDataset.postValue( threadNetworkCredentials ) } else { val error = "User denied request." Timber.d(error) updateThreadInfo(null, "") } }
Việc đăng thông tin đăng nhập lên MutableLiveData<ThreadNetworkCredentials?>
được mô tả bên dưới.
Đặt thông tin xác thực GPS
Dù ứng dụng có tồn tại hay không, bạn vẫn nên đăng ký TBR của mình trong Dịch vụ Google Play. Ứng dụng của bạn sẽ là ứng dụng duy nhất có thể đọc thông tin đăng nhập được liên kết với ID tác nhân biên giới của TBR, nhưng nếu TBR của bạn là người đầu tiên đăng ký thì các thông tin đăng nhập đó sẽ được sao chép vào bộ Thông tin đăng nhập ưu tiên. Mọi Ứng dụng trên điện thoại đều có thể truy cập vào thông tin đó, miễn là người dùng cho phép.
/** * Last step in setting the GPS thread credentials of a TBR */ private fun associateGPSThreadCredentialsToThreadBorderRouterAgent( credentials: ThreadNetworkCredentials?, activity: FragmentActivity, threadBorderAgent: ThreadBorderAgent, ) { credentials?.let { ThreadNetwork.getClient(activity).addCredentials(threadBorderAgent, credentials) .addOnSuccessListener { ToastTimber.d("threadClient: Credentials added", activity) }.addOnFailureListener { e: Exception -> ToastTimber.e("threadClient: Error adding the new credentials: $e", activity) } } }
Thiết lập thông tin xác thực cho sản phẩm TBR
Phần này thuộc quyền sở hữu riêng của mỗi nhà cung cấp và trong lớp học lập trình này, chúng ta sẽ triển khai phần này thông qua Máy chủ nghỉ ngơi HTTP DBUS+Python hoặc Máy chủ nghỉ ngơi HTTP gốc của OTBR.
/** * Creates credentials in the format used by the OTBR HTTP server. See its documentation in * https://github.com/openthread/ot-br-posix/blob/main/src/rest/openapi.yaml#L215 */ fun createJsonCredentialsObject(newCredentials: ThreadNetworkCredentials): JSONObject { val jsonTimestamp = JSONObject() jsonTimestamp.put("Seconds", System.currentTimeMillis() / 1000) jsonTimestamp.put("Ticks", 0) jsonTimestamp.put("Authoritative", false) val jsonQuery = JSONObject() jsonQuery.put( "ActiveDataset", BaseEncoding.base16().encode(newCredentials.activeOperationalDataset) ) jsonQuery.put("PendingTimestamp", jsonTimestamp) // delay of committing the pending set into active set: 10000ms jsonQuery.put("Delay", 10000) Timber.d(jsonQuery.toString()) return jsonQuery } //(...) var response = OtbrHttpClient.createJsonHttpRequest( URL("http://$ipAddress:$otbrPort$otbrDatasetPendingEndpoint"), activity, OtbrHttpClient.Verbs.PUT, jsonQuery.toString() )
Lấy thông tin xác thực từ sản phẩm TBR của bạn
Như đã trình bày trước đó, hãy sử dụng GET HTTP Verb để lấy thông tin xác thực từ TBR của bạn. Xem tập lệnh Python mẫu.
Xây dựng và nhập
Khi tạo Ứng dụng Android, bạn sẽ cần thực hiện các thay đổi đối với tệp kê khai, bản dựng và dữ liệu nhập để hỗ trợ Mô-đun luồng của Dịch vụ Google Play. Ba đoạn mã sau đây tóm tắt hầu hết các nội dung bổ sung.
Xin lưu ý rằng ứng dụng mẫu của chúng tôi chủ yếu được xây dựng cho hoạt động uỷ quyền Matter. Do đó, các tệp Manifest và Gradle của tệp này phức tạp hơn so với những việc bổ sung cần thiết để chỉ sử dụng Thông tin xác thực luồng.
Thay đổi về tệp kê khai
<manifest xmlns:android="http://schemas.android.com/apk/res/android" (...) <!-- usesCleartextTraffic needed for OTBR local unencrypted communication --> <!-- Not needed for Thread Module, only used for HTTP --> <uses-feature (...) android:usesCleartextTraffic="true"> <application> (...) <!-- GPS automatically downloads scanner module when app is installed --> <!-- Not needed for Thread Module, only used for scanning QR Codes --> <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="barcode_ui"/> </application> </manifest>
Build.gradle
// Thread Network implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0' // Thread QR Code Scanning implementation 'com.google.android.gms:play-services-code-scanner:16.0.0' // Thread QR Code Generation implementation 'com.journeyapps:zxing-android-embedded:4.1.0' // Needed for using BaseEncoding class implementation 'com.google.guava:guava:31.1-jre'
Nội dung nhập có liên quan
// Thread Network Module import com.google.android.gms.threadnetwork.ThreadNetworkCredentials import com.google.android.gms.threadnetwork.ThreadBorderAgent import com.google.android.gms.threadnetwork.ThreadNetwork // Conversion of credentials to/fro Base16 (hex) import com.google.common.io.BaseEncoding // HTTP import java.io.BufferedInputStream import java.io.InputStream import java.net.HttpURLConnection import java.net.URL import java.nio.charset.StandardCharsets // Co-routines for HTTP calls import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch // JSON import org.json.JSONObject // Logs import timber.log.Timber // mDNS/SD import android.net.nsd.NsdServiceInfo // QR Code reader / writer import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions import com.google.mlkit.vision.codescanner.GmsBarcodeScanning import com.google.zxing.BarcodeFormat import com.google.zxing.MultiFormatWriter import com.journeyapps.barcodescanner.BarcodeEncoder
5. Phát hiện mDNS/SD
Ứng dụng mẫu của chúng tôi sử dụng chức năng khám phá mDNS/SD để tạo danh sách các Bộ định tuyến đường viền luồng có sẵn trong mạng, cũng như các BAID tương ứng.
Điều này rất hữu ích khi nhập thông tin của TBR của bạn vào bộ nhớ của thông tin xác thực GPS. Tuy nhiên, việc sử dụng thuộc tính này nằm ngoài phạm vi của lớp học lập trình này. Chúng tôi sử dụng thư viện Android Service Discovery NSDManager và mã nguồn đầy đủ có trong Ứng dụng mẫu, tại ServiceDiscovery.kt
.
6. Mối tương quan giữa các yếu tố
Sau khi triển khai các lệnh gọi này hoặc sử dụng Ứng dụng mẫu, bạn có thể hoàn toàn tham gia RPi OTBR của mình. Ứng dụng mẫu của chúng tôi có 8 nút:
Trình tự bạn có thể áp dụng để triển khai TBR là:
- Truy vấn xem có thông tin đăng nhập ưu tiên hay không (màu xanh dương, hàng đầu tiên)
- Tùy thuộc vào câu trả lời
- Nhận thông tin đăng nhập ưu tiên GPS (màu xanh lam, hàng thứ 2)
- Đặt thông tin xác thực TBR trong GPS (màu xanh lam, hàng thứ 3) -> Chọn TBR của bạn -> Tạo ngẫu nhiên -> Nhập tên mạng -> Tôi hiểu
- Bây giờ, bạn đã có thông tin đăng nhập ưu tiên, hãy đặt thông tin đăng nhập đó thành OTBR bằng cách sử dụng Đặt thông tin đăng nhập RPi OTBR. Phương pháp này sẽ áp dụng các thông tin đăng nhập đó vào tập hợp đang chờ xử lý.
Theo mặc định, ứng dụng mẫu sử dụng độ trễ 10 giây. Do đó, sau khoảng thời gian này, thông tin đăng nhập của RPi TBR (và các nút khác có thể tồn tại trên mạng của nó) sẽ di chuyển sang tập dữ liệu mới.
7. Kết luận
Trong lớp học lập trình này, chúng ta đã sao chép một Ứng dụng Android mẫu và phân tích một số đoạn mã sử dụng Dịch vụ Google Play Thread Storage API (API Lưu trữ luồng). Chúng tôi đã sử dụng các API đó để có một tập dữ liệu chung mà chúng tôi có thể triển khai trên RPi TBR, hiển thị TBR của một nhà cung cấp.
Việc có tất cả TBR của người dùng trong cùng một mạng sẽ giúp cải thiện khả năng phục hồi và phạm vi tiếp cận của Thread Network. Phiên bản này cũng ngăn chặn những hành trình có sai sót của người dùng mà trong đó ứng dụng không thể tích hợp Thread Devices vì ứng dụng không có quyền truy cập vào thông tin đăng nhập.
Chúng tôi hy vọng lớp học lập trình và Ứng dụng mẫu này sẽ giúp bạn thiết kế và phát triển Ứng dụng của riêng mình cũng như sản phẩm Bộ định tuyến đường viền Thread.
8. Tài liệu tham khảo
Đồng xử lý RCP
DBUS