Fake JSON Server as an IoT Backend

How to use Fake JSON Server as an IoT Back End.

Setup:

RuuviTag Sensor <- Raspberry PI -> PC with Fake JSON Server

Raspberry Pi is scanning RuuviTag sensors and when the updated data for the sensor is found, it sends new data to Fake JSON Server.

Running the Setup

Start Fake JSON Server

  1. Clone the repository
    $ git clone https://github.com/ttu/dotnet-fake-json-server.git
    $ cd dotnet-fake-json-server/FakeServer
    
  2. Copy sensors.html from Gist to /wwwroot folder
  3. Edit appsettings.json
    • Set Common.EagerDataReload to false
    • Set Api.UpsertOnPut to true
  4. Start the server
    $ dotnet run --file iot.json --urls http://0.0.0.0:57602
    
  5. Open http://localhost:57602/sensors.html

Install RuuviTag Package on Raspberry Pi (Raspbian) or on a PC with Linux

RuuviTag Python package Installation Guide

Execute Python Script

IP address of PC with Fake JSON Server is 192.168.2.22.

from datetime import datetime
from urllib.parse import quote
import requests
from ruuvitag_sensor.ruuvi import RuuviTagSensor

all_data = {}
url = 'http://192.168.2.22:57602/api'

def handle_data(new_data):
    sensor_mac = new_data[0]
    sensor_data = new_data[1]

    if sensor_mac not in all_data or all_data[sensor_mac]['data'] != sensor_data:
        # sensordatas POST will overwrite id, but sensors PUT will use it
        update_data = {'id': sensor_mac, 'mac': sensor_mac, 'data': sensor_data, 'timestamp': datetime.now().isoformat()}
        all_data[sensor_mac] = update_data
        requests.put('{url}/sensors/{mac}'.format(url=url, mac=quote(sensor_mac)), json=update_data)
        requests.post('{url}/sensordatas'.format(url=url), json=update_data)

RuuviTagSensor.get_datas(handle_data)

Async version of the script can be found from ruuvitag-sensor/examples.

Script sends data to 2 different endpoints:

POST /api/sensordatas    : sensordatas has all sent datas
PUT  /api/sensors/{mac}  : sensors has latest data for each sensor

Saved Data

Data in iot.json. Sensors have different fields depending on the sensor’s firmware.

{
  "sensors": [
    {
      "id": "F4:A5:74:89:16:57",
      "mac": "F4:A5:74:89:16:57",
      "data": {
        "humidity": 46.5,
        "temperature": 24.36,
        "pressure": 998.55,
        "acceleration": 1038.0433516958722,
        "acceleration_x": 78,
        "acceleration_y": -15,
        "acceleration_z": 1035,
        "battery": 2893
      },
      "timestamp": "2017-07-01T18:36:56.547306"
    },
    {
      "id": "CA:F7:44:DE:EB:E1",
      "mac": "CA:F7:44:DE:EB:E1",
      "data": {
        "temperature": 24.0,
        "humidity": 38.0,
        "pressure": 998.0,
        "identifier": null
      },
      "timestamp": "2017-07-01T18:36:57.229115"
    }
  ],
  "sensordatas": [
    {
      "id": 0,
      "mac": "F4:A5:74:89:16:57",
      "data": {
        "humidity": 46.5,
        "temperature": 24.35,
        "pressure": 998.48,
        "acceleration": 1030.2921915650918,
        "acceleration_x": 82,
        "acceleration_y": -7,
        "acceleration_z": 1027,
        "battery": 2887
      },
      "timestamp": "2017-07-01T18:36:56.044941"
    },
    {
      "id": 1,
      "mac": "F4:A5:74:89:16:57",
      "data": {
        "humidity": 46.5,
        "temperature": 24.36,
        "pressure": 998.55,
        "acceleration": 1038.0433516958722,
        "acceleration_x": 78,
        "acceleration_y": -15,
        "acceleration_z": 1035,
        "battery": 2893
      },
      "timestamp": "2017-07-01T18:36:56.547306"
    },
    {
      "id": 2,
      "mac": "CA:F7:44:DE:EB:E1",
      "data": {
        "temperature": 24.0,
        "humidity": 38.0,
        "pressure": 998.0,
        "identifier": null
      },
      "timestamp": "2017-07-01T18:36:57.229115"
    }
  ]
}

Sensors HTML Page

HTML page has a component for each sensor:

Every time a new data is sent to the back end, the page gets a notification with a websocket and the data for that sensor is updated with a new request.

Q & A

Q: Why Fake JSON Server is not running on Raspberry Pi?
A: At the moment .NET Core and ARM setup requires some manual work and I’m currently too lazy to do that.

Q: Why wouldn’t I just use Redis, InfluxDB or some othe database?
A: All of those are better options that this.

Written on August 4, 2017