Difference between revisions of "Online Thermometer"

From Wiki Makespace Madrid
Jump to: navigation, search
(2nd Step: Connect Arduino and 'imp' through a voltage converter)
(Aim)
 
(31 intermediate revisions by 2 users not shown)
Line 9: Line 9:
  
 
=== Aim ===
 
=== Aim ===
Post online the temperature of a thermometer through the cloud servers of ElectricImp, Carriots and Ducksboard
+
Read the temperature from a sensor and post it online through the cloud servers of ElectricImp, Carriots and Ducksboard
  
[[File:Flow_eImp_carriots_ducksboard.jpg]]
+
[[File:Flow eImp carriots ducksboard en.jpg|860px]]
 +
 
 +
[[File:HW_Temperature_eImp.JPG|860px]]
  
 
=== Motivation ===
 
=== Motivation ===
Line 32: Line 34:
 
The project publishes online the temperature readings obtained from a DHT11 sensor.
 
The project publishes online the temperature readings obtained from a DHT11 sensor.
  
* The reading is obtained by through an Arduino (Arduino is used because the current version of electricImp does not support the proprietary protocol of the DHT11 sensor). Temperature is read once a minute
+
* The reading is obtained through an Arduino (Arduino is used because the current version of electricImp does not support the proprietary protocol of the DHT11 sensor). The temperature is read once a minute
* The temperature reading is passed to an imp device that forwards it to an agent in the cloud server of ElectricImp
+
* The temperature reading is passed to an imp device that forwards it to an agent in the cloud server of electricImp
 
* The agent sends the reading to Carriots through its http REST API. Carriots is used to keep the historical series of all measured temperature values
 
* The agent sends the reading to Carriots through its http REST API. Carriots is used to keep the historical series of all measured temperature values
 
* When Carriots server receives a new temperature reading, a "listener" makes a new http REST request towards Ducksboard server to update a "dashboard" that displays the latest temperature values received
 
* When Carriots server receives a new temperature reading, a "listener" makes a new http REST request towards Ducksboard server to update a "dashboard" that displays the latest temperature values received
Line 40: Line 42:
  
 
==== 1st Step: Read the temperature value from Arduino and pass it to 'imp' device ====
 
