Languages

Menu
Sites
Language
Heart rate to file Tizen

I have got three questions to ask regarding tizen sdk and Samsung gear 2. I am trying to write a file with the heart rate sensored from gear 2. My app heart rate sensoring beggining with the following command 

window.webapis.motion.start("HRM", onchangedCB);

Firstly I want to find a way to correspondigly close the app when I press the main button of gear 2. I found default code to do so:

 

document.addEventListener('tizenhwkey', function(e) {
        if(e.keyName == "back")          
            tizen.application.getCurrentApplication().exit();
        	window.webapis.motion.stop("HRM");
});

However this code is not seem to working. Moreover heart rate sensor device is not stopping after the start of the app. How can I close the hr device? Thirdly I wrote hr in a file. However it seems that javascript write function does not recognize new line character "\n". How can I add new line character in write function?

Responses

22 Replies
Marco Buettner

1.) As far I know the Wearable does only support "back" as hardware button, so home button will not supported

2.) You should stop the sensor before your close the application. It will be better to write a own exit function.

function closeApp() {
    window.webapis.motion.stop("HRM"); // < 2.3
    //tizen.humanactivitymonitor.stop("HRM"); //tizen 2.3

    setTimeout(function() {tizen.application.getCurrentApplication().exit();}, 800);
}

3.) have you try "\n\n" on the end? Maybe you can switch it to the front of the new line

Jose Ramon

Both "\n\n" and "\n\n\n" don't working. As far far as closeApp functino is concerned what exactly is the 800 value?

Marco Buettner

800 stands for 800ms. It defines the delay before the inner function will be call ... 800ms after the execution of the timeout the inner function will be call.

I never execute a formated text to a file, I have to watch it by myself at home... :)

AVSukhov

Hello,

Try to use "\r\n"

Vikram

Hello,

Below code is working fine in Gear 2 and HRM is closed when I exit test application.

 document.addEventListener('tizenhwkey', function(e) {
        if(e.keyName == "back") {
            tizen.application.getCurrentApplication().exit();
            window.webapis.motion.stop("HRM");  
        }
    });
 

Jose Ramon

These are for swine up and and swipe down evets?

Vikram

When you swipe up your screen, application will be closed. this is the way how to exit your application in Gear.

Hence HRM module will be stopped and the light of backside on Gear will be turned off.

Vikram

sorry for my mistypo.

In Gear, Swipe down is like a back button of mobile. so you can exit your application.

According this, you can stop HRM module by swiping down on your application.

and Home button of Gear has the same function of mobile.

Vikram

Hello,

In my understanding, File API of Gear 2 can  read files only from local system.

How about you use IndexedDB to to store your hr data? Here is a tutorial of IndexedDB for tizen.

    https://developer.tizen.org/documentation/articles/indexeddb

 

Marco Buettner

but FileSystem API can write files to local system ;)

Jose Ramon

Yes writing to filesystem is quite straightforward with some problems, that I am trying to solve. 

Marco Buettner

Its just a simple idea ... maybe you can adapt it to your filesystem write process?

http://jsfiddle.net/7pmh5qcj/

Marco Buettner

Some explaination to the code above.

Maybe its enough to write the sensor data before the application will be close, so you can put the data while the app is running to an array.

On the "close" function you iterate the array like the code on my link.

Use a string as output and write item of the array as an new line and concate it with the output string.

After that you will start the write process via filesystem api.

I haven't test it currently with the filesystem api but its just a idea.

Byunghoon Ahn

fㅇㄴㅁㄻㄴㄹㅇㅁ

Vikram
Hello, I've tested it as following and could see the result. function onchangedCB(hrmInfo) { console.log("Heart rate: " + hrmInfo.heartRate); console.log("R-R interval: " + hrmInfo.rRInterval); if(hrmInfo.heartRate > 0) { updateChart(hrmInfo.heartRate); var file; tizen.filesystem.resolve( 'documents', function(dir){ file = dir.resolve("hrm.txt"); file.openStream( "a", function(fs){ fs.write(hrmInfo.heartRate); fs.write("\r\n"); fs.write(hrmInfo.rRInterval); fs.write("\r\n"); fs.close(); }, function(e){ console.log("Error " + e.message); }, "UTF-8" ); }, function(e){ console.log("Error" + e.message);}, "rw"); } else { $('#textbox').html("No heart rate detected."); } } }
Jose Ramon

