TOPへ

sakura.io 施錠状態監視IoT製作記事

○概要
"あれ・・・?今日家のカギをかけたっけ?"
"どうだったかな・・・閉めたような閉めてないような・・・"
そしてその日は一日中、カギのことが頭から離れなくなるのでした・・・

誰でも起こりうる、そして誰もがやったことがあるであろう日常の悲劇("今日カギ閉めたよな・・・")

「鍵のかけ忘れ?」(?がポイント)

鍵がきちんとかかっていたのならヨシ("カギ開けたままかなぁ・・・")。鍵をかけ忘れたのならそれはもう仕方がないです。("イヤ、閉めたはず・・・")
ここで一番問題なのは"鍵をかけたのか、かけていないのかがわからない"という「不透明な状態」が継続することです。("いや、でも閉めた記憶がないな・・・")仕事でも遊びでも心配事があっては心から集中することはできません。不透明な状態からは早く脱したいですね。
モノを無くしたときに、"モノの方から声をかけてくれればすぐ見つかるのに・・・"と思うことは多々ありますが、家の鍵であればsakura.ioを利用して、これを可能とすることができます。("カギ閉めたっけ?どうだったっけ・・・")


○主に必要なもの
―基板類―
・sakura.io通信モジュール×1(いつも同様、私はβ版通信モジュールを使用しています)("家出るときにカギを持ったのは間違いない・・・")
・Arduinoシールドボード×1
・Arduino Uno Rev3×1

―主に必要な部品類―
・抵抗 1kΩ ×3
・両面接着シート(3M スコッチ 強力両面シート 凸凹面用 70×140mm SH-70)
・リード線類(細目) ×適宜
・ピンヘッダ・ソケット ×適宜("鍵を鍵穴に差し込んだような気はする・・・")

○必要な知識
・Arduinoを使用した簡単なマイコンプログラミングができる
・C言語をコードを多少改造できるレベルは知っている("でも、いつものようなカギ閉めるときのガチャっと感は味わってない気がする・・・")
・JavaScriptのコードを多少改造できるレベルは知っている

―リンク一覧―
1.sakura.io施錠チェックWeb
今回作成したJavaScriptアプリケーションです。参考までにどうぞ。

○全体像
今回の製作の概要図です。


今回はWebSocketを使用した双方向通信を行います。("今家に帰ればカギ閉めれるよな・・・")
Arduinoとsakuraio通信モジュールに与える主な任務は
・玄関ドアの施錠状態を調べ、報告させる。(ドアのデッドボルトにタクトスイッチを押させます)

そして、Web画面からは
・現在の施錠状態の報告("でもカギ確認しに家に戻ったら間に合わなくなる・・・")
・通信モジュールとの接続確認
を通信モジュールに対し指令します。
こちらはJavaScriptで実装します。

○電気回路図


今までで最も簡単な、プルアップ抵抗とタクトスイッチをつなぐだけの電気回路図です。("今日に限って来客とかないよな・・・")

○Arduinoサイドのプログラム
今回はコードをそのまま載せます。今までと比べて大したことはやっていません。

機能としては
・Webからの接続確認に応答
・Webからの指令に基づいて、施錠状態を返信する。("いや、カギは確かに確認した・・・?よな・・・?")
・Webからの指令が無くとも、施錠状態に変化が生じたらWebに施錠状態を送信する。
これらが実装できればOKです。



#include <SakuraIO.h>
#include <stdio.h>

// Sakura IO
SakuraIO_I2C sakuraio;

//定数定義
#define SW_PIN 2 //スイッチ入力

//sakura.ioチャンネル定義
#define ORDER_CH 0
#define KEY_REPORT_CH 1

//グローバル変数定義
uint32_t BeforeOrder=0;
uint32_t NowOrder=0;
int BeforeLockKey=0;
int LockKey=0;
int BeforeSakuraPoint=0;
int SakuraPoint=0;

