LoginSignup
5
2

More than 3 years have passed since last update.

MATLABでWebアクセス:TANITA Health Planet編

Posted at

はじめに

昨年の終わりに体重計をTANITAの物に買い換えて,『データがBluetoothでスマホに転送されるしTANITAのサーバでも記録してくれるし楽チンで良いねぇ』などと喜んでおりました.そして,データもたまってきて,自分でも加工してみたくなってようやく気がつきました.『データをダウンロードする機能がない!』

サポートにも問い合わせたのですが,そのような機能はないとのこと.なんとかならないかと調べてゆくと,あるじゃないですか,Webサーバの API が.というわけで,さっそくTANITAのWeb サービス「Health Planet ヘルスプラネット」から既存のデータを取得して遊んでみました.

環境・使用プログラム

Windows10 (64bit)

Google Chrome 84.0.4147.89 (64ビット)

MATLAB R2020a

準備

以下,アカウントは既に持っていて,サーバ上にデータが存在しているものとします.

「Health Planet ヘルスプラネット」にログインしたら,バナー右上のメニューから「登録情報の確認・変更 」をクリック.続いて「サービス連携」に進みます.出てきた画面の中程「アプリ連携」にある,「アプリケーション開発者の方はこちら」をクリックすると「APIの設定」という画面に遷移しますので,「新規登録」ボタンを押して必要情報を入力後「規約に同意して登録する」をクリックします.すると,Client ID,Client secretの各トークンと,リダイレクトで使われるDomain名(登録時に自分で入力します)が表示されますので,これらを記録しておきます.

image_0.png

MATLABでアクセス

パラメータの設定

MATLABでWebサービスにアクセスするための設定を行います.設定と言っても,変数やパラメータの値をセットするだけです.(ご参考までに,ヘルスプラネットのWeb API の仕様はこちらにあります.OAuth2.0に準拠しているそうですよ.)

下の設定で scope とあるのは取得する情報の種類で,体組成計の情報の場合には "innerscan" となります.(他に,血圧計だとか活動量計などがあるようです.)また,response_type"code" のみが許されている値だそうです.

Code
baseURI = "https://www.healthplanet.jp";  

client_id     = "ご自身のトークンを使ってください.";
client_secret = "ご自身のトークンを使ってください.";
redirect_uri  = "https://localhost";
scope = "innerscan";
response_type = "code";

アクセス許可

送信するURLを生成して,関数 web()を使って送信します.Webブラウザ上でユーザーにアクセス許可を求める関係で,webwriteでは上手くいかないようです.

Code
oauth_auth = sprintf( ...
  "%s/oauth/auth?client_id=%s&redirect_uri=%s&scope=%s&response_type=%s", ...
  baseURI, client_id, redirect_uri, scope, response_type);

web(oauth_auth);

送信が上手くいくと,既定のWebブラウザー上にアクセス許可画面が現れます.ユーザーが「アクセスを許可」をクリックすると「コード発行画面」に遷移し,アクセスコードが表示されます.後でアクセストークンを取得する際にこのコード(アクセスコード)を使うので,どこかにコピペしておきます.

image_1.png
image_2s.png

認証

アクセスコードをプログラムのコードにコピペするのは面倒なので,入力ダイアログを用意してそこにコピペするようにします.このようにして取得したアクセスコードを送信することで,サーバーからアクセストークンを取得します.送信には関数 webwriteを使用します.

Code
code = inputdlg("アクセスコードを入力してくださいな");
code = string(code);

tokens = webwrite(baseURI+"/oauth/token.?", ...
  "client_id",client_id, ...
  "client_secret", client_secret, ...
  "redirect_uri", redirect_uri, ...
  "code", code, ...
  "grant_type", "authorization_code");

データの要求と取得

リクエストの送信とデータの受信には,再び関数 webwrite を使います.データはJSON形式で受け取ることにするので,webwriteへの最初の引数が "https://www.healthplanet.jp/status/innerscan.json?"となります.また,パラメータ "tag" には受け取る情報の種類を示すコードを指定します.「体重」と「体脂肪率」に対応するコードはそれぞれ 6021 と 6022です.その他のパラメータについては,APIの仕様を参考にしてください.

一度に取得できるデータは3ヶ月分という制限があるため,ここでは3回に分けてデータ授受を行っています.

Code
data1 = webwrite(baseURI+"/status/innerscan.json?", ...
  "access_token",tokens.access_token, ...
  "date",1, ...
  "from","20191201000000", ...
  "to",  "20200229000000", ...
  "tag", "6021,6022");

data2 = webwrite(baseURI+"/status/innerscan.json?", ...
  "access_token",tokens.access_token, ...
  "date",1, ...
  "from", "20200301000000", ...
  "to",   "20200531000000", ...
  "tag","6021,6022");

data3 = webwrite(baseURI+"/status/innerscan.json?", ...
  "access_token",tokens.access_token, ...
  "date",1, ...
  "from", "20200601000000", ...
  "to",   "20200831000000", ...
  "tag",  "6021,6022");

以上でWebアクセスは完了.なんとも簡単ですね.遠い昔にPerlでCGIやSSI(サーバーサイドインクルード)を書いていた頃のことをほのかに思い出しました.あのころの苦労はいったい・・・

データ処理

ここから先は完全にMATLABオンリーの世界.取得した変数 data1, data2, data3 はそれぞれ構造体で,その中の data というフィールドにほしい情報が構造体配列として格納されています.

data1.data の中身
フィールド date keydata model tag
1 '202002280615' '73.90' '01000151' '6021'
2 '202002280615' '20.40' '01000151' '6022'
3 '202002270549' '73.60' '01000151' '6021'
4 '202002270549' '20.30' '01000151' '6022'
5 '202002260549' '73.75' '01000151' '6021'
6 '202002260549' '20.50' '01000151' '6022'


