Store Arduino data to Firebase database [Howto]




The last few weeks I was playing with Firebase mostly because I wanted to get familiar with this technology. So at some point I thought that it will be a great idea to connect Arduino with Firebase. Imagine that you have a simple temperature sensor that measures the boiler’s water temperature every few minutes and you want to keep a history log of it in order to make some adjustments to thermostat. If you also want those measurements to be available online so you will be able to access them at any time then each sensor reading has to be stored somewhere.

One great way that I was also using for that kind of things is Xively. Originally it was Pachube , then Cosm and now Xively. I hope the guys don’t decide to change the name again! With Xively client for arduino you simply connect to their Api and you send them the readings. Its fast, its simple and they also have a free plan. But there are a few things that might not work for you. One of them is the limit of readings that you can store, at the moment in free plan you can have up to 3 months history. Store Arduino data to Firebase database [Howto]




Another thing is that you can’t send data every 1 sec, so its impossible to store almost real time readings. And last but not least you need to consider that you are storing YOUR data in a database that you do not have control.

So what are the alternatives? Having your own sql database server is an overkill, not only because of the cost but also for maintenance reasons. For such simple projects you don’t have to spend a fortune. So here is where Firebase comes. The Firebase guys lets you connect to your own firebase database and do  all the CRUD operations through simple calls to their api. You can visit their website and they will give you a 100mb database free. Which is enough to store at least a years readings. This is what I thought but quickly I came up with a huge problem. Firebase uses only HTTPS for security reasons and my Arduino Uno’s microprocessor don’t have enough power for that. In this link you can read what a member of firebase team says about the ssl support. The idea to bypass this issue is to proxy the requests through a server that can speak ssl. In order to achieve this I used the Firebase PHP library that you can find here. Think of it like this Arduino->Php website->Firebase. Once the data are in Firebase then you reatrive them in many different ways.  Let’s start building our project and you will see how all the parts connect together.

First the hardware part. In my case I used the popular DS1820 temperature sensor. By connecting it to my Arduino Uno I was getting  the room temperature readings. I also had to use an Ethernet shield. I had a spare W5100 so I made a small stack: Arduino Uno-Ethernet Sheild W5100-Prototyping Sheild. The circuit diagram is this:

And here is mine with all the parts connected:

Next step is to create your free firebase database in http://www.firebase.com. Then log into the database and go at the last menu item “Secrets”. From there you will get your secret token. Write it down as we will need it later. So now we have the hardware and the database ready. If you dont already have a domain, or sub domain go get one from your favorite registar and host the Firebase php library file in one of the thousand hosting providers that offer free plans. Personally I have a windows azure account so I just went there and created a new website.

Then by ftp I uploaded the firebaseLib.php:

<?php

/**
 * Firebase PHP Client Library
 *
 * @author Tamas Kalman <[email protected]>
 * @link   https://www.firebase.com/docs/rest-api.html
 *
 */

/**
 * Firebase PHP Class
 *
 * @author Tamas Kalman <[email protected]>
 * @link   https://www.firebase.com/docs/rest-api.html
 *
 */
class Firebase
{

    private $_baseURI;
    private $_timeout;
    private $_token;

    /**
     * Constructor
     *
     * @param String $baseURI Base URI
     *
     * @return void
     */
    function __construct($baseURI = '', $token = '')
    {
        if (!extension_loaded('curl')) {
            trigger_error('Extension CURL is not loaded.', E_USER_ERROR);
        }

        $this->setBaseURI($baseURI);
        $this->setTimeOut(10);
        $this->setToken($token);
    }

    /**
     * Sets Token
     *
     * @param String $token Token
     *
     * @return void
     */
    public function setToken($token)
    {
        $this->_token = $token;
    }

    /**
     * Sets Base URI, ex: http://yourcompany.firebase.com/youruser
     *
     * @param String $baseURI Base URI
     *
     * @return void
     */
    public function setBaseURI($baseURI)
    {
        $baseURI .= (substr($baseURI, -1) == '/' ? '' : '/');
        $this->_baseURI = $baseURI;
    }

    /**
     * Returns with the normalized JSON absolute path
     *
     * @param String $path to data
     */
    private function _getJsonPath($path)
    {
        $url = $this->_baseURI;
        $path = ltrim($path, '/');
        $auth = ($this->_token == '') ? '' : '?auth=' . $this->_token;
        return $url . $path . '.json' . $auth;
    }

    /**
     * Sets REST call timeout in seconds
     *
     * @param Integer $seconds Seconds to timeout
     *
     * @return void
     */
    public function setTimeOut($seconds)
    {
        $this->_timeout = $seconds;
    }

    /**
     * Writing data into Firebase with a PUT request
     * HTTP 200: Ok
     *
     * @param String $path Path
     * @param Mixed  $data Data
     *
     * @return Array Response
     */
    public function set($path, $data)
    {
      return $this->_writeData($path, $data, 'PUT');
    }

    /**
     * Pushing data into Firebase with a POST request
     * HTTP 200: Ok
     *
     * @param String $path Path
     * @param Mixed  $data Data
     *
     * @return Array Response
     */
    public function push($path, $data)
    {
      return $this->_writeData($path, $data, 'POST');
    }

    /**
     * Updating data into Firebase with a PATH request
     * HTTP 200: Ok
     *
     * @param String $path Path
     * @param Mixed  $data Data
     *
     * @return Array Response
     */
    public function update($path, $data)
    {
      return $this->_writeData($path, $data, 'PATCH');
    }

    /**
     * Reading data from Firebase
     * HTTP 200: Ok
     *
     * @param String $path Path
     *
     * @return Array Response
     */
    public function get($path)
    {
        try {
            $ch = $this->_getCurlHandler($path, 'GET');
            $return = curl_exec($ch);
            curl_close($ch);
        } catch (Exception $e) {
            $return = null;
        }
        return $return;
    }

    /**
     * Deletes data from Firebase
     * HTTP 204: Ok
     *
     * @param type $path Path
     *
     * @return Array Response
     */
    public function delete($path)
    {
        try {
            $ch = $this->_getCurlHandler($path, 'DELETE');
            $return = curl_exec($ch);
            curl_close($ch);
        } catch (Exception $e) {
            $return = null;
        }
        return $return;
    }Store Arduino data to Firebase database [Howto] Schematic

    /**
     * Returns with Initialized CURL Handler
     *
     * @param String $mode Mode
     *
     * @return CURL Curl Handler
     */
    private function _getCurlHandler($path, $mode)
    {
        $url = $this->_getJsonPath($path);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_timeout);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $mode);
        return $ch;
    }

    private function _writeData($path, $data, $method = 'PUT')
    {
        $jsonData = json_encode($data);
        $header = array(
            'Content-Type: application/json',
            'Content-Length: ' . strlen($jsonData)
        );
        try {
            $ch = $this->_getCurlHandler($path, $method);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
            $return = curl_exec($ch);
            curl_close($ch);
        } catch (Exception $e) {
            $return = null;
        }
        return $return;
    }

}

And now the most importand file that you also have to upload to your hosting directory. Its the file that will respond to Arduino requests. I named it firebaseTest.php

 

For more detail: Store Arduino data to Firebase database [Howto]




Clip to Evernote

Leave a Comment

(Spamcheck Enabled)

Read previous post:
THE GERTBOT POWER CONTROLLER
THE GERTBOT POWER CONTROLLER

The Gertbot board works as either a stand-alone power controller connected to a computer via a serial link and controlled...

Close
Scroll to top