ラベル RaspberryPi2 の投稿を表示しています。 すべての投稿を表示
ラベル RaspberryPi2 の投稿を表示しています。 すべての投稿を表示

2016年8月16日火曜日

PHILIPS Hueを67個制御してみた


暫く更新をサボってしまいました。

今回機会に恵まれて、会社のFabLabを開設するプロジェクトに参加して照明システムを作ってみました。フロア全体の設計はNOIZ ARCHITECTSさんにお願いしています。

約400平米のフロア全体にPHILIPS Hueを67個(うち2個はHue light ribbon 6m)入れて、Hue Bridge2台をRaspberryPiにいれたnode.jsでWebアプリを立てて制御するシステムを組んでいます。


GUIはこんな感じで、右半分で制御対象のランプを矩形、もしくは領域選択ボタンで指定して左側のColorPickerで色と明るさを指定するというものです。
ColorPickerの下のボタンは色を登録しておくボタン、SCENE SELECTボタンは全体の状態を登録しておくボタンです。




こちらは管理者向け画面で、SCAN LIGHTSでlinkされてないHue lampを探して左側にオレンジの丸で表示し、それをDragすると実物のランプが赤くフラッシュし続けるので右画面のマップ上の位置にDropするとその位置に登録します。67個を如何に手を抜いて設置&設定をするかを考えた末のUIです。
マップ上のランプの色の違いはつながっているBridgeの違いを表しています。



Hueのスターターキット(第2世代 Bridgeが四角のHomeKit対応のもの)を2セット借用して自宅で色々APIを叩いてなんとかなるだろうと高をくくっていたのですが、67個を制御しようとするとそう簡単ではなく色々とうまくいかないところが出てきてスケジュールぎりぎりにようやく動かすことが出来ました。
Googleで検索しても数個を制御している例しか見つからないので、引っかかったポイントを記しておきます。

1.一度Hueのランプを1つのHue Bridgeとペアリングさせると、Delete ligthsで登録を削除しても他のHue Bridgeとペアリング出来ないことがある。(出来ることもあったので条件が何かあるのかもしれません。)

やってみたこと
 ・Hue Bridgeを2台使用して1台目のBridgeとペアリングして制御できる状態のランプをDelete lightsして、2台目のBridgeでSearch new lightsでbodyを空の状態で検索
  -> なにも見つからない
 ・同じく2台目のBridgeでSearch new lightsでbodyにランプのシリアルNoを指定して検索
  -> ランプが点滅して繋がったように見えるが、検索結果には何も見つからない
 ただ、不思議な事に1つのランプだけは他のBridgeに移動することが出来た
 スターターキットはBridgeとランプ3個が既にペアリングされた状態になっているので、結果的に片方のBridgeには4個がペアリングされた状態になり、もう片方には2個がペアリングされた状態になってしまいました。時間切れでこの件はこれ以上追っていません。

2.HueのランプはAPIからはUniqueIDやBridgeに登録されているLightの番号は引けるけど、Search new lightsではランプの側面に書かれているシリアル番号が必要になる可能性があるため取り付け前にシリアル番号を控えておく必要がある。
 今回は、ランプが全て設置された状態からセットアップだったので全て外して確認するのは大変だと思ったのですが、Search new lightsでbodyが空でも全てのランプが検索できたので外さずに済みました。

3.数が多いので制御対象を都度group登録してstateを変更して制御しようとしたけど、連続してAPIを叩くと色々とエラーになって指定してないランプの色まで変わってしまったり、ところどころ色が変わらなかったりする。特にon/offの制御を取りこぼすと1つだけ点いていたりして目立つのでちょっとNGかな。
 -> 結局、groupでの制御はやめて、set light stateで個別制御を制御対象全てのランプに投げてエラーが返ってきたものについてはretryを3回ほど投げる仕様にして、その後2秒間GUIの制御が無い場合は全ランプの最終stateの状態を2度投げることでリカバリーすることにした。これはSuccessが返ってきているにもかかわらず、Stateが正しくないランプがあったので念の為にこうしている。

色々と書きましたが、色の均一性とか表現範囲はHueが一番かと思います。これだけ並べて色が均一に出ているのが素晴らしいです。




2016年4月1日金曜日

RP-5基板の組み立て

KiCadで設計してElecrowに注文していた基板も上がってきて、部品も揃ったので組み立ててみました。

ちなみに今回はFedExにしてみました。

3/15火曜日の夜 出図
3/16水曜日 製造開始
3/22火曜日 写真付きで基板できたよとの連絡
3/23水曜日
17:32 出荷地のFedEx営業所を出発  YUEN LONG HK
21:50 FedEx経由地に到着         GUANGZHOU CN
3/24木曜日
03:13 FedEx経由地を出発         GUANGZHOU CN
05:06 輸送中/処理中                          GUANGZHOU CN
07:32 仕向国仕分け場所                    NARITA-SHI JP
11:57 輸送中/処理中                          TOKYO-KOTO-KU JP
14:14 国際輸送許可 - 輸入                 TOKYO-KOTO-KU JP
20:16 輸送中/処理中                          TOKYO-KOTO-KU JP
3/25金曜日
10:02 FedEx 営業所                          TOKYO JP
13:24 配達完了

製造開始から土日を挟んで9日間で到着しています。

今回はTAKACHIのケースに合わせて基板を設計しました。
当然ながらピッタリと収まっています。


レーザーカッターで1.5mm乳白色半透明のアクリル板を切り出して赤外線LEDと受光部の窓を作っています。

後ろ側も同じ板で電源とUSB、Etherの口をRaspberryPi 2 Model-Bの穴位置に合わせて加工しています。
本当は段差が無いようにできればいいのですが、素人の加工としてはこのくらいが限度でしょうか。

2016年3月24日木曜日

HomeServerのinstall

GitHubにRaspberryPi 2 Model Bを使ったSiri対応の学習リモコンのコードを公開しました。
RaspberryPi Model A+/B+でも動くと思います。RaspberryPi 3に関しては確認できたら報告します。

