LINE Clovaを使って声でobnizを動かす

スポンサーリンク

はじめに

小型のIoTボードobnizとスマートスピーカーLINE Clovaを連携させ、声でobnizを動かす試行を行いました。
モーターやLEDを声で操作でき、アイディア次第で色々な工作に使えると思いますので、メモとして残します。

使用したもの

  • obniz
  • LINE Clova Friends Mini
  • LED 緑、黄、赤
  • 抵抗 150Ω(黄、赤用)、100Ω(緑用)
  • サーボモーター SG90
  • DCモーター(羽根を付けて扇風機にする)
  • ブレッドボード、配線

緑のLEDにつなげる抵抗のみ100Ωにしたのは、150Ωでは明るさが足りなかったため、少し抵抗値を下げて明るくしたためです。

ハードウェアの準備

下図のようにobnizとサーボモーター、DCモーターおよび3色のLEDを接続します。
そしてobniz、ClovaともWifiに接続していることを確認します。

Clovaスキルの作成

Clova Developer Center βをブラウザで開き、「スキルを開発する」を押します。スキルとはスマートスピーカーのプログラムのことです。
LINEアカウントでログインします。

「LINE Developersでスキルチャネルを新規作成」を押します。

任意の名前でプロバイダーを作成します。以下の例ではdemo-providerという名前で作成しました。

 任意の名前でチャネルを作成します。以下の例ではspeech-demoとしました。

 同意を求める欄にチェックを入れ、「スキル開発を始める」を押します。

以下のように基本情報を設定します。

項目設定内容
Extension IDcom.speech-demo.myservice
スキル名スピーチデモ
呼び出し名(メイン)スピーチデモ
呼び出し名(サブ)スピーチでも
AudioPlayerの使用いいえ
提供者区分個人
提供者名自分の名前
担当者メールアドレス自分のメールアドレス
Estensionと連携するLINEのアカウント選択しない

”スピーチ”は恐らく他の単語に間違われることは無いと考えましたが、後から思えば、”酢ピーチ”などをサブに入れても良かったかもしれません。”デモ”は接続詞としての”でも”と捉えられるかもしれないと思ったので平仮名にした”スピーチでも”をサブの呼び出し名として登録しました。

「対話モデル」→「対話モデルを編集する」から対話モデルの作成を始めます。
まず、スロットを作成していきます。スロットとはプログラムで言うところの変数、もしくは、関数の引数のようなもので、会話の中に登場した際に値として取り出す単語を指します。
まずは、「カスタムスロットタイプ」の右にある+を押してカスタムスロットを追加していきます。

任意のスロットタイプ名をつけられます。ここでは、commandとしています。

以下のように会話から値として取り出したい単語の代表語と類義語を設定します。類義語には誤認識でそう解釈されるかもしれないような単語も加えます。

サーボモーターは角度を数値で指定したいので、ビルトインインテントの「CLOVA.NUMBER」をスロット名degreeとして追加しました。

次に「カスタムインテント」の右にある+を押して、カスタムインテントを作成します。
ここではobniz_commandとしました。
インテントは、想定される会話とその中でスロットとして取り出したい単語を指定するものです。
以下の欄に想定される会話を入力します。例えば「緑をつけて」のように。

入力した会話の中の「緑」は値として取り出してobnizに渡したい部分になります。「緑」の部分を選択状態にすると下図のようにスロットが選択できるので、commandを選択します。

サーボ用の会話の場合は「サーボ」に続く数値も取り出したいので、「サーボ」を上記と同様にcommandスロットにした後、数値部分を選択してdegreeスロットを割り当てます。

想定する会話全てをインテントに登録し終わったらビルドします。この処理には少し時間がかかります。

ビルドが終わったら、想定通りの動作になるかテストします。「テスト」を押してテスト用の画面に切り替えます。

下の赤枠の部分に会話のサンプルを入力すると、スロットとして取り出せてバックエンドサーバー(今回の例では後述のrunkit)へ送信したデータ、バックエンドサーバーから返ってきたデータ、Clovaの発話内容が確認できます。
バックエンドサーバーとのデータのやり取りはJSON形式で行われ、その内容も確認できます。

以上のようにClovaの動作確認ができたら、次はobniz側のコーディングに進みます。

Runkitでobnizのコーディング

無料のNode.jsサーバーrunkitを利用してobnizのプログラムを作成します。以下からログインします。
https://runkit.com/
以下の例のようにJavascriptでプログラムを作成します。
requireしている’@line/clova-cek-sdk-nodejs’に含まれる機能を利用することで、Clovaとの連携が簡単にできるようになっています。
clovaExtensionIdはClovaスキルを作成した際に設定したものを使用します。
yourObnizIdにはobnizの画面に表示されるIDを入れます。

const Obniz = require('obniz');
const express = require('@runkit/runkit/express-endpoint/1.0.0');
const clova = require('@line/clova-cek-sdk-nodejs');
const app = express(exports);

const clovaExtensionId = 'com.speech-demo.myservice';
const yourObnizId = 'XXXX-XXXX';

// 使い方案内文
const TEMPLATE_INQUIRY = '緑、黄色、赤、扇風機、サーボ180、停止 などを指示してください';

