SensorHub
Last updated
Was this helpful?
Last updated
Was this helpful?
PoC application and counterpart to. You will be able to fetch multiple MaM-based streams, read, store and plot data, map the sensors location, and more.
Possible use-cases might be:
Monitoring of supply chains
Monitoring in agriculture and farming
Monitoring of vehicle conditions (aircrafts, trucks, trains, cars etc.)
Tracking of personal property (bikes, mobile computers etc.)
Environmental measurements (weather, earthquakes etc.)
$ cd XDK110-Bosch/C/IOTA-XDK110-MAM/SensorHub/
$ npm install
$ cd node_modules
$ git clone https://github.com/rckey/mam.node.js.git
Now we need to modify the code to adapt to xdk payload.
We need to modify:
We need to modify this file to add the line of what data we want to present. In this case was Luminosity,Noise,etc.
..
<div id="stream_data">
<div style="position: relative; width: 100%; padding: 5px; text-align: center; margin-top: 10px; "><h4 id="title">Select a device.</h4><div>
<div style="position: relative; width: 100%; padding: 5px; text-align: center;"><h6 id="loc"></h6></div>
<div class="row" style="margin-top: 20px;">
<div class="col-xs-6" style="text-align: center;"><h4>Temperature:</h4><h5 id="temp"></h5></div>
<div class="col-xs-6" id="temp_ctx"></div>
</div>
<hr>
<div class="row" style="margin-top: 20px;">
<div class="col-xs-6" style="text-align: center;"><h4>Pressure:</h4><h5 id="press"></h5></div>
<div class="col-xs-6" id="press_ctx"></div>
</div>
<hr>
<div class="row" style="margin-top: 20px;">
<div class="col-xs-6" style="text-align: center;"><h4>Humidity:</h4><h5 id="hum"></h5></div>
<div class="col-xs-6" id="hum_ctx"></div>
</div>
<hr>
<div class="row" style="margin-top: 20px;">
<div class="col-xs-6" style="text-align: center;"><h4>Luminosity:</h4><h5 id="lig"></h5></div>
<div class="col-xs-6" id="lig_ctx"></div>
</div>
<hr>
<div class="row" style="margin-top: 20px;">
<div class="col-xs-6" style="text-align: center;"><h4>Noise:</h4><h5 id="noi"></h5></div>
<div class="col-xs-6" id="noi_ctx"></div>
</div>
<hr>
..
This javascript file would help us to receive the information that is on the tangle process and embedded on HTML File. See the comments that are on the file.
//We need to all some libraries to use some components such as map, and also libraries for read the tangle and the nodes.
const {ipcRenderer} = require('electron');
const STREAM = require('./classes/stream');
const MAPSTYLE = require('./includes/style/map');
let streams = [];
let selected;
let map;
let running = false;
// We decleare our initial function, so we need to give a lat and lng and start our google map.
function init() {
let location = {lat: 20.673746, lng: -103.351115};
map = new google.maps.Map(document.getElementById('map'), {
zoom: 15,
center: location,
disableDefaultUI: true,
styles: MAPSTYLE
});
/* prototyping */
/*
let ROOTS = ['ONXDTKYBGKGUTAHLMSIZKDBJQHQXWFHSWZJMQTPONYPXGMCFIJGLI9KTASGOL9EFYRHIYLSXGDVVOPLKT',
'DULFOPIOOHWVRDVH9QHZZFEDHRUDWYS9MSY9XTYOEDO9JB9RRJPNUG9ERZCHUVSEDYYWJREELQUXUDFJR',
'PE9KCPMWZKLXIUDKSBFMYGPLFCSJFSAGKXIUHDQDYIGEOKIRTJRZKHMFYJYBSOHQGVHEEJWVBLHMLDNVI']
ROOTS.forEach(root => {
addStream(root);
})
fetchStream(0);
*/
}
//We start to read the node info and attach on html pages
ipcRenderer.on('nodeInfo', (event, packet) => {
$("#iriVersion").html(packet.appVersion);
$("#syncState").html(Math.abs(packet.latestSolidSubtangleMilestoneIndex - packet.latestMilestoneIndex) < 5 ? 'Yes' : 'No');
});
//When we add a root and hit enter this would we add to the list of devices and start to sense the data.
$("#stream_add").keypress(function (_e) {
if (_e.which === 13 && _e.target.value != '') {
addStream(_e.target.value);
_e.target.value = '';
}
});
//We initialies the root to start reading that devices through the time.
ipcRenderer.on('setRoot', (event, id, _newRoot) => {
streams[id].root = _newRoot;
/* next stream */
setTimeout(fetchStream, 1000, ++id);
});
//Read the information from the tangle and start divide each component of the json and past the stream on the html.
ipcRenderer.on('fetchPacket', (event, _packet, id) => {
if (streams[id].id == '') {
$('#temp_ctx').children().hide();
$('#press_ctx').children().hide();
$('#hum_ctx').children().hide();
$('#lig_ctx').children().hide();
$('#noi_ctx').children().hide();
$('#temp_ctx').append('<canvas id="' + streams[id].firstRoot + '_temperature_ctx"></canvas>');
$('#press_ctx').append('<canvas id="' + streams[id].firstRoot + '_pressure_ctx"></canvas>');
$('#hum_ctx').append('<canvas id="' + streams[id].firstRoot + '_humidity_ctx"></canvas>');
$('#lig_ctx').append('<canvas id="' + streams[id].firstRoot + '_light_ctx"></canvas>');
$('#noi_ctx').append('<canvas id="' + streams[id].firstRoot + '_noise_ctx"></canvas>');
}
//Get the coordenates and set the device on the map
$('#' + streams[id].streamLabel).html(_packet.id);
streams[id].id = _packet.id;
let location = {lat: _packet.location.lat, lng: _packet.location.lng};
streams[id].location = location;
streams[id].marker.setPosition(location);
streams[id].lastUpdate = _packet.timestamp;
/* for prototyping */
let d1 = {'temperature': _packet.temperature}
streams[id].addData(d1, _packet.timestamp);
let d2 = {'pressure': _packet.pressure}
streams[id].addData(d2, _packet.timestamp);
let d3 = {'humidity': _packet.humidity}
streams[id].addData(d3, _packet.timestamp);
let d4 = {'light': _packet.light}
streams[id].addData(d4, _packet.timestamp);
let d5 = {'noise': _packet.noise}
streams[id].addData(d5, _packet.timestamp);
if (selected != null && selected == id) {
select(id);
}
});
//Read the data of the specific device
function fetchStream (id) {
id = id > streams.length - 1 ? 0 : id;
highlight(id);
ipcRenderer.send('fetchRoot', streams[id].root, id);
}
function select (id) {
$('#stream_feed > div').each(function () {
$(this).removeClass('active');
});
$('#label_' + id).addClass('active');
selected = id;
map_panTo(streams[id].location);
output();
}
//We add the stream to the map
function addStream (root) {
let s = new STREAM(root);
let id = streams.length;
s.streamLabel= 'label_' + id + '_title';
streams.push(s);
let new_label = '<div class="stream_label" id="label_'
+ id + '" onclick="select(' + id + ');">' + '<h5 id="'
+ s.streamLabel+ '">...' + '</h5><span id="sync_indicator_'
+ id + '" class="label label-white">< 10 sec<span></div>';
$('#stream_feed').append(new_label);
selected = id;
if (running == false) {
running = true;
fetchStream(0);
}
}
function map_panTo (location) {
map.panTo(location);
}
//We the define the output and also the data of the chart to give this information and the values can be reflected
function output () {
if (streams[selected].datasets == undefined)
return;
let data = streams[selected].datasets;
// SET OUTPUT
$('#title').text(streams[selected].id);
$('#loc').text('Lat: ' + streams[selected].location.lat + ' Lng: ' + streams[selected].location.lng);
$('#temp').text(data.temperature[data.temperature.length - 1]);
$('#press').text(data.pressure[data.pressure.length - 1]);
$('#hum').text(data.humidity[data.humidity.length - 1]);
$('#lig').text(data.light[data.light.length - 1]);
$('#noi').text(data.noise[data.noise.length - 1]);
// SET CHARTS
$('#temp_ctx').children().hide();
$('#press_ctx').children().hide();
$('#hum_ctx').children().hide();
$('#lig_ctx').children().hide();
$('#noi_ctx').children().hide();
$('#' + streams[selected].firstRoot + '_temperature_ctx').show();
$('#' + streams[selected].firstRoot + '_pressure_ctx').show();
$('#' + streams[selected].firstRoot + '_humidity_ctx').show();
$('#' + streams[selected].firstRoot + '_light_ctx').show();
$('#' + streams[selected].firstRoot + '_noise_ctx').show();
//SET HISTORY
$('#history_title').html(streams[selected].id);
$('#history_table').html('');
Object.keys(data).forEach(function (key) {
$('#history_table').append('<h4>' + key + ':</h4></br>');
data[key].forEach(function (value) {
$('#history_table').append('    ' + value + '</br>');
})
});
}
function highlight (id) {
$('#stream_feed > div > span').each(function () {
$(this).removeClass('highlight');
});
$('#sync_indicator_' + id).addClass('highlight');
}
$("#stream_delete").click(function (_e) {
if (confirm('Are you sure you want to delete \"' + streams[selected].id + '\"?')) {
alert('Im sorry, can\'t do that for now.');
} else {
}
});