■このソフトで現時点で出来ること
 ・赤外線リモコン、HA端子(JEM-A端子)、弱電スイッチなどの制御
 ・赤外線リモコン信号、HA端子、弱電スイッチ、各種センサーなどのステータス情報取得

 - telnet(socket)経由での上記制御と情報取得(human-readble IF, JSON IF)
 - HomeKit対応アプリからの上記制御と情報取得(HAP-nodeJS経由)
   AppleTV(3rd generation以降)を経由して外出先からの上記制御と情報取得
   iPhoneのsiriによる上記制御と情報取得
   ※ ただしAppleがHomeKitの認証を強化すると動かなくなる可能性あり
 - javascript(node.js)での制御
   センサー等の変化や30sec intervalのイベントでjavascriptの関数が呼び出されるので条件を設定して制御することが可能
     日没にあわせてシャッターを閉める、あかりをつける
     玄関のロックが5分間開いていたらメールする
     雨が降ってきたら窓を閉める
     室温に応じて起床前にエアコンをつける
     窓を開けたらエアコン停止
     etc

■今後追加していきたい機能(余裕があれば)
 - リモコンの学習、各種設定のWebUI化
 - javascriptでの制御部分のVisualPrograming化

■下のブレッドボード用回路の機能
 - 赤外線リモコン送信・受信

■RP-5基板の機能
 - 赤外線リモコン送信・受信
 - ZigBee(XBee)経由でのリモート子機(HA-5)制御
 - HA-5子機の故障診断とファームウェアアップデート、ペアリング

■HA-5基板の機能
 - 赤外線リモコン送信・受信
 - HA端子(JEM-A端子)での家電制御、ステータス確認
 - 弱電(24V以下)のスイッチ制御・ステータス確認(電動シャッターなどのスイッチ)
 - 各種センサー情報の取得(温度、湿度、雨、人感、etc)


ブレッドボード用回路は以下のとおりです。





リモコン学習時のブザー音とリモコン発光時の発光音が不要なら真ん中のブザー音出力ブロックは不要です。

LED101/102はリモコン用の940nmあたりの波長の赤外線LEDなら大体動くと思います。
ちゃんと赤外線LEDが発光しているかどうかはデジカメ等で見ながら発光させると確認できます。
ただし、iPhoneはカメラに赤外線フィルターが入っているようで見えませんでした。

赤外線受光モジュールは電源が逆になっているデバイスもあるので他のものを使う場合は気をつけて下さい。

FETもNchで耐圧がOKなら動くかと思います。こちらもピン配置を確認して使って下さい。

installの大まかな手順を書いておきます。
詳細手順はこちらのREADME.mdを御覧ください。(下の方です)
※scriptからダウンロードするので、gitをcloneする必要はありません。

1.最新版のRASPBIAN JESSIE LITEをダウンロードしてSDカードに書き込みます。
2.SDカードをRaspberryPiにセットしてNetworkを接続し起動後loginします。
3.setup scriptを実行する
 > curl -O https://raw.githubusercontent.com/mnakada/ha1control/master/setup.sh
 > sudo bash setup.sh
4.piのアカウントpasswordを変更する
5.reboot
6.HomeKit対応アプリをiPhoneにinstall
7.対応アプリでHA1HomeServerを登録

国内のエアコン等も大抵のものは動くかと思います。
Daikin/Panasonic/三菱重工は確認しました。

AppleTVの第3世代以降があってiCloudの設定をしてあれば外出先からもアクセス出来ます。
ただし、AppleTVの自動updateをonにしているとupdate後自動起動してくれるのですが、iCloudのloginを一度解除してからもう一度loginし直さないとアクセスできなくなってしまいます。

2016年3月19日土曜日

RP-5基板

最近XBeeの新型のS2Cが出たり、ATmega328も昨年からATmega328pbが出ていてRaspberryPi3も出るし、Kicadも最新版をbuildしたので、回路を見なおして基板を起こし直すことにしました。
これまで親機の方はアクリル板をレーザーカッターで切り抜いてケースを作っていましたが、曲げ加工とか手間がかかるのでTAKACHIのPF-15-3-10Wを使ってみることにしました。
赤外線を通す必要があるので、このケースの前後のパネル部分の代わりに乳白色の半透明アクリル板をレーザーカッターで加工して使ってみます。
赤外線LEDや受光部、RaspberryPiの各種コネクタの位置をパネルの範囲に入るように配置しながら高さ方向の適当な位置を考えていきます。
下の図の赤い線で書かれているのがRP-5基板とRaspberryPiの位置になります。


最初は基板固定用のM2.3用ボスで基板を固定することを考えたのですが、この高さで固定するとRaspberryPiのコネクタがパネルの高さ内に収まらないため3mm程度スペーサーで嵩上げする必要があります。
そこで、ケースの固定用の支柱部分に基板をいれて上側に適当なクッションを入れることでちょうどいい高さに収まらないかと考えています。

基板の回路はこれまでとほとんど変わってませんが、RaspberryPiと接続してIRリモコンの学習用の受光部と発光部、子機との通信用のXBeeと将来置き換えていけるようにESP8266用の回路を入れています。


RaspberryPiと接続して使う場合は下の回路だけ部品をのせることで親機としての機能になります。


Bee経由で子機として使う場合はATmega328pbでリモコン機能を中継する形になります。
回路はシンプルで電源とマイコン、XBee、赤外線受発光部だけになります。



この回路を丁度ケースに入るような形で設計したのが下の基板です。



それほど面積は要らないのですが、ケースに固定する部分の関係で10x15cmに入る位の大きさになってしまいました。
もう1つのFriskサイズの子機基板と一緒にElecrowに発注しました。
今月末くらいに届く予定です。

もう1枚の基板については次回書きます。


2016年2月27日土曜日

HomeBridge改めHAP-nodeJSと接続してsiriで家をコントロール その4

Siriとの会話に疲れてきたので、現状のコードを整理してGitHubに上げました。
とりあえずdemoModeに設定してあるので単独で動いて同じネットワーク上のiPhoneから繋がります。
demoModeではコントロールサーバーにコマンドを投げる所をconsole.logの出力だけ、statusなどを受ける所をダミーデータに置き換えています。

https://github.com/mnakada/HA1HomeBridge.git


