The Internet of Things nowadays features a lot of WiFI/Bluetooth powered applications and IoT cloud platforms, showcasing the endless possibilities IoT unlocks, for use cases and verticals like eHealth, Smart Cities, Home comfort, or heck! just having fun... but, the next IoT will be driven by actual requirements such as really ultra low-power operation down to micro-Amps, to actually enable everlasting applications that can run with few maintenance and unlock distributed applications to be deployed across a wide area, without having to deploy an extensive infrastructure to support it, for example in places which a large WiFI coverage area is not feasible.
Wireless Sensor Networks and M2M applications are long known: mesh networks with several hops between devices extends the coverage of applications, with few Internet-capable devices acting as Border Routers, to connect IEEE 802.15.4 wireless and low power networks to the Internet. Protocols like 6LoWPAN enables constrained devices to run IPv6 stacks, closing the gap between network domains, and actually making the deployment and maintenance of such networks an easy task, using common protocols on top as UDP, TCP, HTTP, MQTT, CoAP and others.
This project showcases a Zolertia Z1 mote sending HTTP POST to Ubidots, on 2.4GHz IEEE 802.15.4 wireless links on IPv6/6LoWPAN, to Ubidots IPv6 endpoint, creating an ultra low-power mesh network of embedded devices, capable of lasting up to 1-2 years on regular 2xAA batteries, with a wireless range of 100-200mts if using a cheap 5dBi external antenna.
Zolertia is widely supported in Contiki OS, an Open Source Operative System specifically designed for embedded devices, enabling to connect most objects and services to IPv4/IPv6. The source code used for this example can be found at my Contiki fork, under the branch ubidots-demo. The base example and Ubidots Contiki Library was created by George Oikonomou.
To create a local working copy open a terminal and:
git clone
https://github.com/alignan/contiki
cd contiki
git checkout -b ubidots-demo origin/ubidots-demo
To create the application (assuming you are using either Instant Contiki Virtual image with the toolchain already installed, or you have installed the toolchain), you will need to compile and flash 2 applications: the Border Router and the Ubidots client. Connect the Z1 motes to your host, and start programming.
To make sure the motes are connected, verify first using (on Linux)
dmesg | grep ttyUSB
Or using the built-in motelist script
cd examples/z1
make z1-motelist
It will show something like:
Reference Device Description
---------- ---------------- ----------------------------------------
Z1RC4841 /dev/ttyUSB0 Silicon Labs Zolertia Z1
cd examples/ipv6/rpl-border-router
make TARGET=z1 savetarget
make border-router.upload && make z1-reset && make connect-router
This will compile and flash the Border Router application to the connected Z1 mote (default at /dev/ttyUSB0 USB port). After being flashed, the command above will run the tunslip6 script, which will create a virtual interface such as your ethernet or WiFI, to connect your border router to your IP network. By default it uses a aaaa::/64
prefix, but if your network is IPv6-ready, you can use any IPv6 prefix with /64 mask as follows:
make connect-router PREFIX=2001:1234:dead:beef::baba/64
And the Border Router will be given the 2001:1234:dead:beef
prefix to setup its own IPv6 global address, and devices inside the network will use this prefix as well.
Take note of the addresses, it will be printed on screen (in this case the prefix given was aaaa::/64
):
Setting prefix aaaa::
Server IPv6 addresses:
aaaa::c30c:0:0:9e
fe80::c30c:0:0:9e
Close the connection using Ctrl+C
at any time, but the example require to leave the terminal open and running. To program the Ubidots client, open another terminal window.
You can execute the example from your host or using a Raspberry Pi, what I did over the Raspberry Pi was to connect a previously-programmed Z1 as Border Router, connect over the USB, then copy the tunslip6
script at contiki/tools
, and executed as follows:
sudo ./tunslip6 -s /dev/ttyUSB0 -t tun08 2001:1234:dead:beed::baba/64
The Ubidots client is configured to send Temperature readings from the Z1 mote built-in digital temperature sensor, and a sequence number every 15 seconds. You must provide your Ubidots short token (not the API key!), then create two variables and write down its ID, as shown in the Ubidots starter guide.
Move to the Ubidots example:
cd examples/ipv6/ubidots
Then at the Makefile
append to the UBIDOTS_WITH_AUTH_TOKEN=
line your short token, without using quotes! At the project-conf.h
file copy your Variable ID keys for UBIDOTS_DEMO_CONF_TEMPERATURE
and UBIDOTS_DEMO_CONF_SEQUENCE
, using quotes this time.
Note: you NEED the msp430-gcc 4.7 version and onwards for this example to work, else you will get an error related to not enough memory (see the comments section in this very own post for more info)
The compile and program the client:
make TARGET=z1 savetarget
make ubidots-demo.upload && make z1-reset && make login
The make login
command will create a serial connection between the Z1 mote and the screen, allowing you to visualize the debug information. Enabling the debug statement at the apps/ubidots/ubidots.c
library, by changing DEBUG_NONE
to DEBUG_PRINT
will print something like below:
Rime started with address 193.12.0.0.0.0.18.211
MAC c1:0c:00:00:00:00:12:d3 Contiki-2.6-2080-gc99beaa started. Node id is set to 4819.
CSMA nullrdc, channel check rate 128 Hz, radio channel 26
Tentative link-local IPv6 address fe80:0000:0000:0000:c30c:0000:0000:12d3
Starting 'Ubidots demo process'
Ubidots client: STATE_ERROR_NO_NET
Ubidots client: STATE_STARTING
Ubidots client: Checking things.ubidots.com
Ubidots client: 'Host: things.ubidots.com' (remaining 46)
Ubidots client: STATE_RESOLVING (1)
Ubidots client: Resolving things.ubidots.com
Ubidots client: STATE_RESOLVING (0)
Ubidots client: Entry for things.ubidots.com cached and usable.
Ubidots client: STATE_TCP_CONNECT (1)
Ubidots client: Connect 2607:f0d0:2101:39::2 port 80
event_callback: connected
Ubidots client: STATE_TCP_CONNECTED
Ubidots client: Prepare POST: Buffer at 197
Ubidots client: Enqueue value: Buffer at 208
Ubidots client: POST: Buffer at 209, content-length 13 (2), at 141
Ubidots client: POST: Buffer at 206
Ubidots client: STATE_POSTING (174)
(...)
Ubidots client: STATE_POSTING (14)
Ubidots client: STATE_POSTING (0)
Ubidots client: HTTP Reply 200
HTTP Status: 200
Ubidots client: New header: <Server: nginx>
Ubidots client: New header: <Date: Thu, 26 Mar 2015 13:54:25 GMT>
Ubidots client: New header: <Content-Type: application/json>
Ubidots client: New header: <Transfer-Encoding: chunked>
Ubidots client: New header: <Connection: keep-alive>
Ubidots client: New header: <Vary: Accept-Encoding>
Ubidots client: Client wants header 'Vary'
H: 'Vary: Accept-Encoding'
Ubidots client: New header: <Vary: Accept>
Ubidots client: Client wants header 'Vary'
H: 'Vary: Accept'
Ubidots client: New header: <Allow: GET, POST, HEAD, OPTIONS>
Ubidots client: Chunk, len 22: <[{"status_code": 201}]> (counter = 22)
Ubidots client: Chunk, len 0: <(End of Reply)> (Payload Length 22 bytes)
P: '[{"status_code": 201}]'
Ubidots client: Prepare POST: Buffer at 174
Ubidots client: Enqueue value: Buffer at 224
Ubidots client: Enqueue value: Buffer at 274
Ubidots client: POST: Buffer at 275, content-length 102 (3), at 118
Ubidots client: POST: Buffer at 273
Ubidots client: STATE_POSTING (273)
(...)
Ubidots client: STATE_POSTING (17)
Ubidots client: STATE_POSTING (0)
Ubidots client: HTTP Reply 200
HTTP Status: 200
Ubidots client: New header: <Server: nginx>
Ubidots client: New header: <Date: Thu, 26 Mar 2015 13:54:46 GMT>
Ubidots client: New header: <Content-Type: application/json>
Ubidots client: New header: <Transfer-Encoding: chunked>
Ubidots client: New header: <Connection: keep-alive>
Ubidots client: New header: <Vary: Accept-Encoding>
Ubidots client: Client wants header 'Vary'
H: 'Vary: Accept-Encoding'
Ubidots client: New header: <Vary: Accept>
Ubidots client: Client wants header 'Vary'
H: 'Vary: Accept'
Ubidots client: New header: <Allow: POST, OPTIONS>
Ubidots client: Chunk, len 44: <[{"status_code": 201}, {"status_code": 201}]> (counter = 44)
Ubidots client: Chunk, len 0: <(End of Reply)> (Payload Length 44 bytes)
P: '[{"status_code": 201}, {"status_code": 201}]'
Now we should have the Ubidots Client connected to Internet over the Border Router, we can verify at any time the Border Router routing table by opening its built-in webserver:
We can verify our devices are accessible over the Internet from anywhere in the world by using online ping services, as shown below I'm making an IPv6 ping to the Ubidots client, behind the Border Router:
And now the Ubidots variables should be updated every 15 seconds, you can choose from several dashboards available to visualize the results:
You can throw in more Z1 motes and see how the network scales and multi-hop is done, you can create as many variables at Ubidots, and publish more variables like the battery level, acceleration readings from the built-in 3-axis accelerometer in the Z1 mote, extend to more sensors such as soil moisture or relative humidity for greenhouse applications in outdoors, where you can even power the devices over solar panels or different energy harvesting methods.
Comments