工事中のところありますが、開発進むにつれて更新します。
1. 私は動かない
私は太っている。仕事もデスクワークだし休憩時間や趣味の時間もテレビで映画を見たり読書をしたり、最近始めたプログラミング学習も座ってパソコン操作が長い。遅く帰宅してから運動しようという気も起らない。だから痩せない。妻はそんな私を心配して、2階の部屋にこもった私を1時間に1回は見に来る。そして「座りっぱなしだとエコノミー症候群になるから。立って少し歩きなさい」と指示を出す。声だけの確認では心配だから見に来る。そんな妻には申し訳ない。妻が2階まで上がってこなくても、私が立って動いていることを知らせてあげたい。そんな妻への気遣いがこの企画の発端だ。

2. エコノミー症候群とは
飛行機のエコノミークラスは座席間隔が狭く、長時間座りっぱなしだと血液の流れが悪くなり、血栓ができ脳内血管が詰まり、脳梗塞を引き起こす病状。日常生活でも座りっぱなしがよくない。妻は座りっぱなしの私に口うるさく注意してくる。それは妻が私を深く愛しているからだ。そのはずだ。

3. 企画の概要
私が座って1時間経ったら、アラームで私に警報をならし、一定期間(例えば5分間)離席してから机にもどればよいが、5分以内に戻ってきたら、またアラームを出す。一方、私が1時間ごとに離席したか、5分は離席していたか、を妻のスマホに文字で伝えるシステムを構築する。私に対するシステムからの警報は、妻の声の録音にしたい。そうすれば妻を思い出し、真剣に離席するだろう。妻はスマホの情報を見て、私が約束を守らなかった時だけ2階にあがってくればいい。毎回2階に上がる必要はないのだ。

4. システム構成案
これにはobnizと超音波距離センサーで私が机の前に座っているか、離席しているか、を判断し、また1時間以内に立ち上がったか、立ち上がってすぐまた座っていないかを判断するプログラムを常時動かす。
また、私が席に着いた、1時間以上座りっぱなし、立ち上がった時間が短い、などの警報は、妻のLINEにメッセージとして表示する。妻は私の自己申告よりも機械がチェックする方が安心だろう。

5. 私を監視するアルゴリズム
(1)初期化処理
座るまで待つ。座ったら、妻おスマホに”座った”と送信して(2)に行く。
(2)座ったから、これから1時間以上座りっぱなしかチェックする。
1時間以内に立ち上がったら、休憩を5分以上取っているかの処理(4)へ行く。
(3)1時間以上継続して座っていたら、私に警報を出すと共に妻にメッセージが飛ぶ。
2階まで様子を見に来るかは妻の判断だが、一旦立ち上がったら(2)の頭に戻る。
(4)妻のスマホに”休憩に入った”と送信して5分以上休憩を取っているかの処理に入る。
5分以上経って戻ってきたら”十分休憩”と妻のスマホに送って、(2)の頭に戻る。
(5)休憩不十分だと、私に警報ならし、妻にもメッセージを送る。
2階まで様子を見に来るかは妻の判断だが、(2)の頭に戻る。
6. 部品確認
まず机のそばに私がすわっているかを判断するobniz 1Y、超音波距離センサー、私に警報を知らせるLEDとブザー、およびこれらを接続するブレッドボード、電線、電源をそろえ、個別に動作確認する。途中でこのブザーは単純な音だけを出し、人間の声や音楽は出せないことが分かった。残念。