動作確認済み環境
 MacBookPro OS-X El Capitan 10.11.3
 RaspberryPi2 RASPBIAN JESSIE LITE kernel 4.1.17
 node.js v4.3.1はnodejs.orgからinstall
 多分v5系でも動くと思います(未確認)。

iPhone側の環境は
 iPhone6S iOS9.3beta4
   (beta3以前の場合、package.sonファイルのhap-nodejsのversion指定を0.2.4にすると動くかもしれません)
 HomeKitアプリはElgato Eve (App Storeでhomekitで検索すると出てきます)

> git clone https://github.com/mnakada/HA1HomeBridge.git
で取得後、
> cd HA1HomeBridge
> nam install
> node .
でHomeKitのBridgeとして起動し、PINを表示します。
あとでこのPINの画面を取り込むのでそのままにしておきます。


iPhoneをWiFi接続にしてElgato Eveを起動
-> アクセサリを追加
-> 自動でホームの名前が入るので適当に修正して右上の次へ
-> アクセサリを選択でHA1HomeBridgeを選択
-> 真ん中のXXX-XX-XXXが囲われているところを選択
-> HomeKitアクセサリを追加のDialogでこのまま追加を選択
-> iPhoneのカメラで先ほどのPINの画面をキャプチャすると自動で接続してくれます。
(もしPINが読み込めないようでしたら、下の方にある手動で登録から登録します)
-> 部屋を選択は後で設定できるので取り敢えず次へ
-> 追加済みのアクセサリで完了
-> ホーム(デフォルトの部屋)を選択するとコントロール画面にたどり着きます。

この状態でアプリからスイッチなどをいじってnode.js側にそれらしいコマンドの表示が出ていれば正常につながっています。

siriで使えるコマンドはclient.uiファイル内でsiriNameのarrayで記述されているものになります。
ここのsiriNameで記述されているものがEveのコントロール画面の項目名として見えていて、siriへの指示はこの項目名に対して指示を出します。
例えば
「玄関の鍵を開けて・閉めて」「風呂のお湯を入れて・止めて」「南側のエアコンを一八度に設定して」「ダウンライトを点けて・消して」「リビングの湿度は?」「寝室の温度は?」
などが動いています。
現状、わかっている問題点は
1.「南側の窓を開けて」は「100%に設定しました」と答えて動くけど「南側の窓を閉めて」も「100%に設定しました」といわれて窓が開いてしまう
シャッター、ブラインドも同様
2.エアコンの温度は設定できるけど、暖房、冷房のモード切替が出来ない、エアコンをoff出来ない
3.「NHKをつけて」はWebの’NHKをつけて’を検索に行ってしまう
と言った感じです。


HomeBridge改めHAP-nodeJSと接続してsiriで家をコントロール その3

コントロールサーバーの動いているRaspberryPi2の上にhomebridgeを動かして、pluginとしてコントロールサーバーと接続しようとしていたのですが、いろいろ実装していく内にhomebridgeの下のレイヤーであるHAP-nodeJSと直接繋ぎこんだ方が良さそうなことがわかってきて繋ぎ方を改めました。
ところが、実装を切り替えて試してみてもEveで初期設定まではうまくいくのですが、接続されたホームの中にAccessoryが何もない状態になってしまいます。
そんなこんなをしている内にHomeBridgeとの接続も同じ状態になってしまい訳がわからなくなってしまいました。
2日ほどわからない状態だったのですが、色々と試している内に最初に試していたdirectoryのイメージを起動するとちゃんと繋がることに気が付きました。
差分を切り分けるために実験していくとHAP-nodeJSのVersionが0.2.4以前ならちゃんと繋がることが分かりました。
どうも0.2.5でHomeKitの最新のプロトコルにupdateされていたようで、自分のiPhoneがiOS9.3beta3だったため繋がらなかったようです。
iOS9.3beta4にupdateして、HAP-nodeJSも0.2.5にしたら無事に繋がるようになりました。
このdebugの過程でdebug情報を色々出していたのですが、何故かAppleTVとの通信をしているlogが残っていました。
AppleのHomeKitのページをよく読むと、うちにある第3世代のAppleTVだとHomeKitの外からのアクセスを中継してくれるようです。
AppleTVのiCloudの設定を再度し直して、LTE回線からiPhoneでEveを起動してみるとちゃんと繋がり、コントロールもできています。
LTE回線経由でもsiriでのコントロールもちゃんとできました。
なかなかいい感じです。

siriとの会話の方は相変わらず実験中で、まだエアコンとシャッター、電動窓、TVはNHKがうまくコントロールできていません。
エアコンは温度設定はできるのですが、暖房、冷房を指定することが出来ません。
エアコンを切ることも出来ていません。
シャッター、電動窓は開くことは出来ても閉じることが出来ません。
「シャッターを開けて」で「100%に設定しました」と言われてシャッターが開きますが、「シャッターを閉めて」でも「100%に設定しました』と言われてしまいます。これはsiriのbugのような気がします。
「NHKをつけて」はNHKをつけてをwebで検索されてしまいます。
もう少し会話の練習が続きそうです。

2016年2月19日金曜日

homebridgeと接続してsiriで家をコントロール その2

homebridgeを使って自宅システムをsiriでコントロール出来るようにするために色々と試しています。
とりあえずざっくりとしたつなぎ込みは出来て、eveというhomekit対応のアプリで接続できるようになりました。

ステータスを取得する方は結構つながってきました。

「リビングの湿度は?」『34%に設定されています』ちょっと日本語が変ですが値は返ってきます。
「寝室の湿度は?」『56%にせっていされています』こちらも日本語がおかしいですが値は返ってきます。
「2階の温度は?」『4.7度から17.6度です』これは全ての温度デバイスの値を読み込んで範囲を回答してます。
「1階の温度は?」->「外の温度は」(文字が勝手に外に置き換わる) -> 自宅周辺の天気予報から温度を答えてくる
「外の気温は?」 -> 同じく自宅周辺の天気予報から回答

