Objective
I have a sensor node CM5000, which is compatible with a sky mote, and want to use it to send temperature data to the cloud service Ubidots. Currently, the node is working with the operating system Contiki-OS, specifically i am working with Instant-contiki-3.0.
I did some research and the web page below gives you the steps to send temperature data to Ubidots using a Z1 mote. I follow the steps of the web page, but since the sky mote is not compatible with a Z1 mote then it does not work.
http://wireless.ictp.it/school_2015/book/#_sending_data_to_ubidots
Here, i will show you how to send data to Ubidots using Sky motes modifying the code from the web page above.
Step 1: Create an account in Ubidots
- Create a Data Source by clicking
Sources -> Add Data Source -> Generic -> Create
Now, you must have a data source named My Datasource.
- Create a variable by clicking
Sources -> My Datasource -> Add Variable -> Name = Temperature -> Create
Now, you must have a variable named Temperature.
- Keep in mind the variable's ID: Click in
Sources -> My Datasource
Each variable at the top right-hand corner have an i, and if you click it, then it will show you the variable's ID. My variable's ID is:
567a05d07625424d60d32a31
- Keep in mind your API Key: Click in
My Profile -> API Keys
There you will find your API Key. My API Key is:
2eed47ae4097bbbfd26ae57c8eb799cc450d0416
- Create a Dashboard by clicking
Dashboard -> + -> Line Chart -> My Datasource -> Temperature -> Finish
Step 2: Create the serial-ubidots App
- Go to the folder /contiki-3.0/apps
cd /home/user/contiki-3.0/apps
- Create a folder named serial-ubidots
- Within that folder, you must create a Makefile named Makefile.serial-ubidots with the following code in it:
serial-ubidots_src = serial-ubidots.c
- Within that folder, you must create a file named serial-ubidots.c with the following code in it:
#include
#include "serial-ubidots.h" void send_to_ubidots(const char *api, const char *id, uint16_t val) // api = API KEY, ID = Variable's ID, Val = Value of temperature { unsigned char buf[6]; snprintf(buf, 6, "%d", val); printf("***%s\t", api); // The *** indicate the start of the data sent to Ubidots printf("%s\t", id); printf("%s***\n", buf); // The *** indicate the end of the data sent to Ubidots } - Within that folder, you must create a file named serial-ubidots.h with the following code in it:
#define VAR_LEN 24 #define UBIDOTS_MSG_LEN (VAR_LEN + 2) struct ubidots_msg_t { char var_key[VAR_LEN]; uint8_t value[2]; }; void send_to_ubidots(const char *api, const char *id, uint16_t val);
- Include the serial-ubidots App in the makefile of sky motes: Go to the folder /home/user/contiki-3.0/examples/sky
cd /home/user/contiki-3.0/examples/sky
Open the Makefile and add the following line
APPS=serial-ubidots
Now, the Makefile should look like this
CONTIKI = ../.. ifndef TARGET TARGET=sky endif all: blink sky-collect #rt-leds test-button test-cfs tcprudolph0 APPS=serial-ubidots %.tgz: %.ihex mkdir $(basename $<) ; \ mv $< $(basename $<) ; \ echo $(basename $<)/$(basename $<).ihex 600 > $(basename $<)/runfile ; \ tar czf $@ $(basename $<) CONTIKI_WITH_IPV4 = 1 CONTIKI_WITH_RIME = 1 include $(CONTIKI)/Makefile.include
Step 3: Create a contiki C file that reads the temperature and send it to the serial port via the serial-ubidots app previously created
- Go to the folder /home/user/contiki-3.0/examples/sky
cd /home/user/contiki-3.0/examples/sky
Create a file named temperature.c with the following code in it
#include "contiki.h" #include "dev/sht11/sht11-sensor.h" #include "dev/light-sensor.h" #include "dev/leds.h" #include
#include "serial-ubidots.h" //Declare the process PROCESS(send_sensor_info_process, "Print the Sensors Information"); //Make the process start when the module is loaded AUTOSTART_PROCESSES(&send_sensor_info_process); static uint16_t get_temp(void) { return ((sht11_sensor.value(SHT11_SENSOR_TEMP) / 10) - 396) / 10; } /*---------------------------------------------------------------------------*/ //Define the process code PROCESS_THREAD(send_sensor_info_process, ev, data) { static struct etimer et; static const char api_key[] = "2eed47ae4097bbbfd26ae57c8eb799cc450d0416"; // This is your API Key previously copied from Ubidots static const char var_key[] = "567a05d07625424d60d32a31"; // This is your variable's ID previously copied from Ubidots PROCESS_BEGIN(); uint16_t raw; while(1){ etimer_set(&et, CLOCK_SECOND * 15); SENSORS_ACTIVATE(sht11_sensor); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); raw = get_temp() ; send_to_ubidots(api_key, var_key, raw); etimer_reset(&et); SENSORS_DEACTIVATE(sht11_sensor); } PROCESS_END(); } - Upload the temperature.c code into the sky mote and login with the following command:
make TARGET=sky temperature.upload && make login
Then, you should be able to see this in the terminal every 15 seconds
***2eed47ae4097bbbfd26ae57c8eb799cc450d0416 567a05d07625424d60d32a31 29***
That means that the sky mote is sending over the /dev/ttyUSB0/ the following information
*** = Indicates start of frame 2eed47ae4097bbbfd26ae57c8eb799cc450d0416 = Api Key \t = Tab key to separate data 567a05d07625424d60d32a31 = Variable's ID \t = Tab key to separate data 29 = Temperature (Celsius) *** = Indicates end of frame
Step 4: Create a Python Script to read the data from the serial port and send it to Ubidots
- Install Python in your computer
sudo apt-get install build-essential checkinstall sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev cd ~/Downloads/ wget http://python.org/ftp/python/2.7.5/Python-2.7.5.tgz tar -xvf Python-2.7.5.tgz cd Python-2.7.5 ./configure make
- Install pip in Linux
sudo easy_install pip
- Install the Python library Ubidots for python
sudo pip install ubidots==1.6.1
- Go to the folder /home/user/contiki-3.0/examples/sky
cd /home/user/contiki-3.0/examples/sky
- Create a file named UbidotsPython.py with the following code in it:
# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------# # Simple application to relay data to Ubidots from a Contiki serial-based conn # ----------------------------------------------------------------------------# import serial from time import sleep from ubidots import ApiClient # Use as default PORT = "/dev/ttyUSB0" # ----------------------------------------------------------------------------# # Create a serial object and connect to mote over USB # ----------------------------------------------------------------------------# def connectMote(port): try: ser = serial.Serial(port, 115200,timeout=0, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) except: sys.exit("Error connecting to the USB device, aborting") return ser # ----------------------------------------------------------------------------# # Parse the serial data and publish to Ubidots, this assumes the following: # \r\n API_KEY \t VAR_KEY \t VALUE \r\n # ----------------------------------------------------------------------------# def process_data(raw): # Search for start and end of frame and slice, discard incomplete if "***" in raw: raw = raw[(raw.index("***") + 3):] if "***" in raw: raw = raw[:raw.index("***")] # We should have a full frame, parse based on tab and create a list ubidots_raw = raw.split("\t") # Create a Ubidots client and get a pointer to the variable client = ApiClient(ubidots_raw[0]) try: my_variable = client.get_variable(ubidots_raw[1]) except Exception, e: print "Ubidots error: %s" % e return # Update the variable my_variable.save_value({'value':int(ubidots_raw[2])}) # ----------------------------------------------------------------------------# # MAIN APP # ----------------------------------------------------------------------------# if __name__=='__main__': # Create the serial object and connect to the mode # Do not check the serial port object as the function already does it s = connectMote(PORT) # Loop forever and wait for serial data while True: queue = s.inWaiting() if queue > 0: data = s.read(1000) process_data(data) sleep(0.2)
Step 5:Send data to Ubidots
- Go to the folder /home/user/contiki-3.0/examples/sky
cd /home/user/contiki-3.0/examples/sky
- Upload the temperature.c code
make TARGET=sky temperature.upload
- Execute the script UbidotsPython.py
python UbidotsPython.py
Wait approximately 15 seconds for the first data to appear in the dashboard of Ubidots.
can we do this for other motes like z1 mote(cc2538 soc based)
ReplyDeleteHi Sergio,
ReplyDeleteNICE topics! Thanks for sharing.
I'm try to do something similar.
I'm tried to send sky mote data to ibm cloud service without sucess till now.
I have 4 sky motes and one RPI.
- 1 sky mote as border router connected to RPI3 with tunslip6 (sudo ./tunslip6 212:7400:13e3::1/64 -t tun0 -s /dev/ttyUSB0)
- 3 sky motes with contiki example ipv6/sky-websense.c
Now you know how i can get the data from the sensors on python ? to further send the data to cloud service ?
Is possible to use MQTT on sky motes?
I tried to modify this example for mote Z1 :
https://github.com/contiki-os/contiki/tree/master/examples/nrf52dk/mqtt-demo
But without sucess... :_(