Raspberry Piを使ってSlackから自宅のエアコンを操作する仕組みを作ってみた

こんにちは、株式会社VALGOでテックリードを担っている村田と申します。

私は電子工作が好きで、特にRaspberry Piを用いたIoTを趣味で構築したりしています。

本記事では、私が個人的に実践した、Raspberry Piを用いたIoTについてご紹介したいと思います。

今回作成したのは、Raspberry Piを用いてSlackから自宅のエアコンを操作する仕組みです。

背景


自分が住んでいる家はとても年季が入っており、夏、冬になると部屋が極端に暑く、寒いです。

帰宅後にエアコンを付けて、部屋が快適な気温になるまで結構時間がかかります。

夏場は特に室温が 43℃近くまで上昇するため、しばらく部屋に入ることすら出来ません。

常日頃「家に帰ったら既に部屋がいい感じになってたらいいのになー」といつも思っていました。

自宅のエアコンは大変古い機種のため、今どきなら必ず搭載されているタイマー機能がありません…

そこで、以前から興味があり遊んでいたRaspberry Piを用いることで解決できないかと考え、この不満を解消すべく実践する事にしました。

目的


外出先からエアコンを操作して帰宅前にエアコンを起動しておき、部屋を快適な気温にしておきたい。

要件


スマートフォンからエアコンを操作出来る

  • 操作は出来るだけ簡単である
  • 普段からSlackというチャットツールを利用していたため、Slackから操作したい

設計


SlackのBotを利用

Slackが使えるプラットフォームであればどのデバイスからでも操作出来るためです。

Hubotを使用

GitHub製のChat bot作成フレームワークです。

本ツールを使用することで簡単に様々なチャットツールとHubotを連携することが出来るようになります。これにより、HubotからRaspberry Piを制御することが可能になります。

各種チャットツールと連携するためには、hubotの他にアダプターと呼ばれるものを導入する必要があるため、今回はSlackアダプターを導入します。

2024現在、Slackアダプターはアクティブな開発が行われておらず、代わりにSlack公式フレームワークのBoltを利用するよう勧められていました。

そのためか、公式手順どおりに進めても原因不明のエラーが発生し進めることができませんでした。

当プロジェクトのGithubコミュニティを調べてみると、今後もメンテナンスの予定は無いようでした。

今、2024年現在にあえてHubotの導入を勧める理由は特に無く、今回はあくまで個人的な理由による導入になります。

最終的にはこちらのIsuueにより何とか導入に成功しました。

Raspberry Piから赤外線LEDを発光させることでエアコンの操作を行う

Raspberry Piをエアコンのリモコンの代わりにします。

概要図


以下は簡単なシステム概要図です。

使用したもの


  • Raspberry Pi Zero W 2
  • microSDカード 64GB
    • スピードクラスはUHS-1であれば十分です。
  • ピンヘッダ
    • 購入したRaspberry Piはピンヘッダ未実装のため購入しました。
  • ブレッドボード
  • ジャンパワイヤ
  • 抵抗今後も電子工作で色々と使用することを考慮し、10Ω〜1kΩあたりのよく使いそうな抵抗を購入しました。今回使用する抵抗は100Ω x 3です。
  • 赤外線 LED(5mm赤外線LED 940nm OSI5FU5111C-40)
  • 赤外線リモコン受信モジュール PL-IRM0101(37.9kHz)シールド付リモコンから発信される赤外線を記録するために使用します。

各種材料は秋葉原にある秋月電子へ訪れ調達しました。

エアコン操作のためには電子回路を構築する必要があるため、以下のような回路を作成しました。

回路図の作成にはOSSのfritzingを利用しました。

LEDを破損させないために、接続する抵抗を求めなければなりません。

抵抗を接続しないと、LEDへ電流が多く流れ過ぎてしまい、破損してしまう恐れがあるためです。

今回購入したLEDの最大定格電流は100mAのため、40〜50mA程度流したいと考えました。

以下の方程式から必要な抵抗値を計算しました。使うのは主にオームの法則です。

3.3[V](使用する電圧) – 1.35[V](LEDの定格電圧) = 1.95[V](抵抗にかかる電圧)

1.95[V] ÷ 50[mA] × 1000 = 39[Ω](50mA流すために必要な抵抗値)

丁度よい抵抗は持っていなかったため、100Ω抵抗3つを並列に繋ぎ約33Ωを使用することにしました。

環境構築


各種ツールなどの詳しい導入手順は、他に参考になる記事が多く投稿されているため割愛します。

書こうかとも思ったのですが、記事の量が多くなってしまい読みにくくなってしまいますし、今回は導入手順を説明することが目的ではないためやめました。

Slackを準備

プライベート用のSlackワークスペースを使用しました。

Raspberry Pi OSのセットアップ

構築時点で最新のRaspberry Pi OSをインストールしました。

以下のパッケージをインストール

  • nvm
    • Node.jsのバージョン管理ツールです。Hubotを動かすためにはNodo.jsが必要です。直接Node.jsをインストールしてもよいのですが、後々バージョンを切り替えたくなった際に面倒なので、初めからこちらを経由して最新のバージョンをインストールしました。
  • Git
  • Hubot
    • 公式サイトや導入記事などを参考にセットアップしました。
  • pigpio
    • PythonでRaspberry PiのGPIOを制御するためのモジュールです。今回インストールしたRaspberry Pi OSには既にインストールされていたため、有効化するだけで済みました。