制御の方もなんとなく動いてきてます。
「リビングの床暖房をつけて」『デバイスからの応答がありません』eveからは制御できています。
「ダイニングの床暖房をつけて」『デバイスからの応答がありません』こちらもeveからは制御できています。
「風呂のお湯を入れて」-> OK
「冷暖房の自動運転を入れて」-> OK
「テレビを消して」『私には無理です』
「テレビをオフして」->OK
「NHKをつけて」->WebからNHKをつけてに関する情報を表示
「日本テレビをつけて」『よくわかりません』
「Eテレをつけて」->OK
「日テレをつけて」->OK
「TBSをつけて」->OK
「テレビ東京をつけて」->OK
「テレビ朝日をつけて」->OK
「テレ朝をつけて」->OK
「フジテレビをつけて」->OK
「テーブル照明をつけて・消して」->OK
「スポット照明をつけて・消して」->OK
「間接照明をつけて・消して」->OK
「ダウンライトをつけて・消して」->OK
「カウンター照明をつけて・消して」->OK
「南側のエアコンを18度にして」->OK
「南側のエアコンを消して」『デバイスからの応答が有りませんでした』
「西側のエアコンを20度にして」「西川のエアコンを20度にして」(勝手に変換される)『私には出来ません』
「西川のエアコン」も登録するとOK

なかなか難しいです。
『デバイスからの応答が有りません』系は何かプログラムに問題がある気がするのでもう少し検討ですね。
他の勝手に違う単語に置き換えられる系はその単語も登録してしまう作戦で行くことにします。
もう少しSiriとの会話?戦い?は続きそうです。

2016年1月30日土曜日

homebridgeと接続してsiriで家をコントロール

最近homebridgeというopen sourceのHomeKitのブリッジソフトが流行っているようなので、自宅のシステムと仮接続してみました。
とりあえず、まだTVのon/offだけですが動作させることが出来ました。
ただ、siriがどんなコマンドを受け付けてくれてサービスをどう登録するのかがよく判りません。
「テレビをonして」「テレビをoffして」は動きますが「テレビをつけて」はダメでした。
放送局とかを指定したりボリュームをコントロールするには何と言えばいいんですかね?

とりあえず、呼び出される関数の中でhomebridge.hap.Serviceをdumpすることで
     AccessoryInformation: { [Function] super_: [Circular] },
     AirQualitySensor: { [Function] super_: [Circular] },
     BatteryService: { [Function] super_: [Circular] },
     BridgingState: { [Function] super_: [Circular] },
     CarbonDioxideSensor: { [Function] super_: [Circular] },
     CarbonMonoxideSensor: { [Function] super_: [Circular] },
     ContactSensor: { [Function] super_: [Circular] },
     Door: { [Function] super_: [Circular] },
     Fan: { [Function] super_: [Circular] },
     GarageDoorOpener: { [Function] super_: [Circular] },
     HumiditySensor: { [Function] super_: [Circular] },
     LeakSensor: { [Function] super_: [Circular] },
     LightSensor: { [Function] super_: [Circular] },
     Lightbulb: { [Function] super_: [Circular] },
     LockManagement: { [Function] super_: [Circular] },
     LockMechanism: { [Function] super_: [Circular] },
     MotionSensor: { [Function] super_: [Circular] },
     OccupancySensor: { [Function] super_: [Circular] },
     Outlet: { [Function] super_: [Circular] },
     SecuritySystem: { [Function] super_: [Circular] },
     SmokeSensor: { [Function] super_: [Circular] },
     StatefulProgrammableSwitch: { [Function] super_: [Circular] },
     StatelessProgrammableSwitch: { [Function] super_: [Circular] },
     Switch: { [Function] super_: [Circular] },
     TemperatureSensor: [Circular],
     Thermostat: { [Function] super_: [Circular] },
     Window: { [Function] super_: [Circular] },

     WindowCovering: { [Function] super_: [Circular] } } }
といったサービスの種類があることは分かりました。
現状はSwitchにTVのon/offを接続しているだけなのですが、少しずつ他のWindowとかDoorやLightあたりを掘っていってみようかと考えています。

2016年1月15日金曜日

バーチカルブラインドの電動化その後

以前電動化したバーチカルブラインドですが、やはりちょっとモーターの出力に対して負荷が重いようで、たまにきちんと閉まらなかったりしてました。

現在使っているモーターはSWITCHSCHIENCEさんで売っているPololuの75:1ギアドモーターなのですがギア比をもう少し高くして低速化することでトルクを確保しようかと検討してみました。

たまたま立ち寄った千石電商でダイセン電子工業の132:1ギアドモーターが置いてあったのですが3.3V品でパワーがあまり出なさそう。
しかもPololuのモーターでエンコーダーを取り付けている後ろ側のシャフトが出ていません。
ただ、ギア部分の寸法が同じなのでうまく組み替えてPololuのモーターを132:1に出来るかもしれないと買ってみました。

ギアボックス部のネジ2本をはずして取り外して見てみたところ軸に付いているギアの歯数が違うので圧入されているギアも一度外して組み替える必要がありました。




なんとか外して組み替えてPololuのモーターに132:1のギアボックスを組み合わせ、取り付けてみました。



これを組み付けて







取り付けます。

ちゃんと速度が半分くらいになって多少の負荷でもきちんと開閉出来るようになりました。





2016年1月4日月曜日

node.js foreverをRaspberryPi起動時に自動起動するように設定する

node.jsをRaspberryPiでnvm管理下で使っていたのですが、サービスを常時動かしておこうとするとforever等で管理することになります。
ところが、foreverはinit.dに登録されているわけではないのでRaspberryPiを再起動すると自動で動いてくれません。
最初nvmを使ってnode.jsをinstallしていたのですが、nvmだと自分のアカウントのhomeの.nvmというディレクトリ以下に色々とinstallされてしまいシステムの起動スクリプトに記述するには気持ち悪い事になってしまいます。(まぁ、そこはそういうものだと割りきってしまっても良いのですが)
nvmは開発用の環境であって運用のための環境ではないということかと思います。
次に考えたのはapt-getでnode.jsをinstallすることですが、versionが0.10.29と古いため結局試行錯誤の末node.js自体はnodejs.orgのDOWNLOADSのLTSのv4.2.4を入れることにしました。
今回は/usr/local/にダウンロードしてきたイメージを展開して/usr/local/nodeにシンボリックリンクを張って運用しています。
ダウンロードの実体は/usr/local/node-v4.2.4-linux-armv7l/以下に展開されて、そこに/usr/local/nodeからシンボリックリンクされているという形です。
$ PATH=/usr/local/node/bin/:$PATH
とpathを通してから
$ npm install -g forever
でforverをinstallします。
これでnode, npm, foreverが準備出来たので、次に/etc/init.d/に起動スクリプトを用意します。