//関数宣言
void ReceptionOrder(); 
void Reception();
void setup()
{
  pinMode(SW_PIN, INPUT);
  LockKey = digitalRead(SW_PIN);
  BeforeLockKey=LockKey;
  
  Serial.begin(9600);
  
  //IoT通信モジュール関係
  
  Serial.print("Waiting to come online");
  for (;;) {
    if ((sakuraio.getConnectionStatus() & 0x80) == 0x80) {
        Serial.println("");
        Serial.println("connected");
        break;
    }
    Serial.print(".");
    delay(1000);
  }
  
  Serial.println("***********************");
  Serial.println("***********************");
  Serial.print("SakuraIoPoint=");
  Serial.println(SakuraPoint);

  //初期化処理
} 

/////////////////////////////////////////////
//メインルーチン
/////////////////////////////////////////////

void loop()    //プログラム本体(ずっと繰り返す。)
{
  //鍵状態の取得
  BeforeLockKey=LockKey;
  LockKey = digitalRead(SW_PIN);
  
  //IoT送受信処理
  ReceptionOrder();
  Transmission();
  delay(500);//0.5s待つ
}

void ReceptionOrder() {
  // 受信キューの状態を取得
  uint8_t rxAvailable;
  uint8_t rxQueued;
  sakuraio.getRxQueueLength(&rxAvailable, &rxQueued);

  BeforeOrder=NowOrder;
  
  // 受信キューにたまっているメッセージの数だけ繰り返す
  for (uint8_t i = 0; i < rxQueued; i++)
  {
    uint8_t channel;
    uint8_t type;
    uint8_t data[8];
    int64_t offset;
    
    //キューからのメッセージを取り出し
    uint8_t ret = sakuraio.dequeueRx(&channel, &type, data, &offset);
    
    //成功したら以下を実行
    if (ret == CMD_ERROR_NONE) {
      SakuraPoint++;
      SakuraPointCount();
      
      Serial.print("channel: ");
      Serial.println(channel);
      Serial.print("type: ");
      Serial.println((char)type);
      Serial.print("value: ");

      //バイト列から変換して値をプリント
      if (type == 'i') {
        memcpy(&NowOrder, &data, sizeof(uint32_t));
        Serial.print(i);
        Serial.print(":");
        Serial.println(NowOrder);
      }
    } else {
      Serial.println("ERROR");
    }
  }

  Reception();
}

//受信時の処理
void Reception()
{
  int val=0;
  switch(NowOrder)
  {
    case 0:
    break;
    
    case 1://"Module>現在の施錠状態確認します。"
      sakuraio.enqueueTx(ORDER_CH,NowOrder);
      SakuraioSend();
      NowOrder=2;
    break;

    case 99://"Module>接続確認OKです。"
      sakuraio.enqueueTx(ORDER_CH,NowOrder);
      SakuraioSend();
      NowOrder=0;
    break;
    
    default:
    break;
  }
}

//送信時の処理
void Transmission()
{
  
  switch(NowOrder)
  {
    case 0:
      if(BeforeLockKey!=LockKey)
      {
        PrintVar();
        sakuraio.enqueueTx(ORDER_CH,(uint32_t)102);
        sakuraio.enqueueTx(KEY_REPORT_CH,(uint32_t)LockKey);
        SakuraioSend();
      }
    break;
    
    case 2://Module>現在施錠状態報告します。
      sakuraio.enqueueTx(ORDER_CH,(uint32_t)(NowOrder+100));
      sakuraio.enqueueTx(KEY_REPORT_CH,(uint32_t)LockKey);
        
      SakuraioSend();
      NowOrder=0;
      PrintVar();
    break;
    
    default:
    break;
  }
}

void SakuraioSend()
{
  sakuraio.send();
  SakuraPoint++;
  SakuraPointCount();
}

void SakuraPointCount()
{
  if(SakuraPoint!=BeforeSakuraPoint)
  {
    Serial.print("SakuraIoPoint=");
    Serial.println(SakuraPoint);
  }
  BeforeSakuraPoint=SakuraPoint;
}