電子回路の作成

回路を作成する際、Raspberry Piの電源はOFFにしておきます。

起動中に配線を行うと回路や本体が故障する恐れがあるためです。

こんな感じで作成しました。

赤外線の送受信と信号データの作成

今回はエアコンの停止と起動(冷房)の信号を記録したいと思います。

赤外線リモコン受信モジュールに対してリモコンから発信される赤外線を照射することで、信号データを記録することができます。

(補足)信号データとは、赤外線LEDの点滅パターンの記録です。信号受信側は、送信側から照射された赤外線LEDの点滅パターンを電気信号に変換し、その電気信号を読み取ることで機器の制御が行われています。

irrp.pyと呼ばれる、pigpioの作者が作成された赤外線送受信スクリプトを使用します。こちらのページからダウンロード可能です。

まずはエアコンの停止を記録するため、以下のコマンドを入力します。

python3 irrp.py -r -g14 -f aircon_stop aircon_stop --no-confirm --post 130

すると、以下のように赤外線受信待機状態に入ります。

この時に受信モジュールに向かってリモコンの停止ボタンを押して赤外線を照射すると赤外線信号データを記録することができます。

記録に成功した場合は、スクリプトが配置されているディレクトリと同じ場所に信号データが記録されたファイルが作成されます。

以下のような情報が記録されていました。

この信号データファイルを使用し、以下のコマンドを実行することで、リモコンを使わずにRaspberry Piからエアコンを停止することができるようになりました。

python3 irrp.py -p -g15 -f aircon_stop aircon_stop

同様に、エアコンの起動(冷房)の信号データを作成します。

Hubot 用スクリプトの作成

以下のディレクトリに JavaScript プログラムを配置することで、Slack から Hubot を呼び出した際に配置したプログラムが実行されるようになります。

今回作成したプログラムは以下のとおりです。

※一部のパラメータはマスキングしています。

// 外部コマンドを実行するためのモジュール
const child_process = require('child_process')
// 呼び出しを許可するユーザのメンバーID
const USER_ID_LIST = ['xxxxxxxx']

// エアコン操作関数
aircon = msg => {
  let command = ''
  switch (msg.match[1]) {
    case '冷房':
      command = 'python3 irrp.py -p -g15 -f aircon_start aircon_start'
      break

    case '停止':
      command = 'python3 irrp.py -p -g15 -f aircon_stop aircon_stop'
      break

    default:
      msg.send(`
      ${msg.match[1]} という機能は存在しません。実行可能な機能は以下の通りです。\\n
      エアコン [機能名]\\n
      機能名:冷房、停止 のいずれか
      `)
      break
  }

  if (command === '') {
    return
  }

  child_process.exec(command, (error, stdout, stderr) => {
    if (error) {
      msg.send(`コマンドの実行に失敗しました。\\nエラー内容:${error}`)
      return
    }
    msg.send(`エアコンの ${msg.match[1]} を実行しました。`)
    return
  })
}

canExecuteCommand = msg => {
  if (!USER_ID_LIST.includes(msg.envelope.user.id)) {
    msg.send('権限がないためコマンドを実行できません。')
    return false
  }
  return true
}

module.exports = robot => {
  robot.respond(/エアコン\\s(.*)/i, msg => {
    if (canExecuteCommand(msg) === false) {
      return
    }
    aircon(msg)
  })
}

上記のプログラムを、Hubotをインストールしたディレクトリ内のscriptsディレクトリに配置します。

このプログラムは、Hubot に特定のメッセージを送信した際に次のような動作をします。

  • Hubot に「エアコン 起動」とメッセージを送信 → エアコン起動(冷房)用の赤外線 LED を発信
  • Hubot に「エアコン 停止」とメッセージを送信 → エアコン停止用の赤外線 LED を発信

これで、SlackとRaspberry Piを連携することができました。

結果


Hubotにメッセージを送信することで、エアコンを操作することができるようになりました。

実際に動作させている様子

今回はエアコンの起動、停止を実装しましたが、他にも様々な応用が可能だと思います。

例えば、現在の気温を返したり、照明のON/OFFをしたりなど…

つまずいた点


赤外線を記録する際、受信モジュールに何も照射していないにも関わらず、謎の信号データが記録されてしまう問題が発生しました。

原因は、Raspberry Piに付いているアクセスLEDと受信モジュールが近い位置にあったことでした。

普通のLEDどころか、どんな物体からも赤外線は放射されているため、それに反応していたようです。

光源となる物を出来るだけ遠ざけることで正しく受信できるようになりました。

気付いたことや所感


  • 抵抗値の計算をしようとした時に、簡単な一次方程式の解き方を忘れていることに気が付きました…
  • Switchbot製品を使えば一撃解決ということは記憶から一時的に消去して、個人的に面白そうだったのであえて実施した取り組みだったのでした。

記事の内容は以上となります。
最後までお読みいただきありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です