以下の例は/etc/init.d/ha1observerという名前で/var/ha1/ha1observer.jsにパラメータを付けて起動するためのものです。

-----
#!/bin/sh

### BEGIN INIT INFO
# Provides:          ha1observer.js
# Required-Start:    $network $syslog
# Required-Stop:     $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: forever running ha1observer.js
### END INIT INFO

USER=ha1observer
SCRIPT=/var/ha1/EventValidate.js
PIDFILE=/var/run/ha1observer.pid
LOGFILE=/var/ha1/ha1observer.log
PATH=/usr/local/node/bin:$PATH
FOREVER=/usr/local/node/bin/forever
NODE=/usr/local/node/bin/node
NODEAPP=/var/ha1/HA1Observer/ha1observer.js

start() {
  $FOREVER start --pidFile $PIDFILE -l $LOGFILE -a -d -c "$NODE $NODEAPP -u $USER -f $SCRIPT"
  RETVAL=$?
}

restart() {
  $FOREVER restart $NODEAPP
  RETVAL=$?
}

stop() {
  $FOREVER stop $NODEAPP
  RETVAL=$?
}

status() {
  $FOREVER list
  RETVAL=$?
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  restart)
    restart
    ;;
  *)
    echo "Usage:  {start|stop|status|restart}" >&2
    exit 1
    ;;
esac
exit $RETVAL

-----

ha1observer.jsは起動後に-uで渡されたユーザーにprocess.setuid()で切り替えて実行されます。
init.dからはrootで実行されるのでsetuidしないと色々と危険です。
これを準備したあと
$ update-rc.d ha1observer defaults 3 1
を実行することでrc?.dにシンボリックリンクが張られます。
再起動して
$ ps aux | grep ha1observer
で確認するときちんと実行されていることが分かります。

2015年11月27日金曜日

スマートロック

ちょっと頼まれて普通の鍵の玄関を電気錠化して遠隔制御を出来るようにしてみました。
自宅は建てた時から電気錠だったのでHA端子接続で簡単につなげられていたため、これまで普通の鍵を置き換える検討をしてませんでした。

今回鍵の電気錠化の部分は㈱ユーシン・ショウワのリ・ボーンIIを使います。




最初はAkerunとかQrioSmartLockとかも検討したのですが、どちらもBluetooth接続で暗号化されているのと鍵という性質上セキュリティが厳しくHack出来ないと考え別のものを探してみました。
リ・ボーンIIは玄関のサムターン部分を外して代わりにつけるタイプで、AkerunやQrioSmartLockと比べて面倒ですが、リモコンキーで制御なのでリモコンキーのボタンを制御できればどうとでもなるはずと考えて、とりあえず入手して検討します。

蓋をあけるとDIP-SWがあります。
今回はAutoLockはこちらで制御するので単純にopen/closeのリモコンでの制御通りに動くモードに設定します。




まず、リモコンキーをバラして確認していきます。



CR2032電池なので公証3Vですが回路は電池の初期電圧とかも当然対応しているので3.3Vでも大丈夫でしょう。



open/closeのpush-swがあって、片方の端子がGNDにつながっています。もう片方がpull-upされているようで、sw-offで3V,sw-onでGNDになります。
なので、ここをコントロールすれば鍵を制御できます。

改造に邪魔なので電池ホルダーをはずして、制御モジュールのコネクタと配線を繋いでいきます。
電源の3.3V,GNDの線とFET-SWの線をopen,closeのpush-swのpull-up側に接続します。
これで鍵自体は制御できました。


これにドアが開いているかを検知するセンサーと内側からドアを開けたい場合に押すスイッチを追加して完成です。




2015年11月20日金曜日

車のバッテリーチェック

以前、車の室内灯を点けっぱなしで一週間おいてしまいバッテリーが上がってしまったことがありました。
室内灯のスイッチがPush-Pushのスイッチなので頭があたったか何かで点いてしまったのかもしれません。
そのときは近所の人にブースターケーブルで繋いでもらい暫く走ってなんとか復活したのですが、なんとかしないとまたやりそうなので対策を作ってみました。
回路は簡単でバッテリーの12VをDC-DCコンバータで3.3Vに落としてXBeeの電源とし、同じ12Vを33Kと2Kで分圧してXBeeのADCに入れています。
DC-DCを使ったのは12Vから3.3Vにレギュレータで落とすとちょと損失が大きくなるためです。
実測するとXBeeの送信時に10mA程度、sleep時には0.1mA程度で30秒に1回500ms程度通信するので問題なさそうです。
サーバーのほうはXBeeが送ってくる電圧が12Vを切ったらメールするように設定したのでバッテリーが上る前に気がつけると思います。

FRISKケースに入れて

 車の中のバッテリー電源に接続します。

金属部品だらけなので電波が飛ぶか心配でしたが家のすぐ前なので大丈夫でした。


2015年11月7日土曜日

KiCad 4.0RC1でESP-WROOM-02用基板作成 その6

次はESP-WROOM-02版です。

RP-3基板





HA-4基板


こちらの基板はXBeeの裏面に書かれているアドレスを読み取れるようにXBeeの下のところに穴を開けてあるのですが、ESP-WROOM-02を載せると丁度放熱用のPadのところが穴に位置してしまってあまりよろしくないかもしれません。

まだ、ESP-WROOM-02をどう使うか悩み中です。ATコマンドのままでうまく使っていくのか、何らかの独自のバイナリのI/Fを定義してAVRと通信させるのか、とか考えてるところです。


2015年10月31日土曜日

KiCad 4.0RC1でESP-WROOM-02用基板作成 その5

基板が上がってきたので部品をマウントしてみます。
まずは従来通りのXBee版です。

RP-3基板
いい感じです。

HA-4基板
こちらもいい感じです。


RP-3基板をRaspberryPi2と組み合わせます。


あれ?

