vincent wong
Published © GPL3+

Publish Hexiwear sensor data onto ARTIK with Evothings

With Evothings, you can publish Hexiwear sensors onto ARTIK cloud uisng Javascript.

IntermediateFull instructions provided1,415
Publish Hexiwear sensor data onto ARTIK with Evothings

Things used in this project

Hardware components

Hexiwear
NXP Hexiwear
×1

Software apps and online services

Evothings Studio
Evothings Studio
ARTIK Cloud for IoT
Samsung ARTIK Cloud for IoT

Story

Read more

Code

app.js

JavaScript
// Using closure to avoid global name space conflicts.
;(() =>
{
'use strict';

// Timeinterval between acceleration fetch. 
const ACCELERATION_SAMPLE_PERIOD = 200; 
const MOTION_SERVICE_UUID = '2000';
const ACCELERATION_CHARACTERISTIC_UUID = '2001';

var Client = require("node-rest-client").Client;

// Application object
var app = {};

// Name of the device the application will try to connect to. 
app.deviceName = 'ChangeMe!!';

// The BLE GATT server.
app.gattServer = null;

// BLE objects
app.motionService = null;
app.accelerationCharacteristic = null;
app.accelerationSamples = []; 

// artik cloud node-rest-client functions
app.artikcloud = "https://api.artik.cloud/v1.1/messages";
app.bearer = "Bearer device-token";
app.sdid = "device-id";

app.c = new Client();

app.build_args = function(ax, ay, az, ts) {

	var args = {
		headers: {
			"Content-Type": "application/json",
			"Authorization": app.bearer 
		},  
		data: { 
    		"sdid": app.sdid,
			"ts": ts,
			"type": "message",
			"data": {
				"x": ax,
				"y": ay,
				"z": az
   			}
		}
	};
	return args;
};
// end artik cloud functions


// Initialise the application.
app.initialize = function() {

	document.addEventListener(
		'deviceready',
		app.onDeviceReady,
		false);
};

// When low level initialization is complete, this function is called.
app.onDeviceReady = function() {

	// Report status.
	app.showInfo('Enter BLE device name and tap Connect');

	// Show the saved device name, if any.
	var name = localStorage.getItem('deviceName');
	if (name) {

		app.deviceName = name;
	}
	$('#deviceName').val(app.deviceName);

	// Register callback for connectButton
	$('#connectButton').click(app.onConnectButton);	
};

// Executed when the Connect/Disconnect button is pressed. 
app.onConnectButton = function() {
	
	if(app.gattServer) {
		
		app.disconnect();
	}
	else {

		app.connect();
	}
};

// Try to connect the smartphone to the GATT server.
app.connect = function() {

	// Get device name from text field.
	app.deviceName = $('#deviceName').val();

	// Save it for next time we use the app.
	localStorage.setItem('deviceName', app.deviceName);

	// Disconnect if connected.
	if (app.gattServer && app.gattServer.connected)
	{
		app.gattServer.disconnect();
		app.gattServer = null;
	}

	app.showInfo('Status: Scanning...');

	// Find and connect to device and get characteristics for LED read/write.
	bleat.requestDevice({

		filters:[{ name: app.deviceName }]
	})
	.then(device => {

		app.showInfo('Status: Found device: ' + device.name);

		// Connect to device.
		return device.gatt.connect();
	})
	.then(server => {

		app.showInfo('Status: Connected');
		
		// Save gatt server.
		app.gattServer = server;

		$('#connectButton').html('Disconnect').attr('class', 'red');

		app.timer = setInterval(function() {

			app.gattServer.getPrimaryService(MOTION_SERVICE_UUID).then(service => {
				
				app.motionService = service;
				
				return app.motionService.getCharacteristic(ACCELERATION_CHARACTERISTIC_UUID);
			})
			.then(characteristic => {

				app.accelerationCharacteristic = characteristic;
				
				return app.accelerationCharacteristic.readValue(); 
			})
			.then(accelerationBuffer => {

				// Parse acceleration variables. 
				var ax = accelerationBuffer.getInt16(0, true) / 100.0;
				var ay = accelerationBuffer.getInt16(2, true) / 100.0;
				var az = accelerationBuffer.getInt16(4, true) / 100.0;

				app.drawDiagram({ x: ax, y: ay, z: az });
				
				var args = app.build_args(ax, ay, az, new Date().valueOf());

				app.c.post(app.artikcloud, args, function(data, response) {            
					console.log(data);
				});

			})
			.catch(error => {

				app.showInfo(error);
			});

		}, ACCELERATION_SAMPLE_PERIOD);


	})
	.catch(error => {

		app.showInfo(error);
	});
};

// Disconnect smartphone from the GATT server.
app.disconnect = function() {

	// Disconnect from GATT server
	app.gattServer.disconnect();
	app.gattServer = null; 
	clearInterval(app.timer);

	// Update UI 
	app.clearDiagram();
	app.showInfo('Status: Disconnected');
	$('#connectButton').html('Connect').attr('class', 'blue');
};


// Print debug info to console and application UI.
app.showInfo = function(info) {

	document.getElementById('info').innerHTML = info;
	console.log(info);
};

app.clearDiagram = function() {

	var canvas = document.getElementById('canvas');
	var context = canvas.getContext('2d');

	// Clear diagram canvas.
	context.clearRect(0, 0, canvas.width, canvas.height);
	
	// Remove samples from array.
	app.accelerationSamples.length = 0;
};

// Draw diagram to canvas. 
app.drawDiagram = function(values) {

	var canvas = document.getElementById('canvas');
	var context = canvas.getContext('2d');

	// Add recent values.
	app.accelerationSamples.push(values);

	// Remove data points that do not fit the canvas.
	if (app.accelerationSamples.length > canvas.width) {

		app.accelerationSamples.splice(0, (app.accelerationSamples.length - canvas.width));
	}

	// Value is an accelerometer reading between -1 and 1.
	function calcDiagramY(value){

		// Return Y coordinate for this value.
		var diagramY = ((value * canvas.height) / 8) + (canvas.height / 2);
		return diagramY;
	}

	function drawLine(axis, color) {

		context.strokeStyle = color;
		context.beginPath();
		var lastDiagramY = calcDiagramY(
			app.accelerationSamples[app.accelerationSamples.length-1][axis]);
		context.moveTo(0, lastDiagramY);
		var x = 1;
		for (var i = app.accelerationSamples.length - 2; i >= 0; i--)
		{
			var y = calcDiagramY(app.accelerationSamples[i][axis]);
			context.lineTo(x, y);
			x++;
		}
		context.stroke();
	}

	// Clear background.
	context.clearRect(0, 0, canvas.width, canvas.height);

	// Draw lines.
	drawLine('x', '#f00');
	drawLine('y', '#0f0');
	drawLine('z', '#00f');
};

// Initialize the app.
app.initialize();

})(); 

