Configuring openthread with random panid, channel

We are using:

NCS v1.9.1
nRF52840
openthread

We expect to operate in an environment with other Thread networks.  So, we would like to randomize the network credentials, and be able to change channels based on the environment.

Issue 1:

This application is for a commissioner, which will form the network.  We would like to configure this project so that, initially and after a factory reset, the network credentials (panid, channel, network key) are random.  In prf.conf, I can set 

CONFIG_OPENTHREAD_NETWORKKEY=""
and the network key is a new random string after a factory reset.  So, that's good.  How do you do that for panid and channel?
The channel and panid seem to be hard coded with defaults in .config.  The documentation about network forming suggest that these can be selected (best channel) or generated  randomly (panid) after a factory reset by an FTD.  How do I configure the project for that?
Issue 2:
Are there any examples or tutorials about changing channels dynamically.  I see that there is an api for that.
I tried including this code in main() at startup, but the channel remains at 25, as defined in prj.conf.
prj.conf (partial)
CONFIG_OPENTHREAD_NETWORKKEY=""
CONFIG_OPENTHREAD_PANID=23709
CONFIG_OPENTHREAD_CHANNEL=25
CONFIG_OPENTHREAD_CHANNEL_MONITOR=y
CONFIG_OPENTHREAD_CHANNEL_MANAGER=y
CONFIG_OPENTHREAD_COMMISSIONER=y
CONFIG_OPENTHREAD_FTD=y

CONFIG_OPENTHREAD_THREAD_STACK_SIZE=8192
CONFIG_OPENTHREAD_RADIO_WORKQUEUE_STACK_SIZE=2048
main()
	otInstance *instance = openthread_get_default_instance();
	otChannelManagerSetAutoChannelSelectionInterval(instance, 60);
	otChannelManagerSetSupportedChannels(instance, 0xFFFFFFFF);
    otChannelManagerSetAutoChannelSelectionEnabled(instance, true);
	printk("Openthread Channel Manager: delay = %d sec   supportedCh = 0x%x  favoredCh = 0x%x\r\n", 
			otChannelManagerGetDelay(instance),
			otChannelManagerGetSupportedChannels(instance),
			otChannelManagerGetFavoredChannels(instance) );
	//otChannelManagerRequestChannelChange(instance, 15);
	otChannelManagerRequestChannelSelect(instance, true);
Do the other devices on the network also change channels if one device does? 
What happens to SEDs when an FTD changes the selected channel?
Do all nodes save the new channel for use at the next power cycle?
Mary
Parents
  • Hi Mary,

    Issue 1

    For this you can use operational datasets. The PAN ID, network key, channel, etc. that are currently in use in the Thread network are part of the active operational dataset. So you can generate a new dataset at startup. For more information you can check out OpenThread CLI - Operational Datasets. This is the API for dataset related CLI commands, but it will show you examples of how to use datasets and what is possible. If you want to see the implementations of the different commands you can take a look at cli_dataset.cpp.

    Issue 2

    You can use datasets for this as well. Here I have changed the channel after the network has started using CLI commands:

    uart:~$ ot ifconfig up
    Done
    uart:~$ ot thread start
    Done
    uart:~$ ot channel
    17
    Done
    uart:~$ ot dataset channel 18
    Done
    uart:~$ ot dataset
    Active Timestamp: 1
    Channel: 18
    Channel Mask: 0x07fff800
    Ext PAN ID: 4e0df2adca0185e4
    Mesh Local Prefix: fdd0:8846:7301:7fb1::/64
    Network Key: 206a5182b5ce9c288d2035ece9f5cc54
    Network Name: OpenThread-15f2
    PAN ID: 0x15f2
    PSKc: 213933f7273435e7a3c9dd833660b53b
    Security Policy: 672 onrc
    Done
    uart:~$ ot channel
    17
    Done
    uart:~$ ot dataset commit active
    Done
    uart:~$ ot channel
    18
    Done

    Do the other devices on the network also change channels if one device does? 

    No, they will not automatically change channels. This is something you must implement in your application.

    What happens to SEDs when an FTD changes the selected channel?

    If the FTD is the SED's parent, the SED  will realize that it has lost connection to it's parent and initiate MLE Attach to try to reattach to the parent or another parent router.

    Best regards,

    Marte

  • I was able to achieve what I wanted for Issue 1 with this code at startup:

        // Network parameters
    	otOperationalDataset dataset;
    	if (!otDatasetIsCommissioned(openthread_get_default_context()))
    	{
    		printk("Thread not commissioned. Creating dataset.\r\n");
    		otDatasetCreateNewNetwork(openthread_get_default_context(), &dataset);
    
    		// Form a network name 
    		snprintk(dataset.mNetworkName.m8, sizeof(dataset.mNetworkName.m8), "MyNetwork");
    		dataset.mComponents.mIsNetworkNamePresent = true;
    		otDatasetSetActive(openthread_get_default_context(), &dataset);
    	}
    
    	error = otDatasetGetActive(openthread_get_default_context(), &dataset);
    	printk("Active Dataset: \r\n");
    	if (dataset.mComponents.mIsNetworkNamePresent)
        {
            printk("Network Name: ");
            printk("%s \r\n", dataset.mNetworkName.m8);
        }
    	if (dataset.mComponents.mIsChannelPresent)
        {
            printk("Channel: %d \r\n", dataset.mChannel);
        }
    	if (dataset.mComponents.mIsPanIdPresent)
        {
            printk("PAN ID: 0x%04x \r\n", dataset.mPanId);
        }
    
    	openthread_set_state_changed_cb(on_thread_state_changed);
    	openthread_start(openthread_get_default_context());

    I did several factory resets, and each time the channel, panid, and networkkey were different.

    Thanks,

    Mary

  • Hi Mary,

    That is great to hear, and thank you for sharing your solution!

    Best regards,

    Marte

Reply Children
No Data
Related