RP-3基板のHA-4基板書き込み用のコネクタがRaspberryPi2のHDMI、Audioコネクタと干渉しています。
CAD上で基板の板端をギリギリで避けたつもりだったのですが、コネクタの出っ張りを考慮するのを忘れてました。
実物確認しなかったためのミスです。
回路動作チェックをしてソフト書いたらもう一度出し直しです.......


2015年10月23日金曜日

KiCad 4.0RC1でESP-WROOM-02用基板作成 その4

日曜日に届きました。



速かったです。注文してから8日です。
10/10(土)の朝に出して10/14(水)の夕方には基板が上がってきてDHLに渡されています。
business day 4-7日となっていたのに土日も動いてくれてるんですね。
そのあと39時間後の10/16(金)の朝には国内についてますが、そこから配達されるまで49時間もかかってます。
実際の配達は佐川急便でした。
深センから成田のほうが成田から東京より近いようですね。

Wednesday, October 14, 2015
1 Shipment picked up SHENZHEN - CHINA             18:50
2 Processed at SHENZHEN - CHINA                      22:59
3 Departed Facility in SHENZHEN                      23:04
4 Clearance event SHENZHEN - CHINA, PEOPLES REPUBLIC 23:18

Thursday, October 15, 2015
5 Customs status updated HONG KONG            00:16
6 Clearance processing complete at SHENZHEN - CHINA  01:19
7 Arrived at Sort Facility HONG KONG                 03:17
8 Processed at HONG KONG                             06:37
9 Clearance processing complete at HONG KONG         06:37
10 Processed at HONG KONG                            19:15
11 Departed Facility in HONG KONG                    22:34

Friday, October 16, 2015
12 Customs status updated TOKYO - JAPAN        03:07
13 Transferred through TOKYO - JAPAN                 08:42
14 Arrived at Sort Facility TOKYO - JAPAN      10:00
15 Clearance event TOKYO - JAPAN                     10:37
16 Processed for clearance at TOKYO - JAPAN          10:37
17 Customs status updated TOKYO - JAPAN        22:42
18 Clearance processing complete at TOKYO - JAPAN    22:56

Saturday, October 17, 2015
19 Processed at TOKYO - JAPAN                        01:21
20 Departed Facility in TOKYO - JAPAN                01:45
21 Arrived at Delivery Facility in TOKYO - JAPAN     08:13
22 Forwarded for delivery TOKYO - JAPAN        09:33

Sunday, October 18, 2015
23 Delivery attempted; recipient not home            10:58
24 Delivered - Signed for by : DLVD BY AGNT          19:31


2015年10月16日金曜日

KiCad 4.0RC1でESP-WROOM-02用基板作成 その3

とくにパターン的におかしくなかったのでElecrowに出してみました。
Elecrowの注文のページは以前はクレジットカードもPayPalのシステム経由だったのでちゃんとしていたけど、今回は直接クレジットカードの番号を入れるように変わってました。
ただ、このページhttpで暗号化されていません。クレジットカードの入力が暗号化されてないのはちょっと不安なのでpaypalにしました。
送料は820gでShenzhen DHLが$20.44、Registerd Air Parcelが$17.02と$3位の差なのでDHLを選択。
片方はpanelize有りなので+1日かな。国慶節の連休明けなので注文が溜まってるから動きが遅そう。
10/10(土)に出したので月曜日から作業し始めてbusiness dayで10日くらいとすると10/26の週に到着ぐらいかな.....と思っていたら10/10の内に
10/10/2015 In production Dear Customer,
We have put your design into production, it will needs about 4-7 business days. Thank you!
Best Regards
Elecrow
と返ってきました。それでも混んでるから7business daysだろうと考えていたのですが10/15(木)の朝に写真付きで出荷の連絡がきました。


この辺がElecrowのいいところですね。深センは時差の関係で10/14(水)です。

DHLのTrackingを確認すると

Wednesday, October 14, 2015
1 Shipment picked up SHENZHEN - CHINA             18:50
2 Processed at SHENZHEN - CHINA                      22:59
3 Departed Facility in SHENZHEN                      23:04
4 Clearance event SHENZHEN - CHINA, PEOPLES REPUBLIC 23:18
Thursday, October 15, 2015
5 Customs status updated HONG KONG            00:16
6 Clearance processing complete at SHENZHEN - CHINA  01:19
7 Arrived at Sort Facility HONG KONG                 03:17
8 Processed at HONG KONG                             06:37
9 Clearance processing complete at HONG KONG         06:37
10 Processed at HONG KONG                            19:15
11 Departed Facility in HONG KONG                    22:34

Friday, October 16, 2015
12 Customs status updated TOKYO - JAPAN              03:07
13 Transferred through TOKYO - JAPAN                 08:42
14 Arrived at Sort Facility TOKYO - JAPAN            10:00
15 Clearance event TOKYO - JAPAN                     10:37
16 Processed for clearance at TOKYO - JAPAN          10:37

この調子だと週末か週明けには到着しそうです。

2015年10月2日金曜日

KiCad 4.0RC1でRaspberryPi2用のESP-WROOM-02用基板作成

KiCad 4.0RC1をせっかくbuildしたのでESP-WROOM-02用の基板を作成してみました。
RaspberryPi2用の基板ですがHAT規格ではありません。合わせられる所はHAT規格に合わせてますが、ACアダプタ用のコネクタを後ろ側から出すため基板外形を変更しています。
ケースは以前作成したRP-2基板用のものを流用する予定です。

回路は色々と余計なものがついていますが、基本的にはRaspberryPi2の電源をUSB-miniからではなくACアダプタ用のコネクタを背面側に出すための回路と、XBeeモジュール・ESP-WROOM-02のいずれか経由で子機と接続するための回路、RaspberryPi2に赤外線リモコンの送受信機能を追加するための回路、子機として使う時のためのAVRマイコン回路で必要に応じてマウント部品を変更して使うようにしています。

回路図は以下のとおり






で出来上がったパターンが以下のとおりです。


SWITCH-SCHIENCEがSeedStudioのPCB作成サービスの取り扱いを始めたのでこちらでお願いするか、以前出したElecrowに出すか、どちらが安いのか比較してみます。
今回は10cm x 10cm x 1.0mm panelizeなし、黒レジスト、10枚です。

