BlocNotes

Notepad of a tinker, maker, hacker or whatever you call it :)

Dashing - Job to get data from InfluxDB v0.8 database

To use my dashboard, I wrote some Dashing jobs to be able to query some values from my InfluxDB database.

There is 3 versions:

  • In Ruby
  • In node.js (javascript) after my switch to Dashing-js
  • A way to update a 'list' widget

The third code also changes the background color of a list widget, to set it regarding data values. I will share the widget's code soon, I just need some time to clean a bit the code

1. Ruby code

# Insert required components
require 'json'
require 'net/http'

# Parameter
serverAddr = 'http://localhost:8086'

# :first_in sets how long it takes before the job is first run. In this case, it is run immediately
SCHEDULER.every '1m', :first_in => 0 do |job|

  # Url to get data
  url = URI( "#{serverAddr}/db/db_name/series?u=xxxx&p=xxxx&q=SELECT%20*%20FROM%20%22/data/Conservatory/Humidity%22%20LIMIT%201" )
  # Query server
  res = Net::HTTP.get( url )
  # Transforms JSON in object
  j = JSON.parse(res)
  send_event('welcome', { text: j[0]['points'][0][2] })
  send_event('synergy', { value: j[0]['points'][0][2] }) 

end

2. In node.js, easier to modify

// Includes
var request = require( 'request' )

// Configuration
var dbAddress = 'localhost'
var dbPort = '8086'
var dbName = 'XXXX'
var dbUser = 'XXXX'
var dbPwd = 'XXXX'
var refreshTime = 60*1000    // in ms

function getData( parameterToRefresh, widgetId, unit ) {
  // URL creation
  var urlToGet = 'http://'+dbAddress+':'+dbPort+'/db/'+dbName+'/series?u=' + dbUser+'&p='+dbPwd+'&q=SELECT%20*%20FROM%20%22/data/'+parameterToRefresh+'%22%20LIMIT%201'
  // Request
  request( urlToGet, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      // No error, send the value to the dashboard
   	  send_event( widgetId, { value: Math.round(JSON.parse(body)[0]['points'][0][2]*100)/100 })
    }
  })
}

setInterval( function() { getData( 'Outside/Pressure', 'outsideText', ' mbara' ) }, refreshTime )

3. And a way to fill a 'list' widget

<pre>// Includes
var http = require( 'http' )
var async = require( 'async' )
var request = require( 'request' )

// Configuration
var dbAddress = 'localhost'
var dbPort = '8086'
var dbName = 'XXXX'
var dbUser = 'XXXX'
var dbPwd = 'XXXX'
// itemsToQuery [ dataNameInInflux, NameToDisplayInWidget ]
var itemsToQuery = [ [ 'Conservatory',  'PLA' ],
                     [ 'SensorTest_1',  'Citrus' ],
                     [ 'LivingRoom',    'Salon' ],
                     [ 'Office',        'Bureau' ]
                    ]
var refreshTime = 60*1000    // in ms

// Function to fetch data
function getDataList(url, callback) {
  var data = ""

  var req = http.request(url, function(res) {
    res.on('data', function(chunk) {
        data += chunk
    })
    res.on('end', function(e) {
        callback(e, data)
    })
  }).end()
}

function refreshDataList( parameterToRefresh, widgetId, unit ) {
  // Variables declaration
  var urls = []
  var itemarray = []
  var average = 0

  // Set url regarding unit
  switch( unit ) {
    case ' %': urlPrefix = 'data/'; urlSuffix = '/'+parameterToRefresh; break
    case '°C': urlPrefix = 'data/'; urlSuffix = '/'+parameterToRefresh; break
    default:   urlPrefix = parameterToRefresh+'/'; urlSuffix = ''; break
  }
  // Table construction regarding the items ot query
  for( var i = 0; i < itemsToQuery.length-1; i++ ) {
    urls.push( 'http://'+dbAddress+':'+dbPort+'/db/'+dbName+'/series?u='+dbUser+'&p='+dbPwd+'&q=SELECT%20*%20FROM%20%22/'+urlPrefix+ encodeURIComponent(itemsToQuery[i][0])+urlSuffix+'%22%20LIMIT%201')
  }

  // Asynchronous call to get the data
  async.map( urls, getDataList, function( err, result ) {
    // Parse results
    for( var i = 0; i < result.length; i++ ) {
      itemarray[i] = {label: itemsToQuery[i][1], value: (JSON.parse(result[i])[0]['points'][0][2] + unit)}
      average = average + JSON.parse(result[i])[0]['points'][0][2]
    }
    average = Math.round( average/result.length*100 )/100

    // Select color and 'moreinfo' message regarding data type and average value
    switch( unit ) {
      case ' %':
        backGroundColor = humidityColor( average )
        moreinfo = 'Moyenne : ' + average + unit; break
      case '°C':
        backGroundColor = insideTemperatureColor( average );
        moreinfo = 'Moyenne : ' + average + unit; break
      case ' V':
        mini = Math.min.apply(Math, result.map(function(table) { return JSON.parse(table)[0]['points'][0][2] }))
        backGroundColor = batteryLevelColor( mini )
        moreinfo = 'Minimum : ' + mini + unit; break
      case ' dB':
        mini = Math.min.apply(Math, result.map(function(table) { return JSON.parse(table)[0]['points'][0][2] }))
        backGroundColor = rssiColor( mini )
        moreinfo = 'Minimum : ' + mini + unit; break
      default:
        backGroundColor = '55555'
    }

    // Prepare structure to send
    var datastruct = {
      items: itemarray,
      backGroundColor: backGroundColor,
      moreinfo:  moreinfo
    }
    send_event( widgetId, datastruct )
  })
}

// Set job call every refreshTime
setInterval( function() { refreshDataList( 'Humidity', 'humidityList', ' %' ) }, refreshTime )