Finally my code is working and it is the following:

 

window.onload = function () {
    var initial = new Date().getTime();
	var dataLength = 500;
	var dps = []; // dataPoints
	var historyDataLength = 5;
	var history = [];
	var temp = "nada";
	
	var initial = new Date().getTime();
	var dataLength = 500;
	var dpsX = [];
	var dpsY = [];
	var dpsZ = [];
	var accX = 0;
	var accY = 0;
	var accZ = 0;
	var timeAll = 0;
	
	function onsuccess(files) {
		   var testFile = null;
		   try{
		      testFile = documentsDir.createFile("test.txt");
		   if (testFile !== null) {
		     testFile.openStream(
		         "a",
		         function(fs){
		          
		           fs.write(temp + "," + accX + "," + accY + "," + accZ + "\n");
		           fs.close();
		         }, function(e){
		           console.log("Error " + e.message);
		         }, "UTF-8"
		     );
		   }
		   }
		   catch (e) { // file already exist -> append content
		       testFile = documentsDir.resolve('test.txt');
		        if(testFile !== null)
		        {
		            testFile.openStream(
		                 "a",
		                 function(fs){
		                 
		                   fs.write(temp + "," + accX + "," + accY + "," + accZ + "\n");
		                   fs.close();
		                 }, function(e){
		                   console.log("Error " + e.message);
		                 }, "UTF-8"
		             );
		        }
		    }
		 }
		 function onerror(error) {
		   console.log("The error " + error.message + " occurred when listing the files in the selected folder");
		 }
	
	
	
	
	var chart = new CanvasJS.Chart("chartContainer",{
		title :{
			fontColor: "#ccc",
			text: "Heart Rate"
		},
		backgroundColor: "#222",
		data: [{
			color: "#CD5C5C",
			type: "line",
			dataPoints: dps 
		}]
	});
	var lastSecond = -1;
	var updateChart = function (heartrate) {
		time = new Date().getTime() - initial;
		timeAll = time;
		console.log("[" + time + "," + heartrate + "]");
		temp = heartrate;
		console.log("tempVar"+ temp);
		
		temp = heartrate;   
		tizen.filesystem.resolve(
			    'documents',
			     function(dir){
			     documentsDir = dir; 
			     dir.listFiles(onsuccess,onerror);
			     }, function(e) {
		         console.log("Error" + e.message);
			     }, "a"
		);
		
		console.log(temp);
		
		dps.push({
			x: time / 1000.0,
			y: heartrate
		});
		if (dps.length > dataLength)
		{
			dps.shift();				
		}
		var second = Math.round(time / 1000.0);
		if(lastSecond != second) {
			// TODO use avg heart rate instead of smapshot.
			history.push({
				x: second,
				y: heartrate
			});
			if(history.length > historyDataLength) {
				history.shift();
			}
			lastSecond = second;
		}

		if(dps.length >= dataLength) {
			chart.render();
		}
		var hrchart = "<center>" + heartrate + "bps</center><table width='100%' cellpadding=4px>";
		for(var i = history.length - historyDataLength; i >= 0 && i < history.length; i++) {
			hrchart += "<tr><td align='right' width='50%'>" + history[i].x + "s</td><td width='50%'>" + history[i].y + "bps</td></tr>";
		}
		hrchart += "</table>";
		$('#textbox').html(hrchart);
	};

	updateChart(0);
	updateChart(250);
	for(var i = 0; i < dataLength; i++) {
		updateChart(0);
	}

//	document.addEventListener('tizenhwkey', function(e) {
//        if(e.keyName == "back")      	
//            tizen.application.getCurrentApplication().exit();
//        	webapis.motion.stop("HRM");
//    });

	window.webapis.motion.start("HRM", onchangedCB);
	
	var lastSecond = -1;
	var updateChart2 = function (x, y, z) {
		time = new Date().getTime() - initial;
		accX = x;
		accY = y;
		accZ = z;
		console.log("[" + time + ", " + x + "," + y + "," + z + "]");
		dpsX.push({
			x: time / 1000.0,
			y: x
		});
		dpsY.push({
			x: time / 1000.0,
			y: y
		});
		dpsZ.push({
			x: time / 1000.0,
			y: z
		});
		if (dpsX.length > dataLength)
		{
			dpsX.shift();
			dpsY.shift();
			dpsZ.shift();
		}
		//var second = Math.round(time / 1000.0);
		
		
//		if(dpsX.length >= dataLength) {
//			chart.render();
//		}
		//var sensors = "<center>x: " + x + "<br>y: " + y + "<br>z: " + z + "</center>";
		//$('#textbox').html(sensors);
	};

	updateChart2(0, 0, 0);
	for(var i = 0; i < dataLength; i++) {
		updateChart2(0, 0, 0);
	}


	window.addEventListener('devicemotion', function(e) {
		updateChart2(
				 e.accelerationIncludingGravity.x,
				-e.accelerationIncludingGravity.y,
				-e.accelerationIncludingGravity.z);
	});

	function onchangedCB(hrmInfo) 
	{
	   if(hrmInfo.heartRate > 0) {
		   
		       
				// add eventListener for tizenhwkey
		   document.addEventListener('tizenhwkey', function(e)  {

	            if(e.keyName == "back") {
	                // you need to write exit statement
	                tizen.application.getCurrentApplication().exit();
	                webapis.motion.stop("HRM");
	            }
	    });
		   
		   updateChart(hrmInfo.heartRate);
		   
		 
		   
	   } else {
		   $('#textbox').html("No heart rate detected.");
		   
	   }
	}
}

