使用带有 Android 事物的 nrf52840-Dongle 创建 LowPAN 网络
Creating LowPAN network with nrf52840-Dongle with Android Things
几周前我买了一个 Nordic nrf58240 USB Dongle
来尝试使用 lowpan API 但在 API 上将它与 LowPAN API 集成几乎没有成功=41=] 东西.
起初我尝试将它开箱即用,以查看它是否可以使用 lowpan 示例工作,但我无法连接它,并且在尝试连接时会在 onProvisionException
回调中出现 Provision Exception创建网络
所以我想让我买 nrf58240-DK 板,看看它是否有效,我按照 here 所述刷新了预构建的 ncp 图像,DK 板在 android 上工作得很好。
所以我多读了一些书,读到我可能必须手动构建一个图像,并设置了 BOOTLOADER 标志,所以我这样做了。
这是我对所有标志使用的命令
make -f examples/Makefile-nrf52840 clean
make -f examples/Makefile-nrf52840 USB=1 BOOTLOADER=1 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDF_FORWARD=1 LINK_RAW=1
arm-none-eabi-objcopy output/nrf52840/bin/ot-cli-ftd -O ihex cli.hex
我拿了那个 .hex 文件并用 windows 的 nrf connect programmer tool
将它闪存到加密狗。将它插回我的 raspberry pi 只是为了在尝试创建网络时仍然得到相同的 Provision 异常
这是我得到的异常
W/System.err: com.google.android.things.lowpan.LowpanException: android.net.lowpan.InterfaceDisabledException: android.os.ServiceSpecificException: InvalidWhenDisabled (code 3)
W/System.err: at com.google.android.things.lowpan.LowpanInterface$AsyncCallGlue.doInBackground(LowpanInterface.java:516)
W/System.err: at com.google.android.things.lowpan.LowpanInterface$AsyncCallGlue.doInBackground(LowpanInterface.java:508)
W/System.err: at android.os.AsyncTask.call(AsyncTask.java:333)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:245)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
W/System.err: at java.lang.Thread.run(Thread.java:764)
W/System.err: Caused by: android.net.lowpan.InterfaceDisabledException: android.os.ServiceSpecificException: InvalidWhenDisabled (code 3)
W/System.err: at android.net.lowpan.LowpanInterface.form(LowpanInterface.java:236)
W/System.err: at com.google.android.things.lowpan.LowpanInterface.run(LowpanInterface.java:587)
W/System.err: at com.google.android.things.lowpan.LowpanInterface$AsyncCallGlue.doInBackground(LowpanInterface.java:513)
W/System.err: ... 7 more
W/System.err: Caused by: android.os.ServiceSpecificException: InvalidWhenDisabled (code 3)
W/System.err: at android.os.Parcel.readException(Parcel.java:2027)
W/System.err: at android.os.Parcel.readException(Parcel.java:1959)
W/System.err: at android.net.lowpan.ILowpanInterface$Stub$Proxy.form(ILowpanInterface.java:810)
W/System.err: at android.net.lowpan.LowpanInterface.form(LowpanInterface.java:230)
W/System.err: ... 9 more
这是我的代码
class MainActivity2: Activity(){
private var lowpanInterface: LowpanInterface? = null
private var lowpanScanner: LowpanScanner? = null
private var lowpanDriver: UartLowpanDriver? = null
private var lowpanManager:LowpanManager? = null
private val TAG = "MainActivity2"
private var connectivityManager: ConnectivityManager? = null
private var network: Network? = null
private var backgroundHandlerThread: HandlerThread? = null
private var handler: Handler? = null
private var uiThreadHandler: Handler? = null
private var socket: Socket? = null
private val UART_PORT = "USB1-1.2:1.1"
private val UART_BAUD = 115200
private val SERVER_ADDRESS = "192.168.1.208"
private val SERVER_PORT = 23456
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lowpanManager = LowpanManager.getInstance()
lowpanManager?.registerCallback(managerCallback)
try {
lowpanDriver = UartLowpanDriver(UART_PORT, UART_BAUD)
lowpanDriver?.register()
Log.d(TAG,"Lowpan Connected")
} catch (e: Exception) {
e.printStackTrace()
}
uiThreadHandler = Handler(Looper.getMainLooper())
}
override fun onDestroy() {
super.onDestroy()
stopNetworkScan()
// Detach from any network we might be attached to.
lowpanInterface?.unregisterCallback(callback)
lowpanInterface?.leave()
lowpanInterface = null
lowpanDriver?.unregister()
lowpanDriver?.close()
lowpanDriver = null
}
private fun scanForNetworks() {
val params = lowpanInterface?.getLowpanProvisioningParams(false)
if(params?.lowpanIdentity?.name == "MeshNetwork"){
return
}
lowpanScanner = lowpanInterface?.createScanner()?.apply {
setCallback(scanner)
startNetScan()
}
}
private fun stopNetworkScan() {
lowpanScanner?.stopNetScan()
}
private fun createNetwork(){
/* We are only specifying the network name here. By
* doing this we allow the interface to pick reasonable
* defaults for other required fields. If we specified
* our own values for those fields, they would be used
* instead.
*/
val identity = LowpanIdentity.Builder()
.setName("MeshNetwork")
.build()
/* Not specifying a LowpanCredential here tells “form()”
* that we want the interface to generate the master key
* for us.
*/
val provision = LowpanProvisioningParams.Builder().setLowpanIdentity(identity).build()
try{
lowpanInterface?.form(provision)
Log.d(TAG,"Network created")
}catch (e:LowpanException){
e.printStackTrace()
}catch (e:LowpanRuntimeException){
e.printStackTrace()
}
}
private fun resetNetwork() {
connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_LOWPAN)
.build()
backgroundHandlerThread = HandlerThread("BackgroundThread")
backgroundHandlerThread!!.start()
handler = Handler(backgroundHandlerThread!!.looper)
connectivityManager!!.registerNetworkCallback(networkRequest,networkCallback, uiThreadHandler)
}
private val scanner = object : LowpanScanner.Callback(){
override fun onNetScanBeacon(beacon: LowpanBeaconInfo) {
val network = beacon.lowpanIdentity
if(network.name == "MeshNetwork"){
joinNetwork(beacon)
}
}
override fun onScanFinished() {
// Release a semaphore
Log.d(TAG,"Scan Finished")
}
}
private val managerCallback = object:LowpanManager.Callback(){
override fun onInterfaceAdded(lowpan_interface: LowpanInterface?) {
super.onInterfaceAdded(lowpan_interface)
lowpanInterface = lowpan_interface
lowpanManager?.let {
Log.d(TAG,"resetting network")
resetNetwork()
Log.d(TAG,"register callback")
lowpanInterface?.registerCallback(callback)
createNetwork()
}
}
override fun onInterfaceRemoved(lowpan_interface: LowpanInterface?) {
super.onInterfaceRemoved(lowpan_interface)
}
}
private val callback = object : LowpanInterface.Callback() {
override fun onStateChanged(state: Int) {
super.onStateChanged(state)
when (state){
LowpanInterface.STATE_ATTACHED -> Log.d(TAG,"Attached")
LowpanInterface.STATE_ATTACHING -> Log.d(TAG,"Attaching")
LowpanInterface.STATE_DISABLED -> Log.d(TAG,"Disabled")
LowpanInterface.STATE_FAULT -> Log.d(TAG,"Fault")
LowpanInterface.STATE_OFFLINE -> Log.d(TAG,"Offline")
}
/* Handle interface state changes. */
}
override fun onLowpanIdentityChanged(identity: LowpanIdentity?) {
super.onLowpanIdentityChanged(identity)
Log.d(TAG,"Identity changed")
Log.d(TAG,"Name: ${identity?.name}")
Log.d(TAG,"Channel: ${identity?.channel}")
Log.d(TAG,"Is Valid: ${identity?.isNameValid}")
Log.d(TAG,"Panid: ${identity?.panid}")
Log.d(TAG,"Raw Name: ${identity?.rawName}")
Log.d(TAG,"Xpanid: ${identity?.xpanid}")
/* Form, join, or leave completed successfully. */
}
override fun onProvisionException(exception: Exception?) {
super.onProvisionException(exception)
exception?.printStackTrace()
/* An error occurred during form or join. */
}
}
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
}
override fun onLost(network: Network) {
}
}
}
我需要以不同的方式闪烁 Dongle
吗?
也许 Dongle
不受支持?
目前还不确定问题是什么
发现问题,我实际上使用了错误类型的图像 ot-cli-ftd
而我需要的是 ot-ncp-ftd
所以命令
arm-none-eabi-objcopy output/nrf52840/bin/ot-cli-ftd -O ihex cli.hex
改为
arm-none-eabi-objcopy output/nrf52840/bin/ot-ncp-ftd -O ihex ncp.hex
如 Android 事物
的文档中所述
To develop LoWPAN applications, you will need a radio module running
as an OpenThread Network Co-Processor (NCP)
几周前我买了一个 Nordic nrf58240 USB Dongle
来尝试使用 lowpan API 但在 API 上将它与 LowPAN API 集成几乎没有成功=41=] 东西.
起初我尝试将它开箱即用,以查看它是否可以使用 lowpan 示例工作,但我无法连接它,并且在尝试连接时会在 onProvisionException
回调中出现 Provision Exception创建网络
所以我想让我买 nrf58240-DK 板,看看它是否有效,我按照 here 所述刷新了预构建的 ncp 图像,DK 板在 android 上工作得很好。
所以我多读了一些书,读到我可能必须手动构建一个图像,并设置了 BOOTLOADER 标志,所以我这样做了。
这是我对所有标志使用的命令
make -f examples/Makefile-nrf52840 clean
make -f examples/Makefile-nrf52840 USB=1 BOOTLOADER=1 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDF_FORWARD=1 LINK_RAW=1
arm-none-eabi-objcopy output/nrf52840/bin/ot-cli-ftd -O ihex cli.hex
我拿了那个 .hex 文件并用 windows 的 nrf connect programmer tool
将它闪存到加密狗。将它插回我的 raspberry pi 只是为了在尝试创建网络时仍然得到相同的 Provision 异常
这是我得到的异常
W/System.err: com.google.android.things.lowpan.LowpanException: android.net.lowpan.InterfaceDisabledException: android.os.ServiceSpecificException: InvalidWhenDisabled (code 3)
W/System.err: at com.google.android.things.lowpan.LowpanInterface$AsyncCallGlue.doInBackground(LowpanInterface.java:516)
W/System.err: at com.google.android.things.lowpan.LowpanInterface$AsyncCallGlue.doInBackground(LowpanInterface.java:508)
W/System.err: at android.os.AsyncTask.call(AsyncTask.java:333)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:245)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
W/System.err: at java.lang.Thread.run(Thread.java:764)
W/System.err: Caused by: android.net.lowpan.InterfaceDisabledException: android.os.ServiceSpecificException: InvalidWhenDisabled (code 3)
W/System.err: at android.net.lowpan.LowpanInterface.form(LowpanInterface.java:236)
W/System.err: at com.google.android.things.lowpan.LowpanInterface.run(LowpanInterface.java:587)
W/System.err: at com.google.android.things.lowpan.LowpanInterface$AsyncCallGlue.doInBackground(LowpanInterface.java:513)
W/System.err: ... 7 more
W/System.err: Caused by: android.os.ServiceSpecificException: InvalidWhenDisabled (code 3)
W/System.err: at android.os.Parcel.readException(Parcel.java:2027)
W/System.err: at android.os.Parcel.readException(Parcel.java:1959)
W/System.err: at android.net.lowpan.ILowpanInterface$Stub$Proxy.form(ILowpanInterface.java:810)
W/System.err: at android.net.lowpan.LowpanInterface.form(LowpanInterface.java:230)
W/System.err: ... 9 more
这是我的代码
class MainActivity2: Activity(){
private var lowpanInterface: LowpanInterface? = null
private var lowpanScanner: LowpanScanner? = null
private var lowpanDriver: UartLowpanDriver? = null
private var lowpanManager:LowpanManager? = null
private val TAG = "MainActivity2"
private var connectivityManager: ConnectivityManager? = null
private var network: Network? = null
private var backgroundHandlerThread: HandlerThread? = null
private var handler: Handler? = null
private var uiThreadHandler: Handler? = null
private var socket: Socket? = null
private val UART_PORT = "USB1-1.2:1.1"
private val UART_BAUD = 115200
private val SERVER_ADDRESS = "192.168.1.208"
private val SERVER_PORT = 23456
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lowpanManager = LowpanManager.getInstance()
lowpanManager?.registerCallback(managerCallback)
try {
lowpanDriver = UartLowpanDriver(UART_PORT, UART_BAUD)
lowpanDriver?.register()
Log.d(TAG,"Lowpan Connected")
} catch (e: Exception) {
e.printStackTrace()
}
uiThreadHandler = Handler(Looper.getMainLooper())
}
override fun onDestroy() {
super.onDestroy()
stopNetworkScan()
// Detach from any network we might be attached to.
lowpanInterface?.unregisterCallback(callback)
lowpanInterface?.leave()
lowpanInterface = null
lowpanDriver?.unregister()
lowpanDriver?.close()
lowpanDriver = null
}
private fun scanForNetworks() {
val params = lowpanInterface?.getLowpanProvisioningParams(false)
if(params?.lowpanIdentity?.name == "MeshNetwork"){
return
}
lowpanScanner = lowpanInterface?.createScanner()?.apply {
setCallback(scanner)
startNetScan()
}
}
private fun stopNetworkScan() {
lowpanScanner?.stopNetScan()
}
private fun createNetwork(){
/* We are only specifying the network name here. By
* doing this we allow the interface to pick reasonable
* defaults for other required fields. If we specified
* our own values for those fields, they would be used
* instead.
*/
val identity = LowpanIdentity.Builder()
.setName("MeshNetwork")
.build()
/* Not specifying a LowpanCredential here tells “form()”
* that we want the interface to generate the master key
* for us.
*/
val provision = LowpanProvisioningParams.Builder().setLowpanIdentity(identity).build()
try{
lowpanInterface?.form(provision)
Log.d(TAG,"Network created")
}catch (e:LowpanException){
e.printStackTrace()
}catch (e:LowpanRuntimeException){
e.printStackTrace()
}
}
private fun resetNetwork() {
connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_LOWPAN)
.build()
backgroundHandlerThread = HandlerThread("BackgroundThread")
backgroundHandlerThread!!.start()
handler = Handler(backgroundHandlerThread!!.looper)
connectivityManager!!.registerNetworkCallback(networkRequest,networkCallback, uiThreadHandler)
}
private val scanner = object : LowpanScanner.Callback(){
override fun onNetScanBeacon(beacon: LowpanBeaconInfo) {
val network = beacon.lowpanIdentity
if(network.name == "MeshNetwork"){
joinNetwork(beacon)
}
}
override fun onScanFinished() {
// Release a semaphore
Log.d(TAG,"Scan Finished")
}
}
private val managerCallback = object:LowpanManager.Callback(){
override fun onInterfaceAdded(lowpan_interface: LowpanInterface?) {
super.onInterfaceAdded(lowpan_interface)
lowpanInterface = lowpan_interface
lowpanManager?.let {
Log.d(TAG,"resetting network")
resetNetwork()
Log.d(TAG,"register callback")
lowpanInterface?.registerCallback(callback)
createNetwork()
}
}
override fun onInterfaceRemoved(lowpan_interface: LowpanInterface?) {
super.onInterfaceRemoved(lowpan_interface)
}
}
private val callback = object : LowpanInterface.Callback() {
override fun onStateChanged(state: Int) {
super.onStateChanged(state)
when (state){
LowpanInterface.STATE_ATTACHED -> Log.d(TAG,"Attached")
LowpanInterface.STATE_ATTACHING -> Log.d(TAG,"Attaching")
LowpanInterface.STATE_DISABLED -> Log.d(TAG,"Disabled")
LowpanInterface.STATE_FAULT -> Log.d(TAG,"Fault")
LowpanInterface.STATE_OFFLINE -> Log.d(TAG,"Offline")
}
/* Handle interface state changes. */
}
override fun onLowpanIdentityChanged(identity: LowpanIdentity?) {
super.onLowpanIdentityChanged(identity)
Log.d(TAG,"Identity changed")
Log.d(TAG,"Name: ${identity?.name}")
Log.d(TAG,"Channel: ${identity?.channel}")
Log.d(TAG,"Is Valid: ${identity?.isNameValid}")
Log.d(TAG,"Panid: ${identity?.panid}")
Log.d(TAG,"Raw Name: ${identity?.rawName}")
Log.d(TAG,"Xpanid: ${identity?.xpanid}")
/* Form, join, or leave completed successfully. */
}
override fun onProvisionException(exception: Exception?) {
super.onProvisionException(exception)
exception?.printStackTrace()
/* An error occurred during form or join. */
}
}
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
}
override fun onLost(network: Network) {
}
}
}
我需要以不同的方式闪烁 Dongle
吗?
也许 Dongle
不受支持?
目前还不确定问题是什么
发现问题,我实际上使用了错误类型的图像 ot-cli-ftd
而我需要的是 ot-ncp-ftd
所以命令
arm-none-eabi-objcopy output/nrf52840/bin/ot-cli-ftd -O ihex cli.hex
改为
arm-none-eabi-objcopy output/nrf52840/bin/ot-ncp-ftd -O ihex ncp.hex
如 Android 事物
的文档中所述To develop LoWPAN applications, you will need a radio module running as an OpenThread Network Co-Processor (NCP)