// obnizに接続
let obniz = new Obniz(yourObnizId);
let connected = await obniz.connectWait({ timeout: 5 });

// 接続機器設定
let servo     = obniz.wired("ServoMotor", {gnd:0, vcc:1, signal:2});
let ledGreen  = obniz.wired("LED", {anode:4, cathode:7});
let ledYellow = obniz.wired("LED", {anode:5, cathode:7});
let ledRed    = obniz.wired("LED", {anode:6, cathode:7});
let dcMotor   = obniz.wired("DCMotor", {forward:10, back:7});

// obnizへの指示
async function demo(command, degree) {
  ledGreen.off();
  ledYellow.off();
  ledRed.off();
  dcMotor.stop();
  if (command === '緑') {
    obniz.display.clear();
    obniz.display.print('Green');
    ledGreen.on();
  } else if (command === '黄色') {
    obniz.display.clear();
    obniz.display.print('Yellow');
    ledYellow.on();
  } else if (command === '赤') {
    obniz.display.clear();
    obniz.display.print('Red');
    ledRed.on();
  } else if (command === '扇風機') {
    obniz.display.clear();
    obniz.display.print('Fan');
    dcMotor.forward();
  } else if (command === 'サーボ') {
    obniz.display.clear();
    obniz.display.print('Servo ');
    obniz.display.print(degree);
    servo.angle(degree);
  }
}

//clovaとの連携部分
const clovaSkillHandler = clova.Client.configureSkill()

  //アプリ起動時の応答
  .onLaunchRequest(responseHelper => {
    responseHelper.setSimpleSpeech({
      lang: 'ja',
      type: 'PlainText',
      value: `「オブナイズスピーチデモ」を起動しました。${TEMPLATE_INQUIRY}`,
    });
  })

  //各インテントごとの対応
  .onIntentRequest(async responseHelper => {
    const intent = responseHelper.getIntentName();
    console.log(`intent : ${intent}`);

    if (intent === 'obniz_command') {
      let slots = responseHelper.getSlots();
      console.log(`slots : ${JSON.stringify(slots)}`);

      let command = slots.command;
      let degree  = slots.degree; 
      console.log(`command : ${command}`);
      if (command == null) {
        //応答する
        responseHelper.setSimpleSpeech({
          lang: 'ja',
          type: 'PlainText',
          value: `${TEMPLATE_INQUIRY}`,
        });
        return;
      }
      await demo(command, degree);
      //応答する
      responseHelper.setSimpleSpeech({
        lang: 'ja',
        type: 'PlainText',
        value: `${command}を実行しました。`,
      });
    } else if (intent === 'Clova.GuideIntent') {
      // ビルトインインテント。ユーザーがヘルプを呼び出した場合

      //応答する
      responseHelper.setSimpleSpeech({
        lang: 'ja',
        type: 'PlainText',
        value: TEMPLATE_INQUIRY,
      });
    } else {
      // その他のインテントの場合
      responseHelper.setSimpleSpeech({
        lang: 'ja',
        type: 'PlainText',
        value: `意図しない入力です。${TEMPLATE_INQUIRY}`,
      });
    }
  })
  // スキルの終了リクエスト
  .onSessionEndedRequest(responseHelper => { obniz.close() })
  .handle();

const clovaMiddleware = clova.Middleware({
  applicationId: clovaExtensionId,
});

app.post('/', clovaMiddleware, clovaSkillHandler);

Clovaから送られてきた情報を処理するためのキモは以下の部分です。
let command = slots.command;
let degree = slots.degree;
await demo(command, degree);
slots.スロット名 で各スロットの値を取り出してローカル変数に格納し、それをdemo関数に渡しています。
demo関数はこの部分より上の方に定義してあり、引数のcommandおよびdegreeの値に応じてobnizを動かすようになっています。

プログラムができたら上部にあるendpointをクリックします。

すると Cannot GET/ と表示されますが、気にせずにブラウザのURL部をコピーします。
LINE Clovaのスキル開発画面を開き、「開発設定」の「ExtensionサーバーのURL」欄に貼り付けます。

動作確認

下の動画のように声でモーターやLEDを操作することができました。

obniz speech demo

扇風機を回すとノイズが出て、Clovaがうまく認識してくれないケースがありました。

おわりに

やはり、obnizはArduino等に比べて圧倒的に簡単に遠隔操作の工作ができると思いました。
しかもスマートスピーカーとの連携も驚くほど簡単に実現できました。
今回の例ではobnizとClovaを近くに置いていますが、obnizとClovaの両方がネットにつながっていれば、遠く離れた場所(地球の裏側からでも)でも動かせるので、アイディア次第ですごく面白いものが作れそうですね。

今となっては記憶が定かでは無くなってしまった内容として、初めのうちClovaのテストがうまく行かず、ケータイからLINE Clovaアプリにログインしてスキル検索(検索対象は何でも良い)をするとうまく動くようになったように思います。ただし、色々試していたため、他の要因でうまく行くようになったのかもしれません。あくまでご参考まで。

参考文献

タイトルとURLをコピーしました