構造体配列のそれぞれの要素のフィールド keydata に,それぞれの tag に対応したデータが格納されているのがわかります.フィールド model は測定を行った製品名を表すコードですので,ここでは使用しません.データは全て文字配列として格納されていますね.

取得した3つのデータから data フィールドを取り出して結合して,それをテーブル変数に変換します(この過程でフィールド model は除去します).

Code
% data フィールドの抽出並びに結合
data = [data1.data; data2.data; data3.data];

% テーブル形へ変換
dataTbl = struct2table(data);
dataTbl = dataTbl(:,["date","keydata","tag"]);

dataTbl の中身
date keydata tag
1 '202002280615' '73.90' '6021'
2 '202002280615' '20.40' '6022'
3 '202002270549' '73.60' '6021'
4 '202002270549' '20.30' '6022'
5 '202002260549' '73.75' '6021'
6 '202002260549' '20.50' '6022'

このままでは,keydata が「体重」「体脂肪率」と繰り返されているので,これを別々の列にします.これを簡単にやってくれる便利な関数 unstack があります.「体重」「体脂肪率」に対応する列名を「WGT」「BFR」とします.

Code
dataTbl = unstack(dataTbl,"keydata","tag", "NewDataVariableNames",["WGT","BFR"]);

並べ替え後のdataTbl の中身
date WGT BFR
1 '202002280615' '73.90' '20.40'
2 '202002270549' '73.60' '20.30'
3 '202002260549' '73.75' '20.50'
4 '202002250546' '74.40' '20.30'
5 '202002240806' '74.05' '20.30'
6 '202002210735' '73.40' '20.00'

あとは,各変数の型を調整してからテーブルをタイムテーブルに変換,データを日付でソートし,一週間移動平均データを加えます.

Code
% 変数の型の調整
dataTbl.date = datetime(dataTbl.date,"InputFormat","yyyyMMddHHmm");
dataTbl.WGT = double(string(dataTbl.WGT));
dataTbl.BFR = double(string(dataTbl.BFR));

% テーブルからタイムテーブルへ
dataTbl = table2timetable(dataTbl);

% データを時間軸でソート
dataTbl = sortrows(dataTbl);

% 一週間移動平均データを付加
dataTbl.WGT_mav = movmean(dataTbl.WGT,7);
dataTbl.BFR_mav = movmean(dataTbl.BFR,7);

最終的な dataTbl の中身
figure_0.png
date WGT BFR WGT_mav BFR_mav
1 2019/12/03 00:00:00 73.1000 19.2000 73.4625 20.5500
2 2019/12/03 06:55:00 73.0500 21.1000 73.3000 20.5200
3 2019/12/04 23:11:00 74.0000 20.3000 73.2667 20.4833
4 2019/12/05 05:51:00 73.7000 21.6000 73.2429 20.6286
5 2019/12/06 05:57:00 72.6500 20.4000 73.3500 20.8857
6 2019/12/07 08:30:00 73.1000 20.3000 73.3929 20.7714

お絵かき

せっかくなので,お絵かきをします.ひとつめは,体重と体脂肪の変化をそれぞれ1週間移動平均とともにプロットした物です.計量は毎朝起床直後に行っているのですが,日々のばらつきが大きいのでスムージングをかけたいとずっと思っていたのです.(TANITAさんは,安定した軽量のために朝食後2時間経過時を推奨してますが,普通はそんな時刻に計量できませんってば.)

お絵かきその1 MATLAB コード
Code
clf;
subplot(2,1,1);
lh0 = plot(dataTbl.date, dataTbl.WGT,'o-','MarkerSize',4,'color',[0.7 0.9 1]*0.8);
lh0.MarkerFaceColor = lh0.Color;

lh1 = line(dataTbl.date, dataTbl.WGT_mav, 'LineWidth',2,'color',[0.2 0.7 0]);
ylabel("体重 [kg]");
title("体重");
grid on;

subplot(2,1,2);
lh2 = plot(dataTbl.date, dataTbl.BFR,'o-','MarkerSize',4,'color',[0.7 0.9 1]*0.8);
lh2.MarkerFaceColor = lh2.Color;

lh3 = line(dataTbl.date, dataTbl.BFR_mav, 'LineWidth',2,'color',[1 0.5 0]);
ylabel("体脂肪率 [%]");
title("体脂肪率");
grid on;

figure_0.png

二つ目は,体重と体脂肪率のクロスプロット.願わくば体重・体脂肪率ともに下がっていってほしいのですが,そう素直には変化してゆかないみたいです.一般に,運動を始めると初期は体脂肪の落ちよりも体重の増加が目立ち,そのうち体脂肪が落ちてくるなどと言われていますがどうでしょう.

お絵かきその2 MATLAB コード
Code
clf;

tmpDays = days(dataTbl.date-dataTbl.date(1));
sh = scatter(dataTbl.WGT_mav, dataTbl.BFR_mav,[],tmpDays,'filled');
set(gca,'Box','on');
xlabel("体重 [kg]");
ylabel("体脂肪率 [%]");

tmpDates = datetime(["2020/1/1","2020/2/1","2020/3/1","2020/4/1","2020/5/1","2020/6/1", "2020/7/1"]);
tmpDatesIdx = arrayfun(@(x) find(dataTbl.date > x, 1, 'first'), tmpDates);

bh= colorbar;
bh.Ticks = tmpDatesIdx;
bh.TickLabels = string(tmpDates);

grid on;
title("体重ー体脂肪率の関係の推移");

figure_1.png

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2