チュートリアル

Raspberry PiとECHOPFを組み合わせて家電を操作してみよう(その2:スマートフォンからECHOPFに指令を飛ばす)

前回はHomeBridgeを使ってRaspberry Piと家電を連携させる部分を作成しました。二回目となる今回は、スマートフォンやデスクトップのWebブラウザからECHOPFに値を書き込んでみたいと思います。この値はどの家電をどう(スイッチをオンにする、またはオフにするなど)操作するかを登録します。次回、この値をRaspberry Pi側で読み込んで実際に家電を操作します。

開発時には同じネットワークにありますが、例えばこの仕組みをインターネット上に配置すれば、外出先からでも自宅の家電を操作できるようになります。

ECHOPFのセットアップ

まずはECHOPF(クラウド)での設定を行います。行うのは以下の四つです。

  1. APIの作成
  2. メンバーの作成
  3. データベースの作成

APIの作成

外部からECHOPFの操作を行いますので、APIを作ります。これは設定メニューのAPIアプリの管理より実行します。

プラスアイコンをクリックします。

モーダルウィンドウが表示されたら任意の名前を入力します。今回はRaspberry Piとしています。

APIアプリが作られるとX-ECHO-APP-ID(アプリケーションID)とX-ECHO-APP-KEY(アプリケーションキー)が生成されます。これは後ほど使いますのでメモして置いてください。

メンバーの作成

外部公開することを考えると、誰でもデータを追加できるのはセキュリティ上よくありません。そこで権限管理を行います。まず左メニューのインスタンスをクリックします。そうするとインスタンス管理が表示されます。

プラスアイコンをクリックするとインスタンス生成モーダルウィンドウが表示されます。そしてメンバーをクリックします。

表示されたモーダルで以下のように入力します。

ラベル
インスタンスID admin
インスタンス名 管理者

最後に生成ボタンを押すと管理者インスタンスが作られます。作成後、左メニューの管理者インスタンスを選択して、メンバー管理をクリックします。

そしてプラスアイコンをクリックしてメンバーを追加します。ログインID、パスワード、名前、メールアドレスをそれぞれ入力してください。

追加されました。このアカウントでログインしたらデータベースを操作できるようにします。

データベースの作成

管理者の時と同じく、インスタンス管理で新しいインスタンスを作ります。今度はデータベースを選びます。

データベースインスタンスは以下のように入力します。

ラベル
インスタンスID homebridge
インスタンス名 HomeBridge

生成されることを確認してください。

設定を行う

左側のメニューからHomeBridgeを選択して、設定を選びます。

フィールドを設定する

まずデータベースを設計します。インスタンスフィールドを選択します。

最初は内容という項目しかありません。そこで項目を追加します。

フィールドID名前概要データ型入力必須
device デバイス どのデバイスを操作するか指定します テキスト 必須
switch オンオフ スイッチをオンにするか、オフにするか指定します 数値 必須

ここにどのデバイスをどう操作するかが入ります。元々あった内容というフィールドは不要なので消しましょう。以下のようになれば完了です。

ACLを設定する

次にACLを設定します。アクセスコントロールを選びます。管理者インスタンスだけ、一覧表示/個別表示/追加/編集/削除を許可します。これはレコード、カテゴリ、初期ACLのレコードおよびカテゴリすべて同じ設定とします。

これでログインしていないユーザ、または管理者インスタンスに属していないユーザはこのデータベースを操作できなくなりました。

最後に、外部レコード登録設定をクリックして、新規登録時ステータスを有効にしておきます。これを忘れるとAPI経由で新規登録したデータが無効状態になってしまいます。

コードの紹介

今回はJavaScript SDKを使います。個々の機能を関数としてまとめているので、順番に紹介します。後でこれらの関数を呼び出すだけで実装できます。

初期化

サーバ側のコードはNode.jsで構築しています。任意のディレクトリを作成し、初期化します。

$ mkdir iot
$ cd iot
$ npm init .

設定ファイル

設定ファイルを config.json として作成します。例えば以下のような内容です。すべてこれまで作成した内容になります。ドメインはECHOPFのドメイン、アプリケーションIDとアプリケーションキーはAPI管理で作成した際に生成されたものです。そして管理者として作成したメンバーインスタンスのIDと、追加したメンバーのログインIDとパスワードを設定します。最後に作成したデータベースインスタンスのIDを記載します。

{
  "domain": "XXX.echopf.com",
  "applicationId": "YOUR_APPLICATION_ID",
  "applicationKey": "YOUR_APPLICATION_KEY",
  "memberInstanceId": "admin",
  "login_id": "admin",
  "password": "password",
  "databaseInstanceId": "homebridge"
}

初期化

ECHOPFの初期化を行うコードは以下の通りです。設定ファイルを読み込んでドメイン、アプリケーションIDとアプリケーションキーで初期化します。ECHOPFのJavaScript SDKはセットアップ | ECHOPFよりダウンロードできます。

const config = require('./config');
const ECHOPF = require('./ECHO.min');