However I am noticing two strange effects. Firstly it seems that sometimes when running the app standalone without any Galaxy device or cable, the app stores my heart rate and accelerometer data. Hovever it seems that sometimes the app is closing without the sensor stops and in the file it stores zero heart rate. Therefore my heart rate signal at the end is a non -continuous signal. Any idea why the app stops (regarding the posted code)? Secondly if I want to store a timestamp for every hrm and accelerometer time is the correct variable?

Marco Buettner

Great to hear that it works for now.

To be ensure that the sensor stop correct, I have write a solution above... before your call the exit() method, stop the sensor and wait for a while (maybe 800ms) or less...

For your second issue. Yeah new Date().getTime() is the correct way to get the timestamp. Notice the different between UNIX timestamp and JavaScript timestamp. The JS timestamp has the unit 'ms', UNIX timestamp 's'

Jose Ramon

The weird is that sometimes it stops by itself without reason. And despite that the app is stopped or it seems that it stops (from the app goes to the main gear 2 menu unexpectedly) when I open again the app it begins to write from the start and the timestamp is initialised again.

Marco Buettner

Do you wanna save the initialize date? Until its onload, it will always on the begin updated.

Jose Ramon

As far as timestamp is conerned it seems that my app doen't save the timestamp real time what is stored in my file is the following:

7520,0,-2.3712873458862305,-6.695117950439453,-6.673582077026367
7520,0,-2.3712873458862305,-6.695117950439453,-6.673582077026367
7520,0,-2.3712873458862305,-6.695117950439453,-6.673582077026367
7520,0,-2.3712873458862305,-6.695117950439453,-6.673582077026367
7520,0,-2.3712873458862305,-6.695117950439453,-6.673582077026367
18770,68,-0.413958340883255,-3.759124279022217,-9.559326171875
18770,68,-0.413958340883255,-3.759124279022217,-9.559326171875
18770,68,-0.413958340883255,-3.759124279022217,-9.559326171875

THe first column of the file is the timestamp from time = new Date().getTime() - initial;

Marco Buettner

new Date().getTime() is already the timestamp. You expression time = new Date().getTime() - initial calculate the different between "now" and the first initialize

christos Athanasiadis

Yea you are right.  Thanks anyway. The only issue that remains even with @Marco implementation:

 

function closeApp() {
    window.webapis.motion.stop("HRM"); // < 2.3
    //tizen.humanactivitymonitor.stop("HRM"); //tizen 2.3

    setTimeout(function() {tizen.application.getCurrentApplication().exit();}, 800);
}

is the unexpected closings of the application.