==== 1st Step: Read the temperature value from Arduino and pass it to 'imp' device ====
The DHT11 temperature sensor is very easy to use but it is not "compatible" with the imp HW due to the proprietary protocol of the sensor. Additionally,  it runs at 5V while the 'imp' works at 3.3V. electricImp recommends using an intermediate micro (arduino) to read the temperature and then forward the reading to the imp through a serial connection [http://forums.electricimp.com/discussion/comment/7224#Comment_7224]
+
The DHT11 temperature sensor is very easy to use but it is not "compatible" with the imp HW due to the proprietary protocol of the sensor. Additionally,  it runs at 5V while the imp works at 3.3V. electricImp recommends using an intermediate micro (arduino) to read the temperature and then forward the reading to the imp through a serial connection [http://forums.electricimp.com/discussion/comment/7224#Comment_7224]
  
 
The temperature is read from Arduino using a library and sketch written by Rob Tilliart [http://arduino-info.wikispaces.com/DHT11-Humidity-TempSensor]. The link describes how to install and use the [http://arduino-info.wikispaces.com/file/view/DHT11.zip/390039522/DHT11.zip library] from Arduino IDE.
 
The temperature is read from Arduino using a library and sketch written by Rob Tilliart [http://arduino-info.wikispaces.com/DHT11-Humidity-TempSensor]. The link describes how to install and use the [http://arduino-info.wikispaces.com/file/view/DHT11.zip/390039522/DHT11.zip library] from Arduino IDE.
  
'''Note:''' The DHT11 sensor shown in the previous link has four PINs on the bottom. However the PCB mounted version sold by DealeXtreme [http://dx.com/p/arduino-digital-temperature-humidity-sensor-module-121350] has only 3 PINs. The following picture describes the function of each PIN:
+
'''Note:''' The DHT11 sensor shown in the previous link has four PINs at the bottom. However the PCB mounted version sold by DealeXtreme [http://dx.com/p/arduino-digital-temperature-humidity-sensor-module-121350] has only 3 PINs. The following picture describes the function of each PIN:
  
 
[[File:DHT11.jpg]]
 
[[File:DHT11.jpg]]
  
The Arduino sketch simply reads the temperature from ''DHT11PIN'' (digital pin 2 of the Arduino) and sends the read value through a serial connection (Arduino digital PINs 7 and 8: ''SoftwareSerial eImpSerial(7, 8)''). A special code (byte ''0xFC'') is sent after the temperature value to inform to the other end of the serial connection (the 'imp') that a new value is available.
+
The Arduino sketch simply reads the temperature from ''DHT11PIN'' (digital pin 2 of the Arduino) and sends the read value through a serial connection (Arduino digital PINs 7 and 8: ''SoftwareSerial eImpSerial(7, 8)''). A special code (byte ''0xFC'') is sent after the temperature value to inform to the other end of the serial connection (the imp device) that a new value is available.
  
After forwarding the temperature reading to the 'imp', arduino waits for a minute (60000 milliseconds) until the next reading.
+
After forwarding the temperature reading to the imp, arduino waits for a minute (60000 milliseconds) until the next reading.
  
  
Line 96: Line 98:
 
==== 2nd Step:  Connect Arduino and 'imp' through a voltage converter ====
 
==== 2nd Step:  Connect Arduino and 'imp' through a voltage converter ====
  
'imp' works at 3.3V while Arduino works at 5V. You cannot connect their PINs directly because you could burn the 'imp' with the higher voltage generated by Arduino. The solution is to connect them through an intermediate voltage converter. This porject has chosen Sparkfun converter [https://www.sparkfun.com/products /11978] but any other similar convertter could be used. There is a tutorial on Sparkfun website that explains how this component works. It also includes an example showing how to wire a serial connection between Arduino and electricImp [https://learn.sparkfun.com/tutorials/using-the-logic-level-converter/hookup-examples "Using the LLC for Serial" paragraph]. Make connections as shown in the [https://dlnmh9ip6v2uc.cloudfront.net/assets/b/1/c/8/e/52275e89757b7fcd1b8b4567.png picture] but keep in mind that our Arduino uses pins 7 and 8 for the serial connection. Wires coming out of 0/RX0 (green) and 1/TX0 (yellow) should come out of PINs 7 and 8.
+
The imp device works at 3.3V while Arduino works at 5V. You cannot connect their PINs directly because you could burn the 'imp' with the higher voltage generated by Arduino. The solution is to connect them through an intermediate voltage converter. This project has chosen a Sparkfun converter [https://www.sparkfun.com/products/11978] but any other similar converter could be used. There is a tutorial on Sparkfun website that explains how this component works. It also includes an example showing how to wire a serial connection between Arduino and electricImp [https://learn.sparkfun.com/tutorials/using-the-logic-level-converter/hookup-examples "Using the LLC for Serial" paragraph]. Make connections as shown in the [https://dlnmh9ip6v2uc.cloudfront.net/assets/b/1/c/8/e/52275e89757b7fcd1b8b4567.png picture] but keep in mind that our Arduino uses pins 7 and 8 for the serial connection. Wires coming out of 0/RX0 (green) and 1/TX0 (yellow) should come out of PINs 7 and 8.
  
 
'''Important:''' Arduino serial connection uses pins 7 and 8 (not pins 0 and 1)
 
'''Important:''' Arduino serial connection uses pins 7 and 8 (not pins 0 and 1)
  
==== 3er Paso: Crear una cuenta y un dispositivo en el servidor de Carriots ====
+
==== 3rd Step: Create a new account and device in Carriots server ====
Se utiliza Carriots en el proyecto como una plataforma en la nube que permite almecenar series históricas de medidas de sensores. De esta forma se puede revisar la evolución histórica de valores o realizar minería de datos. En nuestro caso se podría comprobar la evilución de la temperatura en el tiempo y por ejemplo correlacionarla con los valores de temperatura ambiental publicados por el Ayuntamiento de Madrid o AEMET.
+
The cloud platform of Carriots is used in the project to store historical series of sensor readings. This enables realtime and offline datamining. In our case we could check the evolution of temperature with time and correlate it with the official temperature values ​​published by the City of Madrid or AEMET.
  
Tras crear una cuenta en el servidor de Carriots [https://www.carriots.com/developers], hay que crear un dispositivo que permita almacenar las medidas de temperatura del sensor DHT11. Para ello hay que ir al panel de control de Carriots [https://cpanel.carriots.com/]. En el menú de la izquierda de la página seleccionar dentro de "Device Management" la opción "Devices" [https://cpanel.carriots.com/device/]. En esta página se presentan todos los dispositivos creados por el usuario y se permite definir nuevos dispositivos pulsando el botón "New".
+
After creating an account in Carriots server [https://www.carriots.com/developers], a device is created to store the temperature readings obtained from the DHT11 sensor. To do this, go to Carriots Control pannel [https://cpanel.carriots.com/]. Select "Device Management" and then "Devices" in the menu shown on the left of the page [https://cpanel.carriots.com/device/]. In this page the user can see all his devices and can create new ones with the "New" button.
  
Seleccionando esta opción se muestra el formulario para crear un nuevo dispositivo. Aunque hay muchos parámetros, bastará con personalizar los siguientes valores:
+
Selecting the "New" option brings the user to the "New device" form. Although there are many parameters, it is enought to fill in the following values:
  
* Name: seleccionar un nombre único. Automáticamente se genera el ''deviceId'' o ''Id developer'' como "deviceName@username". Este valor es importante pues se utiliza al enviar datos desde este dispositivo a la plataforma de Carriots)
+
* Name: select a unique name. It automatically generates the ''deviceId'' or ''Id developer'' as "deviceName@username" (this value is important because it is used to identify the sensor data when it is sent from the imp device to Carriots platform)
 
* Type: Other
 
* Type: Other
 
* Sensor: Temperature
 
* Sensor: Temperature
* Enabled: Seleccionado (Carriots descarta las medidas recibidas del dispositivo si no está marcado como "Enabled")
+
* Enabled: Checked (Carriots discards messages/readings received from a device thet is not "Enabled")
 +
 
  
 
[[File:CarriotsDevice.jpg]]
 
[[File:CarriotsDevice.jpg]]
  
==== 4º Paso: Recepción de la temperatura por el 'imp' y subida a la nube de Carriots ====
+
==== 4th Step: Reception of temperature readings by imp device and upload to Carriots cloud server ====
En el proyecto [[Hola Mundo eImp]] ya se explicó que electricImp permite programar tanto una aplicación local en el dispositivo 'imp' como un "agente" en la nube en el servidor de electricImp. Esta doble posibilidad facilita la implementación de servicios en Internet y la vamos a utilizar para enviar al servidor de Carriots los datos de temperatura recibidos desde Arduino.
+
In a previous tutorial [[Hola Mundo eImp]] (in Spanish) we already explained that electricImp supports local applications running on the imp device as well as 'agents' running in the cloud server of electricImp. This feature facilitates the deployment of Internet services  and we will use it to send the temperature data received from Arduino to Carriots server.  
Se recomienda repasar la sección "2º Paso: Cargar la aplicación Hola Mundo" del proyecto [[Hola Mundo eImp]] antes de seguir con este paso.
+
  
[[File:EImpConsole.jpg]]
+
It is recommended to review section "2º Paso: Cargar la aplicación Hola Mundo" of [[Hola Mundo eImp| Hola Mundo eImp tutorial]] before continuing with this tutorial.
  
* Hacer login en la página de electric imp para acceder al IDE
+
[[File:EImpConsole.jpg]]
* En el menú de navegación de la izquierda buscar el dispositivo 'imp' que estamos utilizando (puede que se encuentro dentro de la pestaña "New Devices" o dentro de la pestaña de alguno de los modelos que se hayan definido)
+
* Pulsar sobre el icono de configuración a la derecha del dispositivo imp
+
* Pulsar sobre la lista desplegable "Associated Model" y escribir el nombre del nuevo modelo que vamos a crear "Temperature Carriots". Pulsar "Save Changes"
+
* El modelo "Temperature Carriots" aparecerá en el menú de navegación de la izquierda y pulsando sobre él se muetra el nombre de nuestro dispositivo. Directamente o pulsando sobre el nombre del dispositivo, la sección principal del IDE mostrará el editor de código donde vamos a codificar la aplicación
+
* La aplicación utiliza código en el dispositivo y en el servidor. El código del servidor se incluiría en la caja llamada "Agent" y el código del dispositivo en "Device".
+
  
* Copiar y pegar el siguente código en la caja "Device"
+
Detailed steps:
 +
* Log in to electricImp to access its IDE
 +
* Look for the imp device that we are using in the left navigation menu (the imp device might be under the "New Devices" tab or under the tab or any of the models that have been defined)
 +
* Click on the settings icon to the right of the imp device
 +
* Click on the "Associated Model" drop-down list and type the name of the new model that we are going to create "Temperature Carriots".
 +
* Click "Save Changes"
 +
* The "Temperature Carriots" model will appear in the left navigation menu. Click on it, the name of our device will pop up. Either automatically or after clicking on the device name, the main area of the IDE will display the code editor where we will define the application
 +
* Our application requires code on the device as well as on the server. The server code is included in the box called "Agent" and the device code  in the "Device" box.
 +
* Copy and paste the code below inside the "Device" box
  
 
  server.log("Device Started");
 
  server.log("Device Started");
Line 156: Line 161:
 
  arduino.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, arduinoData);
 
  arduino.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, arduinoData);
 
   
 
   
* Copiar y pegar el siguente código en la caja "Agent"
+
* Copy and paste the following code inside the "Agent" box:
  
 
  const CARRIOTS_URL = "http://api.carriots.com/streams/";
 
  const CARRIOTS_URL = "http://api.carriots.com/streams/";
Line 171: Line 176:
 
  device.on("sendTemperature", postTemperature);
 
  device.on("sendTemperature", postTemperature);
  
'''Nota:''' Sustituir en el código las cadenas ''your_device_id'' y ''your_api_key'' por los valores obtenidos en el paso anterior.
+
'''Note:''' You have to replace in the code <code>your_device_id</code> and <code>your_api_key</code> by the corresponding values ​​in Carriots (read Section [[#Detailed explanation of the agent code on ElectricImp server]] for further info
  
* Pulsar el botón "Build and Run" en la parte superior del IDE. La aplicación se compilará y si hay errores se mostrarán en la consola. Si todo va bien, tras la compilación el servidor de electric imp cargará la aplicación en nuestro imp a través de internet y la conexión wifi (el imp debe estar encendido y conectado a la red wifi)
+
* Click "Build and Run" button at the top of the IDE. The application compiles and any errors are displayed in the console box. If there are no errors, electric imp server will download the application into your imp device over Internet (the imp must be on and connected to a wifi network)
* Una vez cargada la aplicación, se empezará a ejecutar. El dispositivo imp espera a recibir datos a través de la conexión serie con Arduino. Cunado recibe un dato de temperatura, lo envía al agente en el servidor de electricImp y añade un nuevo mensaje en la ventana Log del IDE. Al recepcionar esta nueva lectura, el agente de electricImp la reenvía al servidor de Carriots y añade un mensaje al Log del IDE indicando el resultado de este envío.
+
* Once the application is loaded, it will begin to run. The imp device waits to receive data from Arduino through the serial connection. When it receives a temperature reading, it forwards it to the agent on the ElectricImp server and also post a new message in the Log window of the IDE. On receiving this new reading, the agent forwards it to Carriots server and posts a new message in the Log window registering the result of this submission
  
===== Explicación básica del código del dispositivo 'imp' =====
+
===== Detailed explanation of the imp device code  =====
  
Recordamos que el código del 'imp' se ejecuta de forma secuencial empezando desde la primera línea (las funciones se definen con la palabra clave ''function'' y no forman parte del flujo secuencial).
+
In the previous tutorial we explained that the imp code is executed sequentially starting from the first line (functions are identified with the <code>function</code> key word and are skipped from the sequential flow).
  
Disclaimer: No soy experto en squirrel, el lenguaje de programación de electricImp, así que pido disculpas por la mala calidad y organización del código.
+
Disclaimer: I am not an expert in squirrel, the programming language used by electricImp. I apologise for the poor quality of the code
  
Se define una variable ''s'' para almacenar la cadena de caracteres recibida desde Arduino a través de la conexión serie. La longitud de esta cadena se almacena en ''sSize'' (seguro que squirrel permite trabajar con cadenas de caracteres de una forma más sencilla, pero no la he encontrado).
+
The code defines variable ''s'' to store the char string received from Arduino through the serial connection. The length of the string is stored in ''sSize'' (I am sure that squirrel can handle strings in a simpler way but I could not find it)
  
También se define una variable ''arduino'' que representa la conexión serie. Se utilizan los pines 5 y 7 del imp (''uart57''):
+
The serial connection is defined in the ''arduino'' variable. It uses PINS 5 and 7 (''uart57''):
  
 
  arduino <- hardware.uart57;
 
  arduino <- hardware.uart57;
  
Esta variable se inicializa más abajo. Además de especificar los parámetros técnicos de la conexión serie, se define la función a la que se llamará en el imp cuando se reciban datos a través de la conexión serie: ''arduinoData()''.
+
This variable is initialised further down in the code. On top of defining the technical parameters of the serial connection, we also indicate the function (''arduinoData()'') that the imp device will call every time that it receives new data over the connection:
  
 
  arduino.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, arduinoData);
 
  arduino.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, arduinoData);
 
   
 
   
Se puede encontrar más información sobre las conexiones serie en el imp en la documentación de electricImp [http://www.electricimp.com/docs/api/hardware/uart/]
+
The electricImp docummentation has more information about how to manage serial connections in imp [http://www.electricimp.com/docs/api/hardware/uart/]
  
La función ''arduinoData()'' es la encargada de escuchar la conexión serie con Arduino. Cuando se recibe algún byte por esa conexión, el dispositivo imp llama a esta función. ''arduinoData()'' lee los bytes recibidos y los va almacenando en la variable ''s'' como una cadena de carateres. Este proceso continúa hasta que se recibe el código ''0xFC'', que es el mismo valor que se ha definido en el sketch de Arduino para identificar el final de un envío de datos. Si se leen más de 10 bytes antes de recibir un código de final de envío, se resetea la cadena ''s'' pues se asume que se están recibiendo datos eróneos o ruido.
+
The  ''arduinoData()'' function is responsible for listening to the Arduino serial connection. When a byte is received, the imp device calls this function. ''arduinoData()'' reads the input bytes and stores them as a char string in ''s''. This process continues until a byte valued ''0xFC'' is received. This value is the same one defined in the Arduino sketch to identify the end of a data transmission. If more than 10 bytes are received without receiving an end code, the function assumes that the data is corrupt and it resets variable ''s''.
  
Cuando se recibe el código de fin de envío, la función ''arduinoData()'' envía la cadena almacenada en la variable ''s'' (el dato recibido desde Arduino) al agente que está corriendo en el servidor de electricImp en la nube:
+
When an end code ''0xFC'' is received, ''arduinoData()'' sends the string stored in variable ''s'' to the electrcImp agent that is running in the cloud:
  
 
  agent.send("sendTemperature", s);
 
  agent.send("sendTemperature", s);
  
La función ''agent.send()'' tiene dos parámetros. El primero es el nombre del mensaje que se hará llegar al agente en el servidor (''sendTemperature'' en este caso). El segundo es el objeto que se pasará como parámetro a la función del agente encargada de recibir ese mensaje. Para más información, consultar la documentación del API de electricImp en [http://www.electricimp.com/docs/api/agent/send/] y [http://www.electricimp.com]./docs/api/agent/
+
Function ''agent.send()'' has two parameters. The first one is the name of the message that will be received by the agent in the server (''sendTemperature'' in our code). The second parameter is  the object that will be passed as a parameter to the agent function that will receive the message. More information can be found in the API docummentation of electricImp ([http://www.electricimp.com/docs/api/agent/send/] , [http://www.electricimp.com/docs/api/agent/] )
  
===== Explicación básica del código del agente en el servidor de electricImp =====
+
===== Detailed explanation of the agent code on ElectricImp server =====
El agente del servidor también se codifica en squirrel.
+
The agent is also coded in squirrel.
  
En este proyecto, el agente sólo actúa cuando recibe un mensaje enviado desde el dispositivo 'imp' asociado. Acabamos de ver que 'imp' utiliza la función ''agent.send()'' para enviar un mensaje al agente. En el lado del agente, hay que registrar qué función procesará este mensaje, para ello se utiliza la función ''device.on()'':
+
In this project, the agent is only triggered when it receives a message from its imp associated device. We have just explained that the imp device calls function ''agent.send()'' to send a message to the agent. On the agent side, you use the function ''device.on()'' to register the function that will process this incoming message:
  
 
  device.on("sendTemperature", postTemperature);
 
  device.on("sendTemperature", postTemperature);
  
Esta función tiene dos parámetros. El primero es el nombre del mensaje (''sendTemperature'' en este caso) y el segundo es la función del agente que se encargará de procesar este mensaje (''postTemperature()'' en el ejemplo). El segundo parámetro que el dispositivo incluye al llamar a la función ''agent.send()'' es un objeto cuyo valor se pasa como parámetro a la función elegida en el agente.
+
This function has two parameters. The first one is the name of the message (''sendTemperature'' in our case) and the second one is the function in the agent that will process this message (''postTemperature()'' in the example). The second parameter that the 'imp' device includes when calling the function  ''agent.send()'' is an object whose value is passed as a parameter to the function indicated by the agent.
  
Centrándonos en nuestro ejemplo, el dispositivo imp envía el mensaje ''sendTemperature'' y como parámetro la cadena recibida desde Arduino (una lectura de temperatura). El agente en el servidor recibe este mensaje y llama a la función ''postTemperature()'' pasándole como parámetro la cadena que generó Arduino (la lectura de la temperatura).
+
Focusing on our example, the imp device sends the message ''sendTemperature'' and includes the string received from Arduino as the second parameter (i.e. a temperature reading). The agent on the server receives this message and calls the function ''postTemperature()'' passing as parameter the string generated by  the Arduino (temperature reading).
  
La función ''postTemperature()'' simplemente formatea una petición http POST según la espicificación del API de Carriots incluyendo en el BODY de la petición una cadena JSON con el valor de temperatura recibido desde el dispositivo. Esta petición añade una nueva medida al dispositivo en el servidor de Carriots.
+
The ''postTemperature()'' function just formats an http POST request according to the API of Carriots. The request includes in its BODY a JSON string with the temperature value received from the device. This request creates a new reading in Carriots server.
  
Los detalles sobre cómo funciona la petición http se describen en la documentación del API de eletricImp [http://www.electricimp.com/docs/api/http/ http], [http://www.electricimp.com/docs/api/http/post/ http POST] y [http://www.electricimp.com/docs/api/httprequest/ http request].
+
Details on how the http request works are described in the API documentation of eletricImp [http://www.electricimp.com/docs/api/http/ http], [http://www.electricimp.com/docs/api/http/post/ http POST], [http://www.electricimp.com/docs/api/httprequest/ http request].
  
El formato de la petición al servidor de Carriots está definido en su API. En el tutorial [https://www.carriots.com/tutorials/send_stream/curl How to send a stream using cURL] se explica en detalle como formatear la petición con las cabeceras y parámetros necesarios.
+
The format of the request to Carriots server is defined in its API. Tutorial [https://www.carriots.com/tutorials/send_stream/curl How to send a stream using cURL] explains in detail how to format the request headers and parameters.
  
En nuestro caso, se debe realizar una petición http POST a la URL ''http://api.carriots.com/streams/''. Se debe incluir una cabecera con el API key de carriots (el API key del usuario que creó el dispositivo en Carriots y que tiene derecho a enviar valores desde ese dispositivo). En el código del agente de electricImp se debe sustituir la cadena ''your_api_key'' por el valor real de la API key.  
+
In our case, we  make a request to ''http://api.carriots.com/streams/''. The header must include Carriots API key (the API key of the user who created the device in Carriots and that is entitled to send readings ​​from the device). Replace in the agent code ''your_api_key'' by the actual value of the API key.  
  
Para conocer la API key, hay que ir a la consola de Carriots y seleccionar la pestaña "MySettings" y después "My Account" en el menú superior de la pantalla. El valor de la API_key que debemos usar es el denominado ''Full Privileges Apikey''.
+
To retrieve the API key, go to Carriots console and click on "MySettings" tab and then on "My Account" on the menu at the top of the screen. The API key value is the one named ''Full Privileges Apikey''.
 +
 
 +
Carriots expects a JSON object as the BODY of the http request. Its format is as follows:
  
Como BODY de la petición http, Carriots espera un objeto JSON. Su formato es el siguiente:
 
 
  {
 
  {
 
     "protocol":"v1",
 
     "protocol":"v1",
Line 234: Line 240:
 
  }
 
  }
  
El timestamp de la medida se indica en el parámetro ''at''. En el ejemplo se utiliza la cadena ''now''. Este valor indica a Carriots que almacene la medida con el valor de su reloj en el momento de recibir el mensaje.
+
The timestamp of a reading is  indicated in the parameter ''at''. In the example, we use the string ''now'' . This value tells Carriots to store the received reading with the value of the system time of its server when the message is received.  
  
En el código del agente de electricImp se debe sustituir la cadena ''your_device_id'' por el valor real de la identidad del dispositivo en Carriots (por ejemplo ''TempMSM@makespacemadrid'').
+
Replace ''your_device_id'' in the agent code with the actual identity of the device in Carriots (e.g. ''TempMSM@makespacemadrid'').
  
Las medidas recibidas por el servidor de Carriots se pueden ver seleccionando la opción "Data streams" dentro de "Data management" en el menú de la izquierda del panel de control [https://cpanel.carriots.com/stream/]
+
The readings received by the server can be viewed in Carriots selecting "Data streams" option under "Data management" in the left menu of the control panel [https://cpanel.carriots.com/stream/]
  
==== 5º Paso: Crear una cuenta y un panel en el servidor de Ducksboard ====
+
==== 5th Step: Create a new account and dashboard in Ducksboard server ====
Se utiliza Ducksboard en el proyecto como una plataforma en la nube que permite visualizar "en vivo" medidas de sensores sin necesidad de desplegar o codificar un servidor propio.
+
The cloud platform of Ducksboard is used in the project to visualise live sensor data without having to deploy or code a dedicated server.
  
El primer paso es crear una cuenta en el servidor de Ducksboard [https://app.ducksboard.com/signup/] (la cuenta es gratuita por un mes pero luego hay que pagar una subscripción si se quiere mantener el servicio).
+
The first step is to create a Ducksboard account [https://app.ducksboard.com/signup/] (the trial account is free for one month but then you need to pay a subscription to keep the service).
 +
 
 +
After creating the account, the next step is to personalise a dashboard. We will use the "Main dashboard" generated by default when the account is created. We will add two "widgets" or windows to the dashboard. In one of them we will just display the last temperature reading received. The other widget will show a list or "timeline" of the latest reported values.
  
Tras crear la cuenta, el siguiente paso es personalizar un panel o "dashboard". Utilizaremos el "Main dashboard" que se genera por defecto al crear la cuenta. Vamos a añadir dos "widgets" o ventanas al dashboard. En una de ellas simplemente mostraremos el último valor de temperatura recibido. En el otro, mostraremos una lista o "timeline" de los últimos valores reportados.
 
  
 
[[File:Ducksboard.jpg]]
 
[[File:Ducksboard.jpg]]
  
Para definir un nuevo widget, pulsar el botón "+" en la esquina superior izquierda del dashboard. En la siguiente página, pulsar "Show your own data" (en la parte inferior de la pantalla).  
+
Click on the "+" button on the top left corner of the dashboard to define a new widget. In the following page, click on "Show your on data" (bottom part of the screen)
 +
 
 +
Select option "Your own numbers" and then "Counters" to create the first widget. Next click on the "add this widget" button. This widget shows a counter with the last received value. It also draws in the background a historical graph of received values.
 +
 
 +
Now you can personalise the visual parameters of the widget:
 +
* Name: The text that will be shown to identify the widget window
 +
* Color: The font color used to dsplay the sensor value
 +
* Timeframe: The time scale used to represent the historical graph in the background (hours, days, weeks, etc.)
  
El primer widget se crea seleccionando la opción "Your own numbers" y después "Counters". Pulsar sobre el botón "add this widget". Este widget presenta un contador con el último valor recibido. De fondo, también se incluye una gráfica de la evolución histórica de los valores recibidos.
+
Choose your preferred values and click on "save preferences for this widget" at the bottom of the screen.
  
Ahora se pueden personalizar los parámetros de visualización del widget:
+
Once the widget is created, Ducksboard lets you define alarms, "pull" received values, "push" new values from a device or a server, etc. In our case we will only use the "push" functionality to send temperature readings from Carriots server. To impelement this feature, you will need the following values available from the "DATA&API" tab of the widget:
* Name: La cadena de texto que se muestra para identificar la ventana del widget
+
* Color: El color que se utiliza para mostrar el valor del sensor
+
* Timeframe: La escala que se utiliza para represntar la gráfica de evolución del sensor (horas, días, semanas...)
+
  
Elegir los valores deseados y seleccionar "save preferences for this widget" en la parte de abajo de la pantalla.
+
* PUSH DATA TO THIS URL: URL that Carriots will use to push the temperature readings
 +
* YOUR API KEY: string included in a header of the http request to identify the Ducksboard account and the widget.
  
Una vez creado el widget, Ducksboard permite definir alarmas, hacer "pull" de medidas, recibir medidas en modo "push" desde el dispositivo o un servidor,... En nuestro caso sólo necesitamos implementar la funcionalidad "push" (el servidor de Carriots se encargará de enviar a Ducksboard los nuevos datos de temperatura tan pronto como estén disponibles). Para ello es necesario que nos fijemos en dos valores disponibles en la pestaña "DATA&API" del widget:
+
These two values will be used in the next step.
* PUSH DATA TO THIS URL: es la dirección a la que Carriots enviará los datos de temperatura
+
* YOUR API KEY: valor que se incluye en la cabecera de la petición http e identifica al cliente que envía el dato
+
En el siguiente paso se utilizarán estos dos valores.
+
  
 
[[File:Ducksboard_Widget.jpg]]
 
[[File:Ducksboard_Widget.jpg]]
  
El segundo widget presentará el "timeline" de los últimos valores de temperatura recibidos en Ducksboard. En la patalla principal del "Main dashboard" volver a pulsar el botón "+" y luego "Show your own data". Ahora seleccionar "Your own text", elegir "Timelines" y en ella la opción "Size: 1 column/2 rows". Como el widget anterior, utilizaremos los valores PUSH DATA TO THIS URL y YOUR API KEY en el siguiente paso.
+
The second widget represents the "timeline" of the latest tempereature values received by Ducksboard. From the "Main dashboard" click again on "+" button and then on "Show your own data". Now select "Your own text" and "Timelines" and finally choose "Size: 1 column/2 rows" option. We vill use  later "PUSH DATA TO THIS URL" and "YOUR API KEY" values from "DATA&API" tab as in the previous widget.
  
Se pueden cambiar algunos parámteros de la configuración del panel pulsando el icono de configuración (una rueda dentada) en la pantalla principal del panel. Por ejemplo se puede definir un nuevo fondo o cambiarle el nombre. Desde configuración también se puede compartir el dashboard en público a través de una URL (pestaña "SHARE THIS DASHBOARD" dentro de la opción "PREFERENCES FOR THIS DASHBOARD"). Ducksboard permite dar un nombre al enlace que va a generar y opcionalmente protegerlo con una contraseña. Utilizar el botón "COPY LINK" para obtener la URL pública del dashboard compartido.
+
You can modify some configuration parameters of the dashboard by clicking on the settings icon (gear wheel) in the main window. For example you can change the background or the name of the dashboard. You can also share the dashboard through a public link or URL ("SHARE THIS DASHBOARD" tab inside "PREFERENCES FOR THIS DASHBOARD"). Ducksboard lets you give a name to the link for later reference. You can also protect the dashboard with a password so that only people that know the secret password can access the dashboard content. Use  "COPY LINK" to copy the public URL of the dashboard to the clipboard.
  
==== 6º Paso: Publicación de los datos de temperatura en Ducksboard desde el servidor de Carriots ====
+
==== 6th Step: Publish temperature readings in Ducksboard from Carriots server ====
En este último paso el servidor de Carriots publica los valores de temperatura en el panel de Ducksboard que se acaba de definir. Para ello, se utiliza el [http://dev.ducksboard.com/apidoc/slot-kinds/ API http de Ducksboard].
+
In this final step, Carriots server publishes temperature readings in the dashboard that we just created. To do this, Carriots uses  [http://dev.ducksboard.com/apidoc/slot-kinds/ Ducksboard's http API].
  
La plataforma de Carriots permite definir "listeners", bloques de código que se ejecutan cuando suceden determinados eventos, como por ejemplo la recepción de una nueva medida de un sensor. Este código se ejecuta en la plataforma en la nube de Carriots y se programa en groovy, un lenguaje dinámico basado en la máquina virtual de Java (JVM). Básicamente un listener define una regla basada en una condición. Si pasa A entonces ejecuta B y, si no, ejecuta C.  
+
Carriots platform lets you define "listeners", blocks of code that are excuted when certain events are triggered (e.g. the reception of a new sensor reading). This code is run in the cloud server of Carriots and is written in "groovy", a dynamic language based on the Java Virtual Machine (JVM). A listener is esentially a rule based on the result of a condition: if A then do B; otherwise do C.
  
 
[[File:Carriots_listener.jpg]]
 
[[File:Carriots_listener.jpg]]
  
La documentación de Carriots incluye un tutorial detallado sobre cómo crear un ''listener'' [https://www.carriots.com/tutorials/create_listener]. Siguiendo este tutorial vamos a ver cómo enviar los valores de temperatura a Ducksboard. En la [https://cpanel.carriots.com/listener/new# página de creación de un nuevo listener] se definen los siguientes parámetros:
+
Carriots docummentation includes a detailed titorial that explains how to create a ''listener'' [https://www.carriots.com/tutorials/create_listener]. We will follow this tutorial to send temperature readings from Carriots to Ducksboard. In the [https://cpanel.carriots.com/listener/new# new listener page] you have to define the following parameters:
  
* Name: el valor que queramos darle a este listener (por ejemplo "temperaturaDucksboard")
+
* Name: the name of the new listener (e.g. "temperatureDucksboard")
* Description: explicación de lo que hace (por ejemplo "envío de valores de temperatura a Ducksboard")
+
* Description: text explaining the function of the listener (e.g. "send temperature readings to Ducksboard")
* Entity type: ''Device'' (este listener aplica sólo a nuestro dispositivo)
+
* Entity type: ''Device'' (this indicates that the listener applies only to a device)
* Id: seleccionar la identidad del dispositivo creado en el paso 3
+
* Id: select the id of the device creted in Step 3 (e.g. "TempMSM@makespacemadrid")
* Event: ''Event Data Received'' (el listener será llamado cada vez que se reciba un valor desde el dispositivo seleccionado)
+
* Event: ''Event Data Received'' (the listener will be triggered everytime a new reading is received from the selected device)
* Enabled: seleccionado (si no se marca, el listener no está activo y no se ejecutará)
+
* Enabled: checked (if not checked, the listener is not active and will not be triggered)
  
La lógica del listener se descibe en los campos ''If, Then, Else''. En nuestro ejemplo, siempre enviamos el valor recibido a Ducksboard sin hacer ningun chequeo (en un proyecto real convendría hacer un chequeo de formato). La condición ''IF'' es siempre cierta (''true'') y no hace falta definir una claúsula  ''ELSE''.
+
The logic of the listener is described in the ''If, Then, Else'' fields. In our example we always forward the received temperature value without performing any check (in a real project it would be sensible to validate the received format). Since ''IF'' clause is always true  (''true'') there is no need to define the ''ELSE'' clause.
  
 
  If expression:
 
  If expression:
Line 312: Line 321:
 
         basicHttp2.send();
 
         basicHttp2.send();
  
El código de la claúsula ''Then'' simplemente envía dos peticiones http POST al servidor de Duckstore siguiendo el formato JSON de su API. La primera petición se envía al widget ''Counter'' y la segunda al widget ''Timeline''. La doucmentación de Carriots incluye un [https://www.carriots.com/tutorials/others_APIs/ducksboard tutorial para integrar Ducksboard] que explica en detalle este código .
 
  
'''Importante:''' sustituir en el código los valores ''your_ducksboard_api_key, your_ducksboard_PUSH_URL_counter_widget, your_ducksboard_PUSH_URL_timeline_widget'' por los valores que se han obtenido en el paso 5.
+
The code in the ''Then'' clause just sends two http POST requests to Ducksboard server. The payload/BODY of the requests follows the JSON format defined in Ducksboard's API. The first request is sent to ''Counter'' widget while the second one is sent to ''Timeline'' widget. There is a [https://www.carriots.com/tutorials/others_APIs/ducksboard detailed tutorial] by Carriots that explains this code.
 +
 
 +
'''Important:''' replace in the code ''your_ducksboard_api_key, your_ducksboard_PUSH_URL_counter_widget, your_ducksboard_PUSH_URL_timeline_widget'' by the corresponding values obtained in Step 5
  
Una vez creado el listener, cualquier lectura de temperatura recibida por Carriots desde electricImp (paso 4) será reenviada a los dos widgets de Ducksboard. Además la medida también quedará almacenada en el servidor de Carriots
+
Once the listener has been created, any new temperature reading received by Carriots from electricImp (Step 4) will be forwarded to the two Ducksboard widgets. Additionally the values will also be stored internally in Carriots server.
  
'''Nota: ''' Los datos de temperatura se podrían enviar directamente desde el agente de electricImp a los widgets de Ducksboard sin necesidad de pasar por el servidor de Carriots, pero en ese caso se perdería la serie histórica de medidas.
+
'''Note: ''' Temperature readings could be sent directly from electricImp agent to Ducksboard widgets without using Carriots server, but then we would lose the historical series of readings and the possibility to perform offline review and data mining.
  
=== Enlaces ===
+
=== Links ===
* Ducksboard público del sensor de Temperatura utilizado para construir el ejemplo: [https://public.ducksboard.com/YBhxqTLwFOJA-D8OtZeE/]
+
* Link to the public ''ducksboard'' of the temperature sensor used in this example: [https://public.ducksboard.com/YBhxqTLwFOJA-D8OtZeE/]
 
[[File:Ducksboard_TempMSM.jpg]]
 
[[File:Ducksboard_TempMSM.jpg]]

Latest revision as of 14:05, 17 March 2014

Connected Online Thermometer[edit]

STATUS: Initial version

Miembros: User:Tumaku

Versión española


Aim[edit]

Read the temperature from a sensor and post it online through the cloud servers of ElectricImp, Carriots and Ducksboard

Flow eImp carriots ducksboard en.jpg

HW Temperature eImp.JPG

Motivation[edit]

Start working on a real project with the samples donated to Makespace by electricImp. When installed, the project will allow members to check online the temperature of Makespace Madrid

Background/Prerequisites[edit]

The user already has an electricImp account and has configured the electricImp device with the parameters of the WiFi network. These steps are described in Hola Mundo eImp

Required HW and Cloud Services[edit]

This project requires the following HW and cloud services:

  • DHT11 temperature sensor [1]
  • Arduino Uno (or Pro Mini 5V)
  • Level converter [2]
  • 'imp' device by ElectricImp with free account and cloud service [3]
  • Free account and cloud service of carriots [4]
  • Free trial account and cloud service of ducksboard [5]

Summary[edit]

The project publishes online the temperature readings obtained from a DHT11 sensor.

  • The reading is obtained through an Arduino (Arduino is used because the current version of electricImp does not support the proprietary protocol of the DHT11 sensor). The temperature is read once a minute
  • The temperature reading is passed to an imp device that forwards it to an agent in the cloud server of electricImp
  • The agent sends the reading to Carriots through its http REST API. Carriots is used to keep the historical series of all measured temperature values
  • When Carriots server receives a new temperature reading, a "listener" makes a new http REST request towards Ducksboard server to update a "dashboard" that displays the latest temperature values received

Detailed Description[edit]

1st Step: Read the temperature value from Arduino and pass it to 'imp' device[edit]

The DHT11 temperature sensor is very easy to use but it is not "compatible" with the imp HW due to the proprietary protocol of the sensor. Additionally, it runs at 5V while the imp works at 3.3V. electricImp recommends using an intermediate micro (arduino) to read the temperature and then forward the reading to the imp through a serial connection [6]

The temperature is read from Arduino using a library and sketch written by Rob Tilliart [7]. The link describes how to install and use the library from Arduino IDE.

Note: The DHT11 sensor shown in the previous link has four PINs at the bottom. However the PCB mounted version sold by DealeXtreme [8] has only 3 PINs. The following picture describes the function of each PIN:

DHT11.jpg

The Arduino sketch simply reads the temperature from DHT11PIN (digital pin 2 of the Arduino) and sends the read value through a serial connection (Arduino digital PINs 7 and 8: SoftwareSerial eImpSerial(7, 8)). A special code (byte 0xFC) is sent after the temperature value to inform to the other end of the serial connection (the imp device) that a new value is available.

After forwarding the temperature reading to the imp, arduino waits for a minute (60000 milliseconds) until the next reading.


Find hereafter the Arduino sketch:

/* 
Simple sketch to read Temperature from DHT11 sensor
Written by Javier Montaner @tumaku_ for Makespace Madrid 
http://www.makespacemadrid.org

Based on YourDuino.com Example Software Sketch
DHT11 Humidity and Temperature Sensor test
Credits: Rob Tillaart
http://arduino-direct.com/sunshop/index.php?l=product_detail&p=162
terry@yourduino.com */

#include <dht11.h>
#include <SoftwareSerial.h>

dht11 DHT11;

#define DHT11PIN 2
SoftwareSerial eImpSerial(7, 8); // RX, TX

void setup()   
{
   Serial.begin(9600);
   eImpSerial.begin(9600);
   Serial.println("DHT11 TEST PROGRAM ");
   Serial.print("LIBRARY VERSION: ");
   Serial.println(DHT11LIB_VERSION);
   Serial.println();
}

void loop()  
{
   int chk = DHT11.read(DHT11PIN);
   Serial.print("Temperature (oC): ");
   Serial.println((float)DHT11.temperature, 2);
   eImpSerial.print((float)DHT11.temperature, 2);
   eImpSerial.write(0xFC);
   delay(60000);
}

2nd Step: Connect Arduino and 'imp' through a voltage converter[edit]

The imp device works at 3.3V while Arduino works at 5V. You cannot connect their PINs directly because you could burn the 'imp' with the higher voltage generated by Arduino. The solution is to connect them through an intermediate voltage converter. This project has chosen a Sparkfun converter [9] but any other similar converter could be used. There is a tutorial on Sparkfun website that explains how this component works. It also includes an example showing how to wire a serial connection between Arduino and electricImp "Using the LLC for Serial" paragraph. Make connections as shown in the picture but keep in mind that our Arduino uses pins 7 and 8 for the serial connection. Wires coming out of 0/RX0 (green) and 1/TX0 (yellow) should come out of PINs 7 and 8.

Important: Arduino serial connection uses pins 7 and 8 (not pins 0 and 1)

3rd Step: Create a new account and device in Carriots server[edit]

The cloud platform of Carriots is used in the project to store historical series of sensor readings. This enables realtime and offline datamining. In our case we could check the evolution of temperature with time and correlate it with the official temperature values ​​published by the City of Madrid or AEMET.

After creating an account in Carriots server [10], a device is created to store the temperature readings obtained from the DHT11 sensor. To do this, go to Carriots Control pannel [11]. Select "Device Management" and then "Devices" in the menu shown on the left of the page [12]. In this page the user can see all his devices and can create new ones with the "New" button.

Selecting the "New" option brings the user to the "New device" form. Although there are many parameters, it is enought to fill in the following values:

  • Name: select a unique name. It automatically generates the deviceId or Id developer as "deviceName@username" (this value is important because it is used to identify the sensor data when it is sent from the imp device to Carriots platform)
  • Type: Other
  • Sensor: Temperature
  • Enabled: Checked (Carriots discards messages/readings received from a device thet is not "Enabled")


CarriotsDevice.jpg

4th Step: Reception of temperature readings by imp device and upload to Carriots cloud server[edit]

In a previous tutorial Hola Mundo eImp (in Spanish) we already explained that electricImp supports local applications running on the imp device as well as 'agents' running in the cloud server of electricImp. This feature facilitates the deployment of Internet services and we will use it to send the temperature data received from Arduino to Carriots server.

It is recommended to review section "2º Paso: Cargar la aplicación Hola Mundo" of Hola Mundo eImp tutorial before continuing with this tutorial.

EImpConsole.jpg

Detailed steps:

  • Log in to electricImp to access its IDE
  • Look for the imp device that we are using in the left navigation menu (the imp device might be under the "New Devices" tab or under the tab or any of the models that have been defined)
  • Click on the settings icon to the right of the imp device
  • Click on the "Associated Model" drop-down list and type the name of the new model that we are going to create "Temperature Carriots".
  • Click "Save Changes"
  • The "Temperature Carriots" model will appear in the left navigation menu. Click on it, the name of our device will pop up. Either automatically or after clicking on the device name, the main area of the IDE will display the code editor where we will define the application
  • Our application requires code on the device as well as on the server. The server code is included in the box called "Agent" and the device code in the "Device" box.
  • Copy and paste the code below inside the "Device" box
server.log("Device Started");
local s="";
local sSize=0;
arduino <- hardware.uart57;

function arduinoData() {
 local b = arduino.read();
 while(b != -1) {
   sSize++;
   if (sSize>10) {
      sSize=0;
      s="";
      server.log("reset string");
   }
   if (b == 0xFC) {
       agent.send("sendTemperature", s);
       server.log(s);
       sSize=0;
       s="";
   }
   else {s= s+b.tochar();}
   b = arduino.read();
 }
}

arduino.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, arduinoData);

  • Copy and paste the following code inside the "Agent" box:
const CARRIOTS_URL = "http://api.carriots.com/streams/";
const jsonStringA= "{\"protocol\":\"v1\",\"at\": \"now\",\"device\":\"your_device_id\",\"data\":{\"temp\":\"";
const jsonStringB="\"},\"checksum\":\"\"}";

function postTemperature(tempString) {
 local body = jsonStringA + tempString + jsonStringB;
 local request = http.post(CARRIOTS_URL, {"carriots.apiKey":"your_api_key"}, body);
 local resp = request.sendsync();
 server.log("HTTPResponse: " + resp.statuscode + " - " + resp.body + " " + tempString);
}

device.on("sendTemperature", postTemperature);

Note: You have to replace in the code your_device_id and your_api_key by the corresponding values ​​in Carriots (read Section #Detailed explanation of the agent code on ElectricImp server for further info

  • Click "Build and Run" button at the top of the IDE. The application compiles and any errors are displayed in the console box. If there are no errors, electric imp server will download the application into your imp device over Internet (the imp must be on and connected to a wifi network)
  • Once the application is loaded, it will begin to run. The imp device waits to receive data from Arduino through the serial connection. When it receives a temperature reading, it forwards it to the agent on the ElectricImp server and also post a new message in the Log window of the IDE. On receiving this new reading, the agent forwards it to Carriots server and posts a new message in the Log window registering the result of this submission
Detailed explanation of the imp device code[edit]

In the previous tutorial we explained that the imp code is executed sequentially starting from the first line (functions are identified with the function key word and are skipped from the sequential flow).

Disclaimer: I am not an expert in squirrel, the programming language used by electricImp. I apologise for the poor quality of the code

The code defines variable s to store the char string received from Arduino through the serial connection. The length of the string is stored in sSize (I am sure that squirrel can handle strings in a simpler way but I could not find it)

The serial connection is defined in the arduino variable. It uses PINS 5 and 7 (uart57):

arduino <- hardware.uart57;

This variable is initialised further down in the code. On top of defining the technical parameters of the serial connection, we also indicate the function (arduinoData()) that the imp device will call every time that it receives new data over the connection:

arduino.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, arduinoData);

The electricImp docummentation has more information about how to manage serial connections in imp [13]

The arduinoData() function is responsible for listening to the Arduino serial connection. When a byte is received, the imp device calls this function. arduinoData() reads the input bytes and stores them as a char string in s. This process continues until a byte valued 0xFC is received. This value is the same one defined in the Arduino sketch to identify the end of a data transmission. If more than 10 bytes are received without receiving an end code, the function assumes that the data is corrupt and it resets variable s.

When an end code 0xFC is received, arduinoData() sends the string stored in variable s to the electrcImp agent that is running in the cloud:

agent.send("sendTemperature", s);

Function agent.send() has two parameters. The first one is the name of the message that will be received by the agent in the server (sendTemperature in our code). The second parameter is the object that will be passed as a parameter to the agent function that will receive the message. More information can be found in the API docummentation of electricImp ([14] , [15] )

Detailed explanation of the agent code on ElectricImp server[edit]

The agent is also coded in squirrel.

In this project, the agent is only triggered when it receives a message from its imp associated device. We have just explained that the imp device calls function agent.send() to send a message to the agent. On the agent side, you use the function device.on() to register the function that will process this incoming message:

device.on("sendTemperature", postTemperature);

This function has two parameters. The first one is the name of the message (sendTemperature in our case) and the second one is the function in the agent that will process this message (postTemperature() in the example). The second parameter that the 'imp' device includes when calling the function agent.send() is an object whose value is passed as a parameter to the function indicated by the agent.

Focusing on our example, the imp device sends the message sendTemperature and includes the string received from Arduino as the second parameter (i.e. a temperature reading). The agent on the server receives this message and calls the function postTemperature() passing as parameter the string generated by the Arduino (temperature reading).

The postTemperature() function just formats an http POST request according to the API of Carriots. The request includes in its BODY a JSON string with the temperature value received from the device. This request creates a new reading in Carriots server.

Details on how the http request works are described in the API documentation of eletricImp http, http POST, http request.

The format of the request to Carriots server is defined in its API. Tutorial How to send a stream using cURL explains in detail how to format the request headers and parameters.

In our case, we make a request to http://api.carriots.com/streams/. The header must include Carriots API key (the API key of the user who created the device in Carriots and that is entitled to send readings ​​from the device). Replace in the agent code your_api_key by the actual value of the API key.

To retrieve the API key, go to Carriots console and click on "MySettings" tab and then on "My Account" on the menu at the top of the screen. The API key value is the one named Full Privileges Apikey.

Carriots expects a JSON object as the BODY of the http request. Its format is as follows:

{
   "protocol":"v1",
   "at":"now",
   "device":"your_device_id",
   "data":{
        "temp":"21"
   },
   "checksum":""
}

The timestamp of a reading is indicated in the parameter at. In the example, we use the string now . This value tells Carriots to store the received reading with the value of the system time of its server when the message is received.

Replace your_device_id in the agent code with the actual identity of the device in Carriots (e.g. TempMSM@makespacemadrid).

The readings received by the server can be viewed in Carriots selecting "Data streams" option under "Data management" in the left menu of the control panel [16]

5th Step: Create a new account and dashboard in Ducksboard server[edit]

The cloud platform of Ducksboard is used in the project to visualise live sensor data without having to deploy or code a dedicated server.

The first step is to create a Ducksboard account [17] (the trial account is free for one month but then you need to pay a subscription to keep the service).

After creating the account, the next step is to personalise a dashboard. We will use the "Main dashboard" generated by default when the account is created. We will add two "widgets" or windows to the dashboard. In one of them we will just display the last temperature reading received. The other widget will show a list or "timeline" of the latest reported values.


Ducksboard.jpg

Click on the "+" button on the top left corner of the dashboard to define a new widget. In the following page, click on "Show your on data" (bottom part of the screen)

Select option "Your own numbers" and then "Counters" to create the first widget. Next click on the "add this widget" button. This widget shows a counter with the last received value. It also draws in the background a historical graph of received values.

Now you can personalise the visual parameters of the widget:

  • Name: The text that will be shown to identify the widget window
  • Color: The font color used to dsplay the sensor value
  • Timeframe: The time scale used to represent the historical graph in the background (hours, days, weeks, etc.)

Choose your preferred values and click on "save preferences for this widget" at the bottom of the screen.

Once the widget is created, Ducksboard lets you define alarms, "pull" received values, "push" new values from a device or a server, etc. In our case we will only use the "push" functionality to send temperature readings from Carriots server. To impelement this feature, you will need the following values available from the "DATA&API" tab of the widget:

  • PUSH DATA TO THIS URL: URL that Carriots will use to push the temperature readings
  • YOUR API KEY: string included in a header of the http request to identify the Ducksboard account and the widget.

These two values will be used in the next step.

Ducksboard Widget.jpg

The second widget represents the "timeline" of the latest tempereature values received by Ducksboard. From the "Main dashboard" click again on "+" button and then on "Show your own data". Now select "Your own text" and "Timelines" and finally choose "Size: 1 column/2 rows" option. We vill use later "PUSH DATA TO THIS URL" and "YOUR API KEY" values from "DATA&API" tab as in the previous widget.

You can modify some configuration parameters of the dashboard by clicking on the settings icon (gear wheel) in the main window. For example you can change the background or the name of the dashboard. You can also share the dashboard through a public link or URL ("SHARE THIS DASHBOARD" tab inside "PREFERENCES FOR THIS DASHBOARD"). Ducksboard lets you give a name to the link for later reference. You can also protect the dashboard with a password so that only people that know the secret password can access the dashboard content. Use "COPY LINK" to copy the public URL of the dashboard to the clipboard.

6th Step: Publish temperature readings in Ducksboard from Carriots server[edit]

In this final step, Carriots server publishes temperature readings in the dashboard that we just created. To do this, Carriots uses Ducksboard's http API.

Carriots platform lets you define "listeners", blocks of code that are excuted when certain events are triggered (e.g. the reception of a new sensor reading). This code is run in the cloud server of Carriots and is written in "groovy", a dynamic language based on the Java Virtual Machine (JVM). A listener is esentially a rule based on the result of a condition: if A then do B; otherwise do C.

Carriots listener.jpg

Carriots docummentation includes a detailed titorial that explains how to create a listener [18]. We will follow this tutorial to send temperature readings from Carriots to Ducksboard. In the new listener page you have to define the following parameters:

  • Name: the name of the new listener (e.g. "temperatureDucksboard")
  • Description: text explaining the function of the listener (e.g. "send temperature readings to Ducksboard")
  • Entity type: Device (this indicates that the listener applies only to a device)
  • Id: select the id of the device creted in Step 3 (e.g. "TempMSM@makespacemadrid")
  • Event: Event Data Received (the listener will be triggered everytime a new reading is received from the selected device)
  • Enabled: checked (if not checked, the listener is not active and will not be triggered)

The logic of the listener is described in the If, Then, Else fields. In our example we always forward the received temperature value without performing any check (in a real project it would be sensible to validate the received format). Since IF clause is always true (true) there is no need to define the ELSE clause.

If expression:
        (true)
Then expression:
        import com.carriots.sdk.utils.BasicHttp;
        def basicHttp = new BasicHttp();
        def map= ["user" : "your_ducksboard_api_key", "password":"unused"];
        basicHttp.http_auth=map;
        //basicHttp.url ="https://push.ducksboard.com/values/296067";
        basicHttp.url ="your_ducksboard_PUSH_URL_counter_widget";
        basicHttp.verb ="POST";
        basicHttp.payload='{"timestamp": '+ context.envelope.at + ', "value": ' + context.data.temp + '}';
        basicHttp.send();

        def basicHttp2 = new BasicHttp();
        def map2= ["user" : "your_ducksboard_api_key", "password":"unused"];
        basicHttp2.http_auth=map;basicHttp2.url ="your_ducksboard_PUSH_URL_timeline_widget";
        basicHttp2.verb ="POST";
        Date d= new Date();
        basicHttp2.payload='{"value":{"title": "Temperatura: ' + context.data.temp  +'", "image": ' +
             '"https://app.ducksboard.com/static/img/timeline/green.gif" , "content":"Tiemstamp: '+ d.toString() +'"}}';
        basicHttp2.send();


The code in the Then clause just sends two http POST requests to Ducksboard server. The payload/BODY of the requests follows the JSON format defined in Ducksboard's API. The first request is sent to Counter widget while the second one is sent to Timeline widget. There is a detailed tutorial by Carriots that explains this code.

Important: replace in the code your_ducksboard_api_key, your_ducksboard_PUSH_URL_counter_widget, your_ducksboard_PUSH_URL_timeline_widget by the corresponding values obtained in Step 5

Once the listener has been created, any new temperature reading received by Carriots from electricImp (Step 4) will be forwarded to the two Ducksboard widgets. Additionally the values will also be stored internally in Carriots server.

Note: Temperature readings could be sent directly from electricImp agent to Ducksboard widgets without using Carriots server, but then we would lose the historical series of readings and the possibility to perform offline review and data mining.

Links[edit]

  • Link to the public ducksboard of the temperature sensor used in this example: [19]

Ducksboard TempMSM.jpg