SWITCH-SCHIENCEの場合
 Greenレジスト 10cmX10cm基板で3074円
 それ以外のレジスト 10cmX10cm基板で5882円
 +パブリックベータ期間なら送料324円、通常は1080円
で緑レジストの最安なら3398円
黒レジストにすると6206円

Elecrowの場合
 Greenレジスト 10cmX10cm基板$14
 それ以外のレジスト 10cmX10cm基板$15.9
 + 送料(Registerd Airmaailで$10.37,DHLで$16.37)
で緑レジストの最安で$24.37 = 2924円 ($1=120円換算)
黒レジストにすると$26.27 = 3152円
DHLにすると+720円

価格は緑レジストにすればいい勝負ですが他の色の場合はElecrowの方が半額近いですね。
納期はSWITCH-SCHIENCEは14-21日、ElecrowはこれまでDHLでの経験では1回目14日、2回目v-cutありでも14日だったので、こちらもそれほどの違いはなさそう。
ということで今回は黒色にしたいのでElecrowでRegisterd Airmailを試してみます。
.........
ところが、注文しようとしたらElecrowは国慶節で10/7までお休みでした。
別に急いでないので、もう1つの基板も描いてまとめて注文しようかと思います。

2015年9月25日金曜日

angular.jsとonsenUI

node.js、express、mongoDBときているので次はangular.jsです。
UIはどうしようかと思ったのですが、angular.jsと相性が良さそうで日本語で情報が豊富なonsenUIにしてみました。
ちょっとまだソースコードがグチャグチャなのでもう少し整理してから後ほどGitにでもあげようと思います。
まだ、どの処理をサーバーのnode.js側で処理してどの処理をクライアントのangular.js側で処理するのがいいのかを悩み中です。
最初はほとんどの処理をangular.js側に持っていったのですが、mongoDBから読みだしたデータを大量に送った場合にかなり動作が重たくなることがわかったので、ある程度サーバーサイドで処理して扱いやすい形に変換してからクライアントサイドでUIに表示する形にしたほうがいいようです。
サーバーを動かしているさくらVPSのx86仮想サーバーとiPhone5sのARM系64bitCPUではやはりパフォーマンスが違いますね。


2015年9月11日金曜日

UIの設定ファイル


node.jsのサーバーとmongoDBでサーバーサイドまで繋がったので、その先のクライアントサイドの実現方法を考えていきます。
UIをHTMLでベタに書いていくのはありえないのでUI定義ファイルを設計します。
まず最初にどんなUIにするのか仮決めします。一度パスが通るところまで作ってしまってから気に入らなければ修正する方針で行きます。
初めてなので色々と想定できていない事があると思うので、とりあえず一度作ってみるのが手っ取り早いですよね。

ざっと要件を考えます。
・全体のステータスを表示するメインページ
 ・部屋ごとにまとめて表示
 ・制御できるものに関しては選択すると制御用のボタンが出てくる
  ・TVはon/off/volume+/volume-/選局のボタン
  ・エアコンはモード切り替え/温度選択/offのボタン
・温湿度のグラフページ
 ・3日分くらい表示
・ログの確認ページ
 ・状態の変化、コマンドの記録
・デバイスの動作状況の確認ページ
 ・各コントロールモジュールの電源電圧と動作状況
といったところを表示します。

 最終的に作ったUIのメインページはこのような感じです。

  


UI定義ファイルは最終的にjavascriptで扱うのでJSONで記述します。

最初は部屋を定義します。
この後のItemの定義で使用するroomと表示用のlabelを定義しています。
Itemとは上のUIの1行ごとの部分を指しています。
この定義は上のUIのグレーになっている部分のタイトルなどに使用されます。
  "RoomList": [
    { "room": "all", "label": "全体"},
    { "room": "living", "label": "リビング"},
    { "room": "kitchen", "label": "キッチン"},
    { "room": "bathroom", "label": "浴室"},
    { "room": "bedroom", "label": "寝室"},
    { "room": "studyroom", "label": "書斎"}

  ],