7. obniz側コーディング
obniz開発コンソール用に以下のコードを準備した。アルゴリズムの1時間や5分はデバッグのため、それぞれ30秒、20秒にしてある。またループが多いので、今どこを走っているかをコンソールログに出すようにした。また最初から妻のスマホにメッセージを送るわけにもいかないので、Google Spreadshee-にメッセージを書き込むようにした。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Obniz Economy-Class Syndrome Control</title>
<script src="https://unpkg.com/obniz@3.31.0/obniz.js"></script>
</head>
<body>
<div id="obniz-debug"></div>
<h1>好きなタイトルを入力</h1>
<script>
const obniz = new Obniz('xxxx-xxxx'); // Obniz_IDに自分のIDを入れます
// obnizがオンラインであることが確認されたら、以下の関数内が自動で実行されます
obniz.onconnect = async function () { // (A)
// Initialize
var honey = "blank"; // Tsuma heno message number
// Speaker initialize
const speaker = obniz.wired("Speaker", {signal:8, gnd:9});
speaker.stop(); //
// LED initialize
const led = obniz.wired("LED", {anode:10, cathode:11});
led.off(); // LED OFF
// kyori sensor initialize
const hcsr04 = obniz.wired("HC-SR04", {gnd:0, echo:1, trigger:2, vcc:3});
while (true) { // (B)
// Desk ni inai koto wo tsuma ni rennraku
led.off(); // LED OFF
speaker.stop(); // Buzzor OFF
console.log("riseki");
honey = "riseki" ; // Tsuma ni Riseki wo renraku
// ------------------------------------------
const res = await fetch('https://api.steinhq.com/v1/storages/688ef8fec088333365c685df/シート1', { // <API URL> をご自身のAPI URLに変更。/シート1は残してください。
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"condition": { "device": "Honey" },
"set": { "value": honey }
})
}); // fetchでSteinでAPIとしたスプレッドシートに対してデータを送信
const resJson = await res.json(); // fetchしたデータをJSON形式にパース
console.log(resJson);
// -----------------------------------------
console.log("Position 1"); // PORITION 1
// Suwatte iruka check
var val = await hcsr04.measureWait();
if (val >= 200) { // I am away, so wait until comeback C
console.log("Posirion 2") ;
await obniz.wait(100);
} // (C)
else { // I am at Desk, start 60 min. moniter (D)
// Suwatta koto wo tsuma ni rennraku
let i;
for ( i = 0; i < 30 ; i++ ) { // 60min sit down ? (K) hontou ha 3600 30sec ni shiuta
console.log("Position 3") ;
val = await hcsr04.measureWait();
if ( val < 200 ) { // (E)
; // suwatta mama
} // (E)
else { // 60 min. inai ni tachiagatta (F)
break ; // tachiagatta node 60min loop kara nukeru
} // (F)
} // (K) for loop
if ( i == 30 ) { // suwari panashi (G) hontouha3600 30sec
console.log("Position 4");
// Tsuma wo yobu shori
speaker.play(1000); //1000hz Buzar ON
led.blink(); //LED blink
console.log("Come ! Keeping Sitting")
honey = "Come ! Keeping Sitting!"; // Tsuma ni rennraku
// ----------------------------------------------------------
const res = await fetch('https://api.steinhq.com/v1/storages/688ef8fec088333365c685df/シート1', { // <API URL> をご自身のAPI URLに変更。/シート1は残してください。
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"condition": { "device": "Honey" },
"set": { "value": honey }
})
}); // fetchでSteinでAPIとしたスプレッドシートに対してデータを送信
const resJson = await res.json(); // fetchしたデータをJSON形式にパース
console.log(resJson);
// ---------------------------------------------------------
while (true) { // (I)
console.log("Position 5");; // Tachuagaru made matsu
val = await hcsr04.measureWait(); // Suwatte iruka check
if ( val >= 200) { // (J)
break ; // tachiagatta
} // (J)
await obniz.wait(100);
} // (I)
} // (G)
else { // 60 min. inai ni tachiagatta (H)
// 5 min. ijou riseki surukoto
console.log("Position 6") ;
let j;
for ( j = 0; j < 20 ; j++ ) { // 5min ijou riseki ? (L) hontouha 300, 20sec ni shita
val = await hcsr04.measureWait();
if ( val < 200 ) { // (E)
break; // 5 min. inai ni suwatta
} // (E)
else { // (F)
; // tachiagatta mama
} // (F)
} // (L) for loop
if ( j == 20 ) { // (M) hontouwa 300
console.log("Position 7");
break ; // kyuukei OK
} // (M)
else { // (N) kyuukei ga fusoku
console.log("Position 8");
speaker.play(1000); //1000hz Buzzer ON
led.blink(); // LED blink;
console.log("Come On! Kyuukei Fusoku");
honey = "Come On! Kyuukei Fusoku!"; // Tsuma ni kyuukei fusoku wo renraku
// ---------------------------------------------------
const res = await fetch('https://api.steinhq.com/v1/storages/688ef8fec088333365c685df/シート1', { // <API URL> をご自身のAPI URLに変更。/シート1は残してください。
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"condition": { "device": "Honey" },
"set": { "value": honey }
})
}); // fetchでSteinでAPIとしたスプレッドシートに対してデータを送信
const resJson = await res.json(); // fetchしたデータをJSON形式にパース
console.log(resJson);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; // // swatteru jotai nanode ittann tachiagaru nowo matsu
while ( true) { // (O)
val = await hcsr04.measureWait();
if ( val < 200 ) { // (P)
; // suwatta mama
} // (P)
else { // (Q)
console.log("Atama ni modoru");
speaker.stop();
led.off();
break; // tachiagatta mama
} // (Q)
} // (O) while loop
console.log("Position 9");
} // (H)
console.log("Position 10");
break;
} // (D)
console.log("Position 11");
break;
}
} // whike (true) NO kakko (B)
}// async function NO kakko (A)
</script>
</body>
</html>
8. デバッグ状況
なんとか、ハードウエアは動き出し、スプレッドシートにも書き込みができるようになった。コンソールにデバグ用メッセージも出せる。これでデバグが進みそう。
9. 妻に知らせる方法
せっかくGoogle Spreadsheetを使ったのであるから、GAS(Google App Script)のイベントでプログラムを起動し、そのタイミングでのスマホのLINEにメッセージを送るようにする。つまりobnizのプログラムがスプレッドシートに書き込みを行ったことをトリガーとしてGASのプログラムが動き出し、LINEのMESSAGING APIを使って予め妻のスマホのKINEに登録したチャネルにメッセージを送り表示させるというものである。

10. GAS側コーディング:工事中
工事中。
11. 妻の反応:工事中
工事中。
12. 修正内容:工事中
工事中。
13. 改善結果:工事中
工事中。# 反省とまとめ工事中。