void PrintVar()
{
  Serial.print("Lock=");Serial.println(LockKey);
}

○Webサイドのプログラミング
やることは今回少ないです。基本的に今までと同様の方法を使います。("カギ閉めてなくても一日くらいは大丈夫だよな・・・?")

・通信モジュールとの通信が確立しているか確認する機能。
・通信モジュールに指令を出し、報告を受ける。
・受けた報告を元に、「施錠」「解錠」を表示する。

これだけです。絵面としてはこんな感じに作ってみました。


「接続先URL」と「モジュール」、それに「接続」「切断」に関しては今までと同じで、WebSocket通信を確立するための項目です。
接続成功すると、自動的に「施錠状態報告」の指令を通信モジュールに出します。

「施錠状態報告」
通信モジュールに現在の測定値を報告させる指令を出します。("カギ開いてて誰かが勝手に入ったらどうしよう・・・")
指令を受けた通信モジュールは一旦返答し、その後施錠状態をWebに送信します。
WebSocketを接続したときに自動的に一回実行されます。

「接続確認」
通信モジュールとの接続を確認するためのボタンです。正常に接続されている場合、通信モジュールから返答があります。

メッセージログ
Web側と通信モジュール側とのやり取りを記述していく画面です。("でも"たまたまカギかけ忘れて"というときに限って何かあるんだよな・・・")

○施工
機械的な動作原理としては
・デッドボルトでタクトスイッチを押す
これだけです。
施工もデッドボルトの受け側にリード線を取り付けたタクトスイッチを貼り付けるだけです。("盗まれて困るもの・・・ないこともないけど・・・今日早く帰ってカギ確認したい・・・")


これがデッドボルトで、このデッドボルトがタクトスイッチを押すことでArduinoがON-OFFを検知することができます。


適当な置き方ですが、設置状況はこんな感じです。


○結果
全体構成もプログラムも何もかもが小規模ですが、これも立派なIoTです。

実際に外出してスマートフォンで施錠状態を確認している写真がこちらになります。("カギのことで頭がいっぱいだ・・・!")



IoTなので当たり前ですが、外出先でも施錠状態が確認できます。今回はちゃんと施錠をして外出をしたことがわかります。("よし、確かにカギをかけているぞ!")



詳細は省きますが、施錠状態に変化があった時とWebから施錠状態を確認した時のデータをデータベースに保存するようにもしています。なので、「いつ解錠・施錠されたか」と「いつWebから確認したか」がデータで分かるようになっています。

○まとめ
・企業が提供する入退館システムには遠く及ばないですが、sakura.ioを利用してタクトスイッチ1個・抵抗1個・リード線数本だけで家の鍵をIoT化して自家製お手製の施錠状態監視システムを作ることができ、ようやく余計なことに頭を悩ませなくて済むようになりました。

・余計な心配があると今回の記事のように、やるべきこと・書くべきことに集中できなくなってしまいます。

・"解錠状態だったら出先でもカギをかけれるようにできればいい"とも思ったのですが、カギかけた後に"実はカギは家の中にあった。そしてカギは一本しかない"というインキーという悲劇を生みかねないので、今回は"監視するだけ"にしました。

・これまでのプロジェクトで何回かArduinoやJavaScriptを扱ったことも幸いして、はんだごてを握り始めてからArduino、JavaScriptプログラミングを完了させるまで4時間程度で一通りのシステムを完成させることができました。

・プロジェクトと名をつけるのも憚られる感じもしますが、"IoTだから"と特に肩肘張らず"簡単なものは簡単に作る"、これも立派な"IoT開発"です。

・この"簡単なものを簡単に作る"を実現しているのもsakura.ioがあったからに他なりません。

・今回は家の施錠状態をテーマにしましたが、生活の中で"このモノの状態がどこでもわかったら便利"というのはまだまだ転がっているかもしれません。


2018/3/31(Sat) 記

(C)2018 Iseba's Labo