index.html

HTML
<!DOCTYPE html>

<html>

<head>

	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, user-scalable=no,
		shrink-to-fit=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />

	<title>HEXIWEAR - ARTIK</title>

	<style>
		@import 'ui/css/evothings-app.css';
	</style>

	<style>
		#connectButton {
			width: 100%;
			float: left;
		}

		#disconnectButton {
			width: 49%;
			float: right;
		}

		#deviceName {
			width: 100%;
			display: block;
			-webkit-box-sizing: border-box;
			box-sizing: border-box;
		}

	</style>

	<script>

	// Redirect console.log to Evothings Workbench.
	if (window.hyper && window.hyper.log) { console.log = hyper.log }
	</script>

	<!--script src="bundle.js"></script-->
	<script src="cordova.js"></script>
	<script src="libs/jquery/jquery.js"></script>
	<script src="libs/evothings/evothings.js"></script>
	<script src="libs/evothings/ui/ui.js"></script>
	<script src="libs/bleat/bluetooth.helpers.js"></script>
	<script src="libs/bleat/api.web-bluetooth.js"></script>
	<script src="libs/bleat/adapter.evothings.js"></script>
	<script src="bundle-app.js"></script>

</head>

<body ontouchstart=""><!-- ontouchstart="" enables low-delay CSS transitions. -->
	<header>
		<button class="back" onclick="history.back()">
			<img src="ui/images/arrow-left.svg" />
		</button>
		<img class="logotype" src="ui/images/logo.svg" alt="Evothings" />
	</header>

	<h1>HEXIWEAR - ARTIK</h1>

	<h2>Enter name of your BLE device</h2>

	<input id="deviceName" value="ChangeMe!!" type="text" />

	<button id="connectButton" class="blue">
		Connect
	</button>

	<p id="info"></p>

	<canvas id="canvas" width="300" height="150"></canvas>

</body>

</html>

Credits

vincent wong

vincent wong

81 projects • 205 followers

Comments