Android Wear アプリ開発 センサ活用チュートリアル4 WordPress&PHP編
PHPプログラム
本ページは、Android Wear 開発チュートリアルのPHPプログラム編です。Wearアプリの開発やWear↔Mobile間通信については、こちらの Index からご参考ください。
Index
Functionalities
Files
Explanations
機能
| post.php (サーバ) |
| |
|---|---|---|
| charts.php (サーバ) |
|
Files
post.php
<?php
require_once('bioinfo_classes.php');
if(
( isset($_SERVER["SHELL"]) || isset($_SERVER["HOMEPATH"]) )
&& stristr($argv[0],'post.php') ){
$_REQUEST["d0"]="0,0,".date("Y-m-d H:i:s").",0,0";
}
if( isset($_REQUEST["d0"]) ){
$i = 0;
$bioinfo_list = new BioInfo_List();
while(true){
$k = "d".$i;
if( isset($_REQUEST[$k]) ){
$bioinfo_list->add_bioinfo_from_csv($_REQUEST[$k]);
}else{
break;
}
$i++;
}
if( count($bioinfo_list->bioinfo_list) > 0 ){
$bioinfo_list->insert_db();
}
//var_dump($bioinfo_list);
}
?>
charts.php
<?php
require_once('bioinfo_classes.php');
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Graphs</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
</head>
<body>
<h1>Graphs</h1>
<?php
$bioinfo_list = new Bioinfo_List();
$bioinfo_list->chart_flg="xyz";
$bioinfo_list->load_sensor_values_from_db("acc",20);
$bioinfo_list->set_chart_config("acc","acc",30,-30,10);
$bioinfo_list->output_chart_js("acc");
$bioinfo_list = new Bioinfo_List();
$bioinfo_list->chart_flg="0";
$bioinfo_list->load_sensor_values_from_db("hr",20);
$bioinfo_list->set_chart_config("hr","hr",140,0,10);
$bioinfo_list->chart_max=140;
$bioinfo_list->chart_min=0;
$bioinfo_list->output_chart_js("hr");
$bioinfo_list = new Bioinfo_List();
$bioinfo_list->chart_flg="0";
$bioinfo_list->load_sensor_values_from_db("lux",20);
$bioinfo_list->set_chart_config("lux","lux",0,0,0);
$bioinfo_list->output_chart_js("lux");
$bioinfo_list = new Bioinfo_List();
$bioinfo_list->chart_flg="incremental";
$bioinfo_list->load_sensor_values_from_db("sc",20);
$bioinfo_list->set_chart_config("sc","sc",100,0,0);
$bioinfo_list->output_chart_js("sc");
?>
</body>
</html>
bioinfo_classes.php
<?php
$DB_HOST="localhost";
$DB_USER="xxxxx";
$DB_PW="xxxxx";
$DB_NAME="wpbioinfo";
Class Bioinfo_List {
public $bioinfo_list=array();
public $chart_flg=0;
public $chart_max=0;
public $chart_min=0;
public $chart_config = array(
"__PREFIX__"=>"",
"__CHART_TITLE__"=>"",
"__CHART_MAX__"=>40,
"__CHART_MIN__"=>0,
"__STEP_SIZE__"=>10);
public function add_bioinfo_from_csv($csv){
$rec = new BioInfo();
$rec->set_values_from_csv($csv);
$this->bioinfo_list[] = $rec;
}
public function insert_db(){
//echo "insert db<BR>\n";
try {
$pdo_opts = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
$pdo = new PDO ( 'mysql:host='.$GLOBALS["DB_HOST"].';dbname='.$GLOBALS["DB_NAME"].';charset=utf8', $GLOBALS["DB_USER"], $GLOBALS["DB_PW"], $pdo_opts );
$stmt = $pdo->prepare( 'INSERT INTO `'."sensor_data".'`
(`user_id`,`device_id`,`timestamp`,`sensor_id`,`value`)
VALUES (:user_id,:device_id,:timestamp,:sensor_id,:value)
ON DUPLICATE KEY UPDATE
`value`=VALUES(`value`)
;');
foreach( $this->bioinfo_list as $i => $rec ){
//var_dump($rec);
$d = explode(' ', $rec->timestamp);
if( count($d) == 3 ){
array_pop($d);
$rec->timestamp=join(' ',$d);
}
$stmt->bindValue(':user_id', $rec->user_id, PDO::PARAM_STR);
$stmt->bindValue(':device_id', $rec->device_id, PDO::PARAM_STR);
$stmt->bindValue(':timestamp', $rec->timestamp, PDO::PARAM_STR);
$stmt->bindValue(':sensor_id', $rec->sensor_id, PDO::PARAM_STR);
$stmt->bindValue(':value', $rec->value, PDO::PARAM_STR);
$stmt->execute();
}
}catch(PDOException $PDO_ERROR){
header('Content-Type: text/plain; charset=UTF-8', true, 500);
exit('DataBase ERROR/'.$PDO_ERROR->getMessage()."\n");
}
return(count($this->bioinfo_list));
}
public function load_sensor_values_from_db($str, $num){
if( $this->chart_flg == "xyz" ){
$num = $num*3;
}
try {
$pdo_opts = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
$pdo = new PDO ( 'mysql:host='.$GLOBALS["DB_HOST"].';dbname='.$GLOBALS["DB_NAME"].';charset=utf8', $GLOBALS["DB_USER"], $GLOBALS["DB_PW"], $pdo_opts );
$stmt = $pdo->prepare( 'SELECT * FROM `'."sensor_data".'`
WHERE `user_id`=0 AND `device_id`=0 AND `sensor_id` LIKE "%'.$str.'%"
ORDER BY `timestamp` DESC LIMIT '.$num.'
;');
$stmt->execute();
while($result = $stmt->fetch(PDO::FETCH_ASSOC)){
$rec = new BioInfo();
$rec->set_values_from_assoc($result);
$this->bioinfo_list[] = $rec;
}
}catch(PDOException $PDO_ERROR){
header('Content-Type: text/plain; charset=UTF-8', true, 500);
exit('DataBase ERROR/'.$PDO_ERROR->getMessage()."\n");
}
return(count($this->bioinfo_list));
}
public function set_chart_config($prefix,$title,$max,$min,$step){
$this->chart_config = array(
"__PREFIX__"=>$prefix,
"__CHART_TITLE__"=>$title,
"__CHART_MAX__"=>$max,
"__CHART_MIN__"=>$min,
"__STEP_SIZE__"=>$step);
}
public function output_chart_js($prefix){
$chart_js_str='
<style type="text/css">
<!--
div.chart_canvas { width: 48%; }
-->
</style>
<DIV class="chart_canvas">
<canvas id="__PREFIX__Chart"></canvas>
</DIV>
<script>
var ctx = document.getElementById("__PREFIX__Chart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: [__X_AXIS_LABELS__],
datasets: [
{
label: "__VALUE_LABEL_1__",
data: [__DATA_ARRAY_1__],
borderColor: "rgba(255,0,0,1)",
backgroundColor: "rgba(0,0,0,0)"
}';
if( $this->chart_flg=="xyz" ){
$chart_js_str=$chart_js_str.',
{
label: "__VALUE_LABEL_2__",
data: [__DATA_ARRAY_2__],
borderColor: "rgba(0,255,0,1)",
backgroundColor: "rgba(0,0,0,0)"
},
{
label: "__VALUE_LABEL_3__",
data: [__DATA_ARRAY_3__],
borderColor: "rgba(0,0,255,1)",
backgroundColor: "rgba(0,0,0,0)"
}';
}
$chart_js_str=$chart_js_str.'
],
},
options: {
title: {
display: true,
text: "__CHART_TITLE__"
},
scales: {
yAxes: [{
ticks: {
suggestedMax: __CHART_MAX__,
suggestedMin: __CHART_MIN__,
stepSize: __STEP_SIZE__,
callback: function(value, index, values){
return value;
//return value + "度"
}
}
}]
},
}
});
</script>
';
$timestamp_list=array();
$value_list_1=array();
$value_list_2=array();
$value_list_3=array();
foreach ( $this->bioinfo_list as $i => $rec ){
$t = preg_replace('{.* ([0-9]*:[0-9]*):[0-9]*.*}',"$1",$rec->timestamp);
if( !in_array($t,$timestamp_list) ){
$timestamp_list[] = $t;
}
if( $this->chart_flg == "xyz" ){
if( $rec->sensor_id==$prefix." x" ){
$value_list_1[] = $rec->value;
}else if( $rec->sensor_id==$prefix." y" ){
$value_list_2[] = $rec->value;
}else if( $rec->sensor_id==$prefix." z" ){
$value_list_3[] = $rec->value;
}
}else if( $this->chart_flg == "incremental" ){
if( count($value_list_1) == 0 ){
$value_list_1[] = 0;
}else{
$value_list_1[] = $this->bioinfo_list[$i-1]->value - $rec->value;
}
}else{
$value_list_1[] = $rec->value;
}
}
$timestamp_list = array_reverse($timestamp_list);
$value_list_1 = array_reverse($value_list_1);
$value_list_2 = array_reverse($value_list_2);
$value_list_3 = array_reverse($value_list_3);
foreach ( $this->chart_config as $k => $v ){
$chart_js_str=str_replace($k,$v,$chart_js_str);
}
$chart_js_str=str_replace("__X_AXIS_LABELS__",'"'.join('","',$timestamp_list).'"',$chart_js_str);
$chart_js_str=str_replace("__VALUE_LABEL_1__","x",$chart_js_str);
$chart_js_str=str_replace("__DATA_ARRAY_1__",join(",",$value_list_1),$chart_js_str);
$chart_js_str=str_replace("__VALUE_LABEL_2__","y",$chart_js_str);
$chart_js_str=str_replace("__DATA_ARRAY_2__",join(",",$value_list_2),$chart_js_str);
$chart_js_str=str_replace("__VALUE_LABEL_3__","z",$chart_js_str);
$chart_js_str=str_replace("__DATA_ARRAY_3__",join(",",$value_list_3),$chart_js_str);
echo $chart_js_str;
}
}
Class BioInfo {
public $user_id;
public $device_id;
public $timestamp;
public $sensor_id;
public $value;
public function set_values_from_csv($csv){
$d = explode(",",$csv);
$this->user_id = $d[0];
$this->device_id = $d[1];
$this->timestamp = $d[2];
$this->sensor_id = $d[3];
$this->value = $d[4];
}
public function set_values_from_assoc($assoc){
foreach ( $assoc as $k => $v ){
$this->$k = $v;
}
}
}
?>
Database
使っているテーブルの仕様は以下の通り、複数ユーザ対応を想定したuser_id、例えばスマートウォッチに加えてスマートフォンのセンサデータを取得するなど、複数デバイスの利用を想定した device_id は現在のところ、使われていない。
| # | 名前 | データ型 | 照合順序 | NULL | デフォルト値 | コメント | その他 | |||
| 1 | varchar(255) | utf8_general_ci | いいえ | なし | ||||||
| 2 | varchar(255) | utf8_general_ci | いいえ | なし | ||||||
| 3 | timestamp | いいえ | CURRENT_TIMESTAMP | ON UPDATE CURRENT_TIMESTAMP | ||||||
| 4 | varchar(255) | utf8_general_ci | いいえ | なし | ||||||
| 5 | float | いいえ | なし | |||||||
コード解説
AndroidからHTTP POSTをする方法は前のページ「Mobileプログラム編」をご参考ください。
Chart.js: グラフを表示する
<DIV class="chart_canvas">
<canvas id="__PREFIX__Chart"></canvas>
</DIV>
<script>
var ctx = document.getElementById("__PREFIX__Chart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: [__X_AXIS_LABELS__],
datasets: [
{
label: "__VALUE_LABEL_1__",
data: [__DATA_ARRAY_1__],
borderColor: "rgba(255,0,0,1)",
backgroundColor: "rgba(0,0,0,0)"
},
{
label: "__VALUE_LABEL_2__",
data: [__DATA_ARRAY_2__],
borderColor: "rgba(0,255,0,1)",
backgroundColor: "rgba(0,0,0,0)"
},
{
label: "__VALUE_LABEL_3__",
data: [__DATA_ARRAY_3__],
borderColor: "rgba(0,0,255,1)",
backgroundColor: "rgba(0,0,0,0)"
}
],
},
options: {
title: {
display: true,
text: "__CHART_TITLE__"
},
scales: {
yAxes: [{
ticks: {
suggestedMax: __CHART_MAX__,
suggestedMin: __CHART_MIN__,
stepSize: __STEP_SIZE__,
callback: function(value, index, values){
return value;
//return value + "度"
}
}
}]
},
}
});
</script>
上記にChart.jsを使う場合のコードを掲載しました。
- 7行目: type: “line”
グラフの種類の指定です。ここでは線グラフにしています。
- 8行目: data: {}
ここからX軸の設定です。
- 9行目: labels: [__X_AXIS_LABELS__]
X軸のラベルの設定です。ここには時刻が入ります。
- 10行目: datasets: []
データの設定です。ここではデータが3セットで、線が3本の設定になっていますが、線が1本のグラフの場合、PHP側で調整しています。
label: ・・・ データの名前。心拍数、歩数等。
data: ・・・ 数値の配列をコンマ区切りで繋げた文字列
borderColor: ・・・ 線の色
backgroundColor: ・・・ 背景色
- 34行目: text: “__CHART_TITLE__”
グラフタイトルの設定です。
- 37行目:
Y軸の設定です。
suggestedMax: ・・・ Y軸の最大値の設定です。0の場合、データの数値が超過した場合は自動で設定されるようです。
suggestedMin: ・・・ Y軸の最小値の設定です。0の場合、データの数値が下回った場合は自動で設定されるようです。
stepSize: ・・・ 横補助線の感覚です。
callback: 個々のデータ点上に単位を入れる場合に使います。
Class Bioinfo_List {
public $bioinfo_list=array();
public $chart_flg=0;
public $chart_max=0;
public $chart_min=0;
public $chart_config = array(
"__PREFIX__"=>"",
"__CHART_TITLE__"=>"",
"__CHART_MAX__"=>40,
"__CHART_MIN__"=>0,
"__STEP_SIZE__"=>10);
public function set_chart_config($prefix,$title,$max,$min,$step){
$this->chart_config = array(
"__PREFIX__"=>$prefix,
"__CHART_TITLE__"=>$title,
"__CHART_MAX__"=>$max,
"__CHART_MIN__"=>$min,
"__STEP_SIZE__"=>$step);
}
public function output_chart_js($prefix){
$chart_js_str='ここにJavascriptのコードを入れる';
if( $this->chart_flg=="xyz" ){
$chart_js_str=$chart_js_str.'ここにJavascriptのコードを入れる';
}
$chart_js_str=$chart_js_str.'ここにJavascriptのコードを入れる';
$timestamp_list=array();
$value_list_1=array();
$value_list_2=array();
$value_list_3=array();
foreach ( $this->bioinfo_list as $i => $rec ){
$t = preg_replace('{.* ([0-9]*:[0-9]*):[0-9]*.*}',"$1",$rec->timestamp);
if( !in_array($t,$timestamp_list) ){
$timestamp_list[] = $t;
}
if( $this->chart_flg == "xyz" ){
if( $rec->sensor_id==$prefix." x" ){
$value_list_1[] = $rec->value;
}else if( $rec->sensor_id==$prefix." y" ){
$value_list_2[] = $rec->value;
}else if( $rec->sensor_id==$prefix." z" ){
$value_list_3[] = $rec->value;
}
}else if( $this->chart_flg == "incremental" ){
if( count($value_list_1) == 0 ){
$value_list_1[] = 0;
}else{
$value_list_1[] = $this->bioinfo_list[$i-1]->value - $rec->value;
}
}else{
$value_list_1[] = $rec->value;
}
}
$timestamp_list = array_reverse($timestamp_list);
$value_list_1 = array_reverse($value_list_1);
$value_list_2 = array_reverse($value_list_2);
$value_list_3 = array_reverse($value_list_3);
foreach ( $this->chart_config as $k => $v ){
$chart_js_str=str_replace($k,$v,$chart_js_str);
}
$chart_js_str=str_replace("__X_AXIS_LABELS__",'"'.join('","',$timestamp_list).'"',$chart_js_str);
$chart_js_str=str_replace("__VALUE_LABEL_1__","x",$chart_js_str);
$chart_js_str=str_replace("__DATA_ARRAY_1__",join(",",$value_list_1),$chart_js_str);
$chart_js_str=str_replace("__VALUE_LABEL_2__","y",$chart_js_str);
$chart_js_str=str_replace("__DATA_ARRAY_2__",join(",",$value_list_2),$chart_js_str);
$chart_js_str=str_replace("__VALUE_LABEL_3__","z",$chart_js_str);
$chart_js_str=str_replace("__DATA_ARRAY_3__",join(",",$value_list_3),$chart_js_str);
echo $chart_js_str;
}
}
?>
Chart.jsの仕様に合わせて文字列を生成し、javascriptを記載した文字列に対して置換を行います。置換されたものを出力します。




