How to send data points to Ubidots from gateway

Started by detroit_johnny, November 29, 2015, 08:49:25 PM

detroit_johnny

I'm looking to send data from one of my motes that talks to the Pi Gateway to the ubidots.com web site.  Purpose:  push data to Ubidots and create a widget for a website that reads from it.  I prefer not to have any web site read directly from my pi gateway inside my house. 

Ubidots requires and API key and variable for upload which I setup.  I can run test code from my gateway pi in the form of a python script that sends a random number to ubidots.  Is there an easy way via an event in the metrics.js file to do this?  I'm thinking there is but I really need some guidance.  I'm not having a lot of luck playing around with the metrics file. 


detroit_johnny

#1
I almost have this working but I'm stuck with "stale" data for some reason.

First step, I needed to install the ubidots support on my gateway pi like this:
npm install ubidots

Then I went into my metrics.js file and I have 2 sections.  One is the event and the other is the helper function.

First the event:
ubidotsVoltagePost : { label:'Post voltage to ubidots site', icon:'comment', descr:'Post data to ubidots', 
	nextSchedule:function(node) { return 300000; }, 
	scheduledExecute:function(node) {
	  exports.vmoteData(node.metrics['VAC'].value);
  }},


Then the helper function:
exports.vmoteData = function(ubiVolts) {
var ubidots = require('ubidots');
var client = ubidots.createClient('YOUR-UBIDOTS-API-KEY');

client.auth(function () {
  var v = this.getVariable('YOUR-UBIDOTS-VARIABLE-ID-NUMBER');
  v.saveValue(ubiVolts);
  console.log('Sending voltage to Ubidots: ' + ubiVolts);
});
}


The problem I'm having is the code keeps posting the old, original voltage value every 5 minutes, even though the voltage value is fluctuating on my gateway (I see it on my dashboard).  Why does the javascript not update and send the most up to date 'VAC' value?

HeneryH

I just looked up Ubidots.  Off topic of you question but...  damn, I'd have more than 5 sensors in no time then you are quickly at $12/mo.  Too rich for my blood!

detroit_johnny

So far I'm trying to stick to their free plan, not updating often, and only 1 sensor.  I'm making this voltage sensor public for my home owner's association web site... I'll create an ubidots "widget" to show my home's line voltage but only update every 5-10 minutes.  Someday this might blossom into measuring our community pool's water temperature as well.

I'm with you HeneryH, free is better!  :-)  For my own personal checks on my sensors I just VPN into my house on my phone. 

Felix

Quote from: detroit_johnny on December 01, 2015, 09:06:33 PM
I almost have this working but I'm stuck with "stale" data for some reason.
The problem I'm having is the code keeps posting the old, original voltage value every 5 minutes, even though the voltage value is fluctuating on my gateway (I see it on my dashboard).  Why does the javascript not update and send the most up to date 'VAC' value?

I think your stale data is because of a closure. You are basically capturing the data of the metric at the time of the definition, instead I would try to define a function that gets the metric value and call that instead of the metric value itself.

detroit_johnny

I've been trying to solve this but I don't quite understand what is going on.  I see other events in the metrics.js that call for metric values and those don't go stale.  I don't know how to formulate a function that can call the most recent 'VAC' data point I have.  Any tips?

Felix

#6
It would be something like this:

exports.getMetricValue: function(metricName) { return exports.vmoteData(node.metrics[metricName].value); }

ubidotsVoltagePost : { label:'Post voltage to ubidots site', icon:'comment', descr:'Post data to ubidots', 
	nextSchedule:function(node) { return 300000; }, 
	scheduledExecute:function(node) {
	  exports.vmoteData(getMetricValue('VAC'));
  }},


detroit_johnny

Thanks Felix.  Tried your code as guidance and I have this version now but still gives stale / unchanging original initial value and never changes...

First the event definition, now does not store any variable but passes node and metric name info to the external helper:
  ubidotsVoltagePost : { label:'Post voltage to ubidots site', icon:'comment', descr:'Post data to ubidots', 
	nextSchedule:function(node) { return 300000; }, 
	scheduledExecute:function(node) {
	  exports.getMetricValue(node, 'VAC');
  }},


Then the helper function outside the event code does all the work to figure out the VAC value and then post it to Ubidots (but the VAC value never changes):
exports.getMetricValue = function(node, metricName) { 
  var ubiVolts = node.metrics[metricName].value; 
  var ubidots = require('ubidots');
  var client = ubidots.createClient('UBIDOTS-API-KEY');

client.auth(function () {
  var v = this.getVariable('UBIDOTS-VARIABLE-ID-NUMBER');
  v.saveValue(ubiVolts);
  console.log('Sending voltage to Ubidots: ' + ubiVolts);
  });
}


Scratching my head...do I need to "flush" the variable data or something to force the code to get the value again?  So strange... other event functions work fine  :-\ 

Felix

I think I missed wrapping the getValue call in exports.vmoteData, I added that above. But I haven't tried this code, it was just a suggestion. I would use the log to do some debugging to identify why the data is stale, that's the easy way without getting into nodeJS debuggers.

detroit_johnny

I got it to work.  I can't explain why it works, but maybe someone can based on my code.  I think the key is this global variable?

First I created a global variable in the metrics.js file.  This line of code is just after Felix's introductory code, around line 79.  It's not tied to any event
var ubiVolts = 0;


Then I created a new, additional event on top of the Ubidots event I already had.  Here's how the those two events are coded
metricUpdater : { label:'Update a metric so it can be used on other websites', icon:'comment', descr:'Use with Ubidots for example', serverExecute:function(node) { if (Date.now() - new Date(node.metrics['VAC'].updated).getTime() < 2000) { ubiVolts = (node.metrics['VAC'].value);  }; } },
	
  ubidotsVoltagePost : { label:'Post voltage to ubidots site', icon:'comment', descr:'Post data to ubidots', 
	nextSchedule:function(node) { return 300000; }, 
	scheduledExecute:function(node) {
	  exports.getMetricValue(node, ubiVolts);
  }},


And finally the helper function I had to tweak just a little bit but mostly unchanged...
exports.getMetricValue = function(node, ubiVolts) { 
var ubidots = require('ubidots');
var client = ubidots.createClient('UBIDOTS-API-KEY');

client.auth(function () {
  var v = this.getVariable('UBIDOTS-VARIABLE-ID-NUMBER');
  v.saveValue(ubiVolts);
  console.log('Sending voltage to Ubidots: ' + ubiVolts);
});
}


Felix