What's the temperature in my room? Do I need to water my plants? I have a Raspberry Pi with several sensors connected to it, it's not hard to answer these questions. SSH to Pi, run a Python script I wrote before and then I can get the data. The problem here is, however, how to access them easily? A web app is a good candidate for this purpose.

Github repository.

Overview


The basic idea is that to create a web app that shows the data from different sensors. The data can be either cached or just updated. The information is presented in a table, with an Update button at the end of each row. Once Update is clicked, the front-end makes an API call so the backend activates the sensor and sends back the date.

Setup


I chose Node.js with Express.js framework as my backend. For front-end, apart from HTML, Javascript and CSS, I also used Jade to generate pages.

Installation

  cd somewhere/
  git clone https://github.com/tylerwowen/pisensors
  cd pisensors
  npm install

npm install will install all required dependencies that are defined in package.json

  chmod 755 pisensor/scripts/temphum.py

After the above steps, the layout should be like this:

├── app.js
├── bin
│   └── www
├── node_modules
│   ├── body-parser
│   ├── debug
│   ├── express
│   ├── jade
│   └── morgan
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── cache
│       └── cache.json
│   ├── objects
│       ├── humidity.js
│       ├── sensor.js
│       ├── temperature.js
│       └── vibration.js
│   ├── index.js
│   └── users.js
├── scripts
│   └── temphum.py
└── views
    ├── error.jade
    ├── index.jade
    └── layout.jade

Configuration

Dependencies

  sudo apt-get update
  sudo apt-get install build-essential python-dev
  git clone https://github.com/adafruit/Adafruit_Python_DHT.git dhtlib
  cd dhtlib
  sudo python setup.py install
  cd .. && sudo rm -r dhtlib

Add New Sensors

When you need to add a new sensor.

  var Sensor = require('./sensor.js');

  function Light(sensor, value, unit) {
    Sensor.call(this, sensor, value, unit);
  }

  Light.prototype = new Sensor();

  Light.prototype.fetchDataFromSensor = function(callback) {
    var cmd = 'sudo ./scripts/light.py'; // You need to write this script
    Sensor.prototype.fetchDataFromSensor.call(this, cmd, callback);
  };

  Light.prototype.fetchDataFromCache = function(cachedData) {
    var JSONData = cachedData.light;
    Sensor.prototype.fetchDataFromCache.call(this, JSONData);
  };

  module.exports = Light;
  ...
  "Vibration": {
    "sensor": "Vibration",
    "value": "True",
    "unit": "celsius",
    "updatedAt": "11:37:31 PM"
  },
  "Light": {
    "sensor": "Light",
    "value": "True",
    "unit": "celsius",
    "updatedAt": "12:27:31 PM"
  }
  ...

Since I haven't implemented the database at this moment(July 26, 2015), it's necessary to modify the cache file manually. Later the MongoDB will be added and this part will be discarded.

Implementation


/routes/index.js

This file is the core of this web application. It has two responsibilities (I know this violates the Single Responsibility Principle, but I will explain):

/routes/objects/Sensor.js

It is the super class for all other specific sensors. It's not totally abstract, and it has some concrete methods.

/views/index.jade

The index.jade provides a layout for the data table. It works for any number of sensors. To do so, it loops over the array sensorData which is passed from index.js.

/public/javascript/main.js

This is the front-end javascript that listens to click events. Once an user clicks the Update button of a sensor, the scripts calls the corresponding API and updates the row based on the response from backend. An example API call: http://127.0.0.1:3000/update/Temperature.

Outcome


The web page looks like the picture below. alt test

Todo


[ ] Add MongoDB supports
[ ] Beautify front-end with Bootstrap
[ ] Data visualization -- present history data in diagrams