Index
Analyze Some Sensors’ Values
さて、前々からの積み残し
- When I Want(時間で)
- If She Felt Temp/Humidity(温湿度センサから)
- When She Saw(カメラから)
- If She Felt Someone(人感センサから)
ここでは4番をトリガにいろいろ
作業させてみたって話を。
Who’s Coming?
先日購入した人感センサで収集データを基に
あらゆる判定にこの情報を使っていこうという
ネタ。
先日の加湿器のネタも仮に自動化したとしても
人のいないときに動くのは電気の無駄使いなので
私が部屋にいるときだけ動いてほしい。
そんな時にもこのセンサ情報が役に立つ。
また、暗くなったら電気を自動で付けるのも
人のいないときにやっても無人の部屋が
照らされるだけで無駄。
寒くなってきたり、熱くなってきたら
無人の部屋に「寒くありませんか?」とか
「暑いですね?」などと響くのも
一種の心霊現象と言ってもいい。
で、人を検知したとしてもまた別の問題があり
例えば、私が考え事をしているときや
DVDで映画を見ているときなどは殆ど動かないので
人がいないと判断して電気を消してしまう
可能性がある。
よくホテルとかビルのトイレで用を足している
ときに、便座に座って動かないでいると勝手に
電気が消えてしまう時がある。まさにアレ。
もう一つ問題が。
例えば、湿度がこれ以下なら加湿器を付けるって
した場合、20秒間隔でチェックして
下回ってたらまた加湿器をつけて、、を繰り返す。
要は加湿器のステータスをチェックして
もう電源が入っていたら何もしないって評価を
しないとならん。でも、閾値近辺の場合は
さらに厄介で20秒間隔で付けたり消したりを
繰り返す可能性がある。なので、加湿器の場合は
電源を入れる閾値と電源を消す閾値を分ける
必要がある。
これらを完璧に解決する方法を見つけた。
Check In & Check Out
前回も上記問題の解決策を載せてみたのだが
その具体的実装をやっていくこととする。
先ずは、前回から時間も経っていることだし
今の仕組みを明るさのチェックを例にとって紹介。
私自身UMLみたいなフロー図をあまり理解して
いないので使っている図形は間違っていると
思うがご容赦いただきたい。
graph TD
title[How to manage a room lamp]
subgraph Explanatory Notes
notes1[A]==>|External Relation|notes2[B]
notes3[A]-->|Internal Relation|notes4[B]
notes5[A]-.->|DB Relation|notes6[B]
notes7[Module]
notes8((Devices))
notes9(Database)
notes10>API]
notes11{Conditions}
end
subgraph Database
db(database)
db2>API]
end
subgraph Sensors/Home Devices
mot((Motion Sensor))
lux((Brightness Sensor))
lamp1((Room Lamp))
felica((Pasori))
sensor0[Sensor Daemon]
sensor3[Felica Daemon]
sensor1>IoT API]-->|get sense|mot
sensor2>IoT API]-->|get sense|lux
sensor4>IoT API]-->|get sense|felica
sensor0-->sensor1
sensor0-->sensor2
sensor3-->sensor4
sensor0-.->db2
sensor3-.->db2
end
subgraph Main Daemon
pi1[Rpi+2s]
command1[KuroRS Daemon]==>lamp1
end
subgraph Judge Sequence
judge1>Judge API]-.->db2
judge2>Judge API]-.->db2
judge3>Judge API]-.->db2
judge4>Judge API]
db2-->|select latest motion data|db
db2-->|select latest lux data|db
db2-->|select latest felica data|db
db2-->|accumlation|db
subgraph Conditions
cond1{Is my Lord in my room?}
cond2{Did something move?}
cond3{Is it bright in my room?}
cond4{Is it night now?}
end
cond1==>|yes|pi1
cond2-->|yes|judge3
cond3-->|yes|judge4
cond4==>|yes|command1
end
cond1-->|no|judge2
cond2==>|no|pi1
cond3==>|no|pi1
cond4==>|no|pi1
pi1==>|start|judge1
judge1-->|1|cond1
judge2-->|2|cond2
judge3-->|3|cond3
judge4-->|4|cond4
classDef nodeapp fill:#acf
classDef nodeapi fill:#fa9
classDef nodecmd fill:#88e
classDef nodecond fill:#ef9
class db,pi1,sensor0,sensor3 nodeapp
class sensor1,sensor2,sensor4,judge1,judge2,judge3,db2 nodeapi
class command1 nodecmd
class cond1,cond2,cond3 nodecond
ざっくりこんな感じ。
センサーデバイスの取得した値だけでなく
今は明るいのか暗いのか
今は朝なのか夜なのか
今動いている物体がいるのかいないのか
今家主はいるのかいないのか
今家主は動いているのかいないのか
これを調べることにしている。
家主がいるかいないかは
ラズパイにPasoriを挿してFelicaライブラリから
ICカードを載せられたかを判定して
DBにステータスを書き込んでいる。
これでカードが載っていたら家主がいると
判断することにしている。
Using Felica
早速Pasoriを挿して認識させる。
家にあったPasoriは以下のもの。
| 品名 | 型番 |
|---|---|
| Sony 非接触ICカードリーダ/ライタPasori | RC-S380 |
オーソドックスなUSB接続のタイプなもの。
おもむろに指してみる。
$ lsusb
Bus 001 Device 010: ID 054c:06c3 Sony Corp.
Bus 001 Device 006: ID 0411:00b3 BUFFALO INC. (formerly MelCo., Inc.) PC-OP-RS1 RemoteStation
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
こんな感じで見えている。
一番上のやつがPasoriであろう。
ちなみに上から2番目のやつはKURO-RS。
参考にした記事はこちらの先駆者の方。
本当素晴らしい。
こちらの記事を参考にFelica.jsというモジュールを作る。
Felica.js
const NfcpyId = require('node-nfcpy-id').default;
const DB=require('./db');
const nfc = new NfcpyId({mode: 'loop'}).start();
//const nfc = new NfcpyId({mode: 'non-loop'}); // non-loop mode
//const nfc = new NfcpyId({mode: 'non-touchend'}); // non-touchend
nfc.on('touchstart', (card) => {
console.log('touchstart', 'id:', card.id, 'type:', card.type);
db=new DB();
db.open();
db.insertNowOn().then(()=>{
db.close();
});
});;
nfc.on('touchend', () => {
console.log('touchend');
db=new DB();
db.open();
db.insertNowOff().then(()=>{
db.close();
});
});
nfc.on('error', (err) => {
console.error('err: '+err);
});
本当に簡単にDB操作を加えただけ。
db.jsモジュールの内容は今後紹介は
してもいいのだが、on/off(1/0)を
テーブルに書き込んでいるだけで至ってシンプル
なのでここでは割愛。
こちらをforeverに渡してやる。
$ forever start Felica.js
Judge.jsモジュールはこちらの値と
モーションセンサの値を見て
家主が今いるかを判断する。
Main Daemon
今回は電気をつけるってことに
目的を絞っているが、他のものも
大体は前項のようなフローで動いている。
以前に書いたメインモジュールは
その後手を入れており
現在は以下のような作り。
Rpi+2s.js
const async = require('async');
const googleSpeak = require('./GoogleSpeak');
const scheduleCaller = require('./ScheduleCaller');
const Tenki = require('./Tenki');
const jdg = require('./Judge');
const kuro=require('./KURO-RS');
const google=require('./GoogleAPI');
const bulb=require('./setBulb');
var sleep=(s) => {
var e = new Date().getTime() + (s * 1000);
while (new Date().getTime() <= e);
}
var mq=async.queue((msg, callback) => {
var gs=new googleSpeak();
gs.bowwow(msg);
setTimeout(() => {
callback(null);
}, 2000);
}, 2);
class Rpi2s {
constructor() {
}
howling(){
this.ret ;
this.fc = new Tenki();
let sc = new scheduleCaller();
//check Lux
let getlux=async () => {
...(snip)...
}
getlux();
//check Temp
let gettemp=async () => {
...(snip)...
}
gettemp();
//check Humidity
let gethumi=async () => {
...(snip)...
}
gethumi();
//check Schedule
let getsch=async()=>{
...(snip)...
}
getsch();
//check YouTube or Twitter
let getlastupdated=async () => {
...(snip)...
}
getlastupdated();
}
async bowwow(msg){
let j=await new jdg();
let isDupli=false;
isDupli=await j.isDuplicated(msg);
if(!isDupli){
console.log(this.changeVariables(msg));
mq.push(this.changeVariables(msg));
}
}
changeVariables(txt){
var message=txt;
var weather=this.fc.getWeather();
var j=new jdg();
var hellos=['おはようございます','こんにちは','こんばんは'];
var hellotype=((j.isDaytime())?((j.isMorning())?0:1):((j.isNighttime())?2:0));
var sayhello=hellos[hellotype];
return message
.replace(/\$MONTH/ig, new Date().toFormat("M"))
.replace(/\$DAY/ig, new Date().toFormat("D"))
.replace(/\$HOUR/ig, new Date().toFormat("H"))
.replace(/\$MINUTE/ig, new Date().toFormat("M"))
.replace(/\$SECOND/ig, new Date().toFormat("S"))
.replace(/\$WEATHER/ig, weather.weather[0].wamei)
.replace(/\$SAYHELLO/ig, sayhello);
}
}
module.exports=Rpi2s;
howling()というメソッドが
プログラムのmainにあたるところ。
bowwow()で喋らせるのだが
今はmqueueクラスを使っているので
ここではGoogleSpeakを呼ば出さなくなった。
同じ言葉を何回も喋らないように
JudgeモジュールにisDupricatedメソッドを
用意して以前喋らせた内容と一緒なら
queueに渡さないって処理を追加している。
今のところこれでなんとなく動いてはいる。
上のフロー図を見ていただくとわかると
思うのだが、各センサーデバイスから取得した
データを評価しているだけなので、例えば
電灯が点いているか、NASの電源が入っているか
加湿器の電源が落ちているかという
家電の電源ステータスは把握できてない。
今後はここが課題。
あと、Judge.jsも後々紹介していくかな。
Next
さて次は各リモートコントロールする機器の
ステータスをちゃんと取得してから
コマンド送るようにする。
目下、用意する必要があるのは、電灯と加湿器、NAS。
これらの電源が入っているかを確認してリモートからでも
電源状況が把握できるようにしてみる。
全然本題と関係ないが
今のヘビーローテーションはASAYAKE 01。