DIY Thread Mesh Network Experiment
For a while I've been thinking to get bit more familiar with Thread mesh network protocol. Now finally during summer period I find the time to actually do this
Based on my understanding more or less everyone doing Thread development nowadays are using OpenThread, which is Google's open source implementation of Thread mesh network so it was my choice of protocol implementation to try for. Those wondering what is this Thread I am summarizing it to one sentence; Thread is low-power IPv6 based mesh network for IoT devices. If you are interested on knowing more what is Thread and how does it work you can read that for example from Thread Group's official website under "What is Thread" page.
As I had selected the protocol stack next step was to select the HW platform. OpenThread git repository includes port for example for Nordic Semi, NXP, TI and Silicon Labs SoC devices. For me natural choice was Silicon Labs, as I have bunch of their Thundeboard Sense 2 development kits available in my shelf. In OpenThread Silicon Labs port there is support directly for this board, so I would not need to do any HW adaptation implementation either.
Then next step was to get started, so starting to learn some documentation from openthread.io, especially pages "Get Started" and "Build OpenThread". But what the heck, on guides there is only mentioned how to build on Linux and Mac machines and at the moment I have only Windows 10 PC available. (I know many of you may think what the hell only Windows! What a noob guy! I know, but that's my reality at the moment) First thoughts OK, let's install some Linux distribution over virtual machine on Windows. And gladly find that Microsoft is even supporting directly Ubuntu virtual machine on their windows store. It supports only terminal / command line, but that should be enough for me, so let's install that.
Meanwhile downloading this Ubuntu app I started to read more about Docker. I had just heard what it is, tool to provide containers for developers to pack all required tools and dependencies to a single container which enables easily doing development on any machine running Docker. And that Docker is available for Windows as well. Immediate thought but do I then actually need Linux at all, wouldn't I be able to build the stuff on Docker container running on Windows? OK I'll install Docker on my Windows PC. While installing I read bit more and find out that Docker Desktop for Windows supports both Linux and Windows Docker containers and that Docker is using Windows native Hyper-V Virtualization and Networking. So seems Docker is doing already this virtualization for me, so no need for already installed Ubuntu terminal VM app.
When Docker was installed next step to follow instructions on earlier mentioned "Build OpenThread" page, so starting on pulling OpenThread container. As on the docker web site powershell is mentioned in example on using Docker on Windows I use that too.
>docker pull openthread/environment:latest
And now I have OpenThread environement on my PC, nice! Next step on build guide run docker environment (again in powershell)
>docker run -it --rm openthread/environment bash
Nice, seems I have bash terminal now opened for linux based OpenThread Docker container
root@24428794c898:/#
Going forward on the build OpenThread guide, run bootstrap script:
root@24428794c898:/# ./script/bootstrap
This seems to install required tools like GNU toolchain and other dependencies. Then again following build guide, running second phase of bootstrap which should set up the environment for building
root@24428794c898:/# ./bootstrap
All good so far. Next step is to actually build OpenThread example images for Thunderboard Sense 2. For that then moving to read build guide for EFR32MG12 which is the SoC in Thunderboard Sense 2 kit. According to this guide I would need to copy Silabs Flex SDK to my OpenThread environment. This SDK is distributed via Simplicity Studio IDE. Gladly I have that already installed as well as Flex SDK as well on my Windows 10. But I find a problem, how to copy the files from the windows file system to docker container. As I cannot see any of my local Windows file system in the docker container. After scratching my head I thought that this must be possible. Quick internet search led me to Docker documentation, page "Get Started with Docker for Windows" and there are chapters File Sharing and Shared Folders on Demand which explains how to do this. Seems I just need to -v option when starting the docker. So I exit the container by typing "exit" in bash command prompt. Now I am back in powershell prompt and restart the docker container with -v command (my Simplicity studio is in default installation location, if your differ you need to adjust accordingly)
>docker run -it --rm -v C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite:/gecko_sdk_suite openthread/environment bash
Now checking can I see gecko_sdk_suite folder in my container
root@af5e9dceb6d1:/# ls -l total 72 drwxr-xr-x 2 root root 4096 Jun 30 15:26 bin drwxr-xr-x 2 root root 4096 Apr 24 2018 boot drwxr-xr-x 5 root root 360 Jul 24 12:54 dev drwxr-xr-x 1 root root 4096 Jul 24 12:54 etc drwxrwxrwx 1 root root 4096 Jul 24 12:03 gecko_sdk_suite drwxr-xr-x 2 root root 4096 Apr 24 2018 home drwxr-xr-x 1 root root 4096 Jul 21 07:08 lib drwxr-xr-x 1 root root 4096 Jul 21 07:08 lib64 drwxr-xr-x 2 root root 4096 Jun 30 15:25 media drwxr-xr-x 2 root root 4096 Jun 30 15:25 mnt drwxr-xr-x 1 root root 4096 Jul 21 07:09 openthread drwxr-xr-x 2 root root 4096 Jun 30 15:25 opt dr-xr-xr-x 126 root root 0 Jul 24 12:54 proc drwx------ 1 root root 4096 Jul 7 03:25 root drwxr-xr-x 1 root root 4096 Jul 6 21:56 run drwxr-xr-x 1 root root 4096 Jul 6 21:56 sbin drwxr-xr-x 2 root root 4096 Jun 30 15:25 srv dr-xr-xr-x 12 root root 0 Jul 24 11:30 sys drwxrwxrwt 1 root root 4096 Jul 21 07:11 tmp drwxr-xr-x 1 root root 4096 Jul 21 07:09 usr drwxr-xr-x 1 root root 4096 Jun 30 15:26 var
And indeed gecko_sdk_suite folder is there. Excellent! Now I can move forward on teh EFR32BG12 build guide by copying or linking via symbolic link the Flex SDK to my container. I want to try linking to avoid spending time copying the files
root@6bff6543cc41:/# cd openthread/third_party/silabs/ root@6bff6543cc41:/openthread/third_party/silabs# mkdir gecko_sdk_suite root@6bff6543cc41:/openthread/third_party/silabs# ln -s /gecko_sdk_suite/v2.7 ./gecko_sdk_suite/v2.7 root@6bff6543cc41:/openthread/third_party/silabs# ls -l gecko_sdk_suite/ total 0 lrwxrwxrwx 1 root root 21 Jul 24 13:20 v2.7 -> /gecko_sdk_suite/v2.7 root@6bff6543cc41:/openthread/third_party/silabs#
So linking files in Linux container from mounted host Windows filesystem seems to work. Next step is building, just going first to OpenThread root folder
root@6bff6543cc41:/openthread/third_party/silabs# cd /openthread/ root@6bff6543cc41:/openthread# make -f examples/Makefile-efr32mg12 BOARD=BRD4166A
But this throws me an error. After "wondering in the dark and scratching my head" for a while I figured out that I closed the container after bootstrapping as I needed to restart it while mounting required gecko_sdk_suite. So let's try to do bootstrap again and then build again (note: I'm showing only the commands below, removing all prints made by bootstrap and build process)
root@6bff6543cc41:/openthread# ./script/bootstrap root@6bff6543cc41:/openthread# ./bootstrap root@6bff6543cc41:/openthread# make -f examples/Makefile-efr32mg12 BOARD=BRD4166A
Voila! Building succeeds and I can find binaries in output/efr32mg12/bin folder
root@6bff6543cc41:/openthread# ls -l output/efr32mg12/bin/ total 63132 -rwxr-xr-x 1 root root 12766256 Jul 24 13:33 ot-cli-ftd -rwxr-xr-x 1 root root 8666676 Jul 24 13:33 ot-cli-mtd -rwxr-xr-x 1 root root 12490508 Jul 24 13:33 ot-ncp-ftd -rwxr-xr-x 1 root root 8538388 Jul 24 13:33 ot-ncp-mtd -rwxr-xr-x 1 root root 1451892 Jul 24 13:33 ot-rcp -rwxr-xr-x 1 root root 12775596 Jul 24 13:33 sleepy-demo-ftd -rwxr-xr-x 1 root root 8678508 Jul 24 13:33 sleepy-demo-mtd
Next step is to give a try for one of the built image. Instead of trying to use GDB or JLink from the container, I would prefer to use Simplicity Commander tool which I already have on my Windows. Also I am not sure in which format the binaries are so I'll copy wanted binary on GNU toolchain objcopy to Intel HEX format and save it to gecko_sdk_suite folder I've mounted from my windows file system
root@6bff6543cc41:/openthread# arm-none-eabi-objcopy -O ihex output/efr32mg12/bin/ot-cli-ftd /gecko_sdk_suite/ot_cli_ftd.hex
At this point everything that needs to be done for this experiment in the build environment (docker container) is done. And as we learned that docker container does not save state it is good to figure out how to preserve the state. So that there is no need for next time to do all bootstrapping and linking the gecko_sdk_suite. After search I find out it can be done via docker commit command. To be able to do this open another powershell prompt and keep the docker run on the first one. On the second powershell first find ID of the running docker container
>docker ps
This lists all running containers and shows their ID. Well actually it is the same what you can see in the running container prompt after root@. So in my here case it is 6bff6543cc41. lets create a image now, again doing this in the second powershell
>docker commit 6bff6543cc41 myopenthread/efr32:v1
Now I can confirm the image has been created with command
>docker images
And indeed this lists all the container images including the original openthread one as well as my just take snapshot. Now I can close the running docker container (by typing exit in the bash prompt). How to start the stored container then, I'll try
docker run -it --rm -v C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite:/gecko_sdk_suite myopenthread/efr32:v1 bash
This opens up the stored container with the changes already made. for example output binaries are there and no bootstrapping required before building. Now everything is good in the development environment for the possible future needs. Next step is to flash built image to two Thunderboard Sense 2 boards with Simplicity Commander
After doing this and still having both connected to my PC via USB cable, I'll continue according to Run Example chapter on EFR32MG12 build guide. So open up terminal connection to both devices. You may use your favorite terminal program, I happen to have Termite installed so I use that one. First setting up one device as a network leader, note that you may need to wait for couple of seconds after "thread start" command before entering "state" command
> dataset init new Done > dataset Active Timestamp: 1 Channel: 26 Channel Mask: 07fff800 Ext PAN ID: b8cff6d34e87d126 Mesh Local Prefix: fdbb:d54e:8ac0:ce1f/64 Master Key: af0bd6952c867b3b8012d777d39d20bd Network Name: OpenThread-8f3d PAN ID: 0x8f3d PSKc: b079fb8b948ea0e9cb6c0db0a2cad2c7 Security Policy: 0, onrcb Done > dataset commit active Done > ifconfig up Done > thread start Done > state leader Done >
OK, so now I have network leader up and running. Then setting up the second device as a router for the same network by giving the Master Key of the leader device. As you can see below when I first typed "state" command, device was not yet managed to join the network but on second try it was
>dataset masterkey af0bd6952c867b3b8012d777d39d20bd Done > dataset commit active Done > routerselectionjitter 1 Done > ifconfig up Done > thread start Done > state detached Done > state router Done >
Just to make sure devices are in same network I also checked the neighbor tables. First from the leader
> neighbor table | Role | RLOC16 | Age | Avg RSSI | Last RSSI |R|S|D|N| Extended MAC | +------+--------+-----+----------+-----------+-+-+-+-+------------------+ | R | 0x8c00 | 16 | -21 | -21 |1|0|1|1| 4ea538a08e2e40cf | Done >
And from the router
> neighbor table | Role | RLOC16 | Age | Avg RSSI | Last RSSI |R|S|D|N| Extended MAC | +------+--------+-----+----------+-----------+-+-+-+-+------------------+ | R | 0x3c00 | 6 | -22 | -22 |1|0|1|1| 32301ae05e4a475f | Done >
So I have managed successfully to build OpenThread for Thunderboard Sense 2 and used the command line interface to set up a two device Thread network. Next step is to add more nodes, perhaps do some own simple application (for example temperature sensor) and perhaps get a border router to get access to and from internet. And perhaps have a look what Connected Home over IP (CHIP) project has managed to do so far. Stay tuned.
At the moment of writing I work for Arrow as Market Development Engineer focusing on Silicon Labs products. All thoughts and opinions expressed are my own not my employer’s.