次に各制御対象毎にUI定義をします。全部出しても同じような定義だらけなので代表的なものだけに絞っています。

 "ItemList": [
   { 
     "room": "all",
     "label": "玄関",
     "status": [
       {"label": "玄関錠", "sensor": "entrance_key_stat"}
     ],
     "buttons": [
       {"label": "open", "command": "entrance_key_open"},
       {"label": "close", "command": "entrance_key_close"}
     ]
   },

このItemは上のUIの一番上の方の玄関のラインを定義しています。
最初にroom:でallを指定しているのでUI上は全体の項目の中に配置されています。
次のlabelはこのItemの項目名として表示されているものです。
status arrayの中はCloseと表示されている状態表示の定義です。
この中のlabelはsensorのための表示用ラベルですがここのUIでは使用していません。
後にGraph等の中で必要になるかもしれないので定義しています。未定義の場合はroom.label+item.labelとみなされます。
button arrayの中はこのItemを選択した時に出てくるボタンを定義しています。下が玄関Itemを押すと出てくる制御用のボタンです。

  
labelでボタンに表示する名称、commandに送信するコマンドを定義しています。

次のItemは制御部分が無くstatusが2つあるものの定義です。
  
この例のように同じような種類の情報表示のみの場合に使っています。

  { 
    "room": "all",
    "label": "室内1F/2F",
    "status": [
      {"label": "室内1F温度", "type": "temp", "sensor": "internal_1f_temp"},
      {"label": "室内2F温度", "type": "temp", "sensor": "internal_2f_temp"}
    ]
  },

statusにtypeを設定すると単位をつけたりいくつかのところで特別な処理をしたりします。
今のところtemp,humidity,pir,rainと設定なしの5種類があります。

次はエアコン用のitemです。
  {
    "room": "study room",
    "type": "aircon",
    "label": "エアコン",
    "status": [
     {"type": "temp", "sensor": "studyroom_aircon_temp"},
     {"sensor": "studyroom_aircon_stat"}
    ],
    "commandPrefix": "studyroom_aircon_", 
    "buttons": [
     {"label": "off", "command": "off"}
    ]
  },
typeでairconであることを指定しています。これはモード切り替え、温度切り替えのために特殊処理があるためairconであることを指定します。 statusは温度とエアコンの状態を表示しています。commandPrefixは送信コマンドの前に追加する文字列を指定していて、この後出てくるAirconListで指定しているコマンドと合わせることで送信するコマンドを決定します。これはエアコン自体のコマンドは同じものだけどコントロールモジュールが違うのでエアコン毎にprefixを付けたい場合に付加します。
buttonsでモード切り替え、温度切り替え、送信ボタン以外のボタンを定義します。ここではOffボタンだけです。
エアコンを選択すると下の状態になります。

  

ここでcoolerの所を上下にスライドするとモードが切り替わります。


  
さらに温度の所を上下にスライドすることで温度設定を変更できます。
このカルーセルの動作の度にリモコンコードが出てしまうと煩わしいので決めた後にsendボタンで送信するようにしています。

カルーセル自体のUI設定はItemListの中ではなく別途AirconListの中で定義しています。

  "AirconList": [
    { "label": "auto", "color": "#404040",
      "command": [
        { "label": "auto", "commandSuffix": "auto" }
      ]},
    { "label": "cooler", "color": "#2586d9",
      "command": [
        { "label": "18", "commandSuffix": "cooler_18" },
       : 途中省略
        { "label": "29", "commandSuffix": "cooler_29" },
        { "label": "30", "commandSuffix": "cooler_30" }
      ]},
    { "label": "heater", "color": "#d93625",
      "command": [
        { "label": "18", "commandSuffix": "heater_18" },
       : 途中省略
        { "label": "28", "commandSuffix": "heater_28" },
        { "label": "29", "commandSuffix": "heater_29" }
      ]}
  ],

 最後にTVのitemです。

  {
    "room": "living",
    "type": "tv",
    "label": "TV",
    "commandPrefix": "",
    "buttons": [
      {"label": "on", "command": "tv_on"},
      {"label": "off", "command": "tv_off"},
      {"label": "vol+", "command": "tv_vup"},
      {"label": "vol-", "command": "tv_vdn"}
    ]
  },

typeをtvにしてitemがTV用であることを指定します。
commandPrefixはエアコンの時と同じです。
buttonsにon, off, vol+, vol-を指定しています。
TVの場合はこれらのボタンと選局のカルーセルが現れます。

  

TV局名の所を上下にスライドすることで選局できます。

  
選局後に局名ボタンを押すことでコマンドが送信されます。
TVの選局リストは下記のように定義しています。

 "TVChCommandList": [
    { "label": "NHK", "commandSuffix": "tv_1" },
    { "label": "NHK", "commandSuffix": "tv_2" },
    { "label": "日テレ", "commandSuffix": "tv_4" },
    { "label": "テレビ朝日", "commandSuffix": "tv_5" },
    { "label": "TBS", "commandSuffix": "tv_6" },
    { "label": "テレビ東京", "commandSuffix": "tv_7" },
    { "label": "フジテレビ", "commandSuffix": "tv_8" },
    { "label": "TOKYO MX", "commandSuffix": "tv_9" },
    { "label": "放送大学", "commandSuffix": "tv_12" }
  ]

今回はここまで。




2015年9月4日金曜日

mongoDB/mongoose

自宅のNATの内側から、さくらVPSのnode.js上のサーバーまでsecure websocket serverが開通したので気温や湿度、コマンドのやりとりや各種センサーの情報を記録するデータベースを設定していきます。
MEANスタックというのが流行りのようなので、mongoDBを使ってみることにしました。
node.js上のアクセスはmongooseを使用しています。
素人が書くよりも色々ネット上に書いてくれている情報があるのでインストール方法とかは省略します。
mongooseはSchemaを設定してアクセスするようなので、最初にどういうデータで格納していくかを考えていきます。
まず、定期的に測定する気温や湿度などのセンサー情報と何かスイッチ等をon/offした時などのタイミングで上がってくるイベントの最新情報のみを記録するためのStatusSchemaを考えます。これはLogとは別に最新データを素早くアクセスするために記録します。
情報としては接続先のclientID、センサー名称、センサーの値、更新時のTimeStampです。

var StatusSchema = new mongoose.Schema({
  client: {type:String, required: true},
  sensor: {type:String, required: true},
  value: {type:String, required: true},
  update: {type:Date, default:Date.now}
});
var Status = db.model('status', StatusSchema);

次にデバイスの最新情報を取得して保持しておくためのDeviceInfoSchemaです。
記録する情報は接続先のclientID、デバイス名称、デバイスタイプ、ZigBeeアドレス下位32bit、デバイスの機能情報、バージョン、電源電圧、デバイス状態、更新時のTimeStampです。
var DeviceInfoSchema = new mongoose.Schema({
  client: {type:String, required: true},
  device: {type:String, required: true},
  type: {type:String, required: true},
  addrL: {type:String, required: true},
  func: {type:String, required: true},
  version: {type:String, required: true},
  voltage: {type:String, required: true},
  state: {type:String, required: true},
  update: {type:Date, default:Date.now}
});
var DeviceInfo = db.model('deviceInfo', DeviceInfoSchema);

次は全ての変化の記録を記録していくLogSchemaです。
ここには接続先のclientID、情報のタイプ、データベースを検索する時に情報粒度を落とすためにつける分解能フラグ、更新時のTimeStamp、データ本体です。
データ本体はコマンド、レスポンス、ステータスなどのメッセージobjectです。
var LogSchema = new mongoose.Schema({
  client: {type:String, required: true},
  type: {type:String, required: true},
  fine: {type:Boolean, required: false},
  timeStamp: {type:Date, default:Date.now},
  data: mongoose.Schema.Types.Mixed
});
var Log = db.model('log', LogSchema);

最後にclientごとのUIを定義するためのClientUISchemaです。
これは制御する機器のコマンドとUIの表記を記述したテーブルを記録しています。
var ClientUiSchema = new mongoose.Schema({
  client: {type:String, required: true},
  clientUi: mongoose.Schema.Types.Mixed
});
var ClientUi = db.model('client_ui', ClientUiSchema);

長くなってきたのでUIのテーブルについては次回にします。