Создание сети LowPAN с помощью nrf52840-Dongle с Android Things - PullRequest
0 голосов
/ 18 января 2019

Я купил Nordic nrf58240 USB Dongle несколько недель назад, чтобы попытаться поиграть с lowpan API, но практически не смог его интегрировать с LowPAN API на устройствах Android.

Сначала я попытался подключить его из коробки, чтобы увидеть, работает ли он на примере lowpan, и я не смог подключить его и получал исключение Provision в обратном вызове onProvisionException при попытке создать сеть

Итак, я подумал, что позвольте мне купить платы nrf58240-DK и посмотреть, работает ли это, я прошил предварительно встроенный образ 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 и прошил его ключом с 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$2.call(AsyncTask.java:333)
W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err:     at android.os.AsyncTask$SerialExecutor$1.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$1.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 не поддерживается?

Не уверен, что проблема на данный момент действительно

1 Ответ

0 голосов
/ 18 января 2019

Обнаружил проблему, я на самом деле использовал неправильный тип изображения 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 Things

Для разработки приложений LoWPAN вам понадобится работающий радиомодуль в качестве сетевого сопроцессора OpenThread (NCP)

...