ECHOPF.initialize(
  config.domain,
  config.applicationId,
  config.applicationKey
);

ログイン

ログイン処理は次のように記述します。どのメンバーインスタンスに、どのIDとパスワードでログインするか指定します。今回は async/await を使って非同期処理を行っています。

const login = async () => {
  const result = await ECHOPF.Members.login(
    config.memberInstanceId,
    config.login_id,
    config.password
  );
  return result;
};

データベース追加処理

データベースに行を追加する処理です。 ECHOPF.Databases.RecordObject のインスタンスを使います。そしてデータを適用する際には put メソッドを使います。自分で追加したフィールド( deviceswitch)は contents というフィールドにHashで追加します。

そして保存は push メソッドになります。こちらも非同期処理なので、 async/await を使って処理します。なお、refidはユニークである必要があるので注意してください(今回はランダムな文字を生成しています)。

const add = async (device, value) => {
  const entry = new ECHOPF.Databases.RecordObject(config.databaseInstanceId);
  entry.put('refid', Math.random().toString(36).slice(-8));
  entry.put('title', 'Test');
  entry.put('contents', {
    'device': device,
    'switch': value
  });
  try {
    const result = await entry.push();
    return result;
  } catch (e) {
    console.log(e);
  }
};

後はこれらの関数を順番に実行していけば、管理者としてログインし、さらにデータを保存する処理ができあがります。

const main = async () => {
  const user = await login();
  const result = await add('cooler', 1);
  console.log(result); // 保存されたレコード
};
try {
  main();
}catch(e) {
  console.log('Error', e);
}

注意点

上記のコードは Node.js で実行しますが、Node.jsの場合は別途 form-data というライブラリをインストールしておく必要があります。

$ npm install form-data --save

サーバに組み込む

では上記の関数をHTTPサーバ上に組み込みます。今回は Express.js を使っています。ライブラリをインストールします。

$ npm install express body-parser --save

そして index.js を作成します。

const config = require('./config');
const ECHOPF = require('./ECHO.min');
// 初期化
ECHOPF.initialize(
  config.domain,
  config.applicationId,
  config.applicationKey
);
// Expressの設定
app.use(express.static('public'));
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());
// POST /add にリクエストがきた時の処理
app.post('/add', async function(req, res) {
  const user = await login();
  const result = await add(req.body.device, req.body.value);
  res.json({result: true});
});
// アプリケーションサーバの立ち上げ
app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});
// ログイン処理(上記参照)
const login = async () => {
  // 省略
};
// データベース追加処理(上記参照)
const add = async (device, value) => {
  // 省略
};

これでサーバは完成です。

Webブラウザ

次にWebブラウザ側のコードを作成します。まずHTMLですが、 public/index.html として作成します。内容としては、 POST /add に送るためのデータを入力させるのと、JavaScriptファイルの読み込み、そして非同期処理を行うライブラリの superagent を読み込みます。

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title></title>
    <meta charset="utf-8" />
    <meta name="description" content="" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>
  <body>
    <form id="form">
      デバイス<br />
      <input type="text" name="device" value="" /><br />
      値<br />
      <input type="radio" name="value" value="1" checked="true" />オン<br />
      <input type="radio" name="value" value="0" />オフ
      <button>送信</button>
      <div id="result"></div>
    </form>
    <script src="/js/app.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/superagent/3.8.3/superagent.min.js"></script>
  </body>
</html>

続いてJavaScriptの処理です。送信ボタンを押したタイミングでデバイス、値を取得して POST /add をリクエストします。

document.addEventListener('DOMContentLoaded', (e) => {
  // jQueryの代わり
  $ = (query) => document.querySelector(query);
  // フォームを送信する際の処理
  $('#form').onsubmit = (e) => {
    e.preventDefault();
    // 入力された値の取得
    const device = $('[name="device"]').value;
    const value = parseInt($('[name="value"]:checked').value);
    // POST /add をリクエスト
    superagent
      .post('/add')
      .send({
        device: device,
        value: value
      })
      .then(res => {
        $('#result').html('登録しました');
      });
  }
});

試す

ではWebサーバを立ち上げます。

$ node index.js

そして http://(立ち上げたPCのIPアドレス):3000/ にスマートフォンからアクセスしてみましょう。簡易的な画面が表示されたはずです。表示されたらデバイス名を適当に入力し、送信ボタンを押します。送信が完了すると、登録しましたと表示されます。

そしてECHOPFの管理画面でデータベースインスタンスを見ると、実際にデータが登録されているのが分かるはずです。

データの編集を押せば、登録された内容を確認できます。

まとめ

ここまでの処理でスマートフォンからのデータ登録処理が完了しました。JavaScript SDKを使うことで、簡単にECHOPFへのデータ登録ができるのが分かってもらえたでしょう。

次回はこの登録したデータをRaspberry Piから読み出して家電を操作する部分を作成します。

今回のコードはechopfcom/Echopf_IoTにアップロードしてあります。実装時の参考にしてください。