【IoT】irMagicianとラズパイで、Twitter経由でエアコンを操作する!

2018/03/18

IT/IoT

ツイッターのbot経由でエアコンを操作する

いよいよ、実用的な部分に入っていきます!

ツイッターには様々なAPIがありますが、大きく2種類に分けて考えることができます。ひとつは、任意のタイミングで情報をもらいに行く「REST」型。もうひとつが、接続しっぱなしでリアルタイムに情報をもらう「Stream」型です。

今回はStream型の中でもユーザー情報などに特化した「User Stream」というAPIを使用しました。接続にはPythonを使います。

※2018年の6月あたりにこのAPIは廃止になるようです。「Account Activity API」というのが替わりに新しく出るらしいのですが、情報がまだ少ないので今回は「User Stream」を使用しました。

まずbotアカウントを作る

bot用のアカウントを作成します。APIを使用するので、電話番号の登録が必要です。

今回作ったアカウントはこちら。@saki_bot_pi(さきのラズパイ)

Appを登録し、各種キー等を用意する

Twitter Appsにアクセスして、Appを登録します。Appは、botのアカウントで登録する必要があります。本アカウントとごちゃごちゃになるとややこしいので、ブラウザのシークレットモード等で作業すると安全です。

WebSiteは今回無いので、プレースホルダーを入力。hogehoge.comにしました。

登録できたら、Appの画面が開きます。タブが4つ程あって、「Details」が選択されているはずです。「Permissions」タブを開いて、「Read and Write」が選択されていることを確認します。選択されてなかったら「Read and Write」を選択して、設定を更新して下さい。

次に、「Keys and Access Tokens」タブを開きます。「Consumer Key (API Key)」と「Consumer Secret (API Secret)」をメモしておきましょう。さらに画面下の方にいくと、「Token」と書かれた部分がありますので、Tokenを作成します。Tokenが作られると「Access Token」、「Access Token Secret」が書かれているので、これらもメモします。

ここでメモした4つの情報は、とても大切な情報です。人に見られないように、教えないようにしましょう。

Pythonプログラムを書く

まず、Twitter用のPythonライブラリを入手します。導入はとても簡単で、以下のコマンドで導入できます!

Copy
                                            
                                                $ pip install twitter
                                            
                                        

説明等に関しては、こちらに詳しく載ってます。
twitter 1.18.0

Twitterライブラリを入手したら、いよいよ中身を書いていきます。先に完成品を見せてしまいますね!

Copy
                                            
                                                ファイル名:tw.py
                                                #coding:UTF-8
                                                import twitter
                                                import subprocess
                                                #authの中身は、メモしたキー等の情報を入力して下さい。
                                                auth = twitter.OAuth(
                                                	consumer_key="",
                                                	consumer_secret="",
                                                	token="",
                                                	token_secret=""
                                                )
                                                new_tw = twitter.Twitter(auth=auth)
                                                twitter_userstream = twitter.TwitterStream(auth=auth, domain="userstream.twitter.com")
                                                for msg in twitter_userstream.user():
                                                	if 'in_reply_to_screen_name' in msg:
                                                		if msg['in_reply_to_screen_name'] == "saki_bot_pi":
                                                			if msg['user']['screen_name'] == "takamachi1saki":
                                                				text = msg['text'].encode('utf-8')
                                                				if "エアコン" in text:
                                                					if ("オン" in text or "つけて" in text):
                                                						res = subprocess.call(["python","/home/pi/irmcli/irmcli.py","-p","-f","air_on.json"])
                                                						if res == 0:
                                                							tweet = "@takamachi1saki はーい、つけたよー"
                                                						else:
                                                							tweet = "@takamachi1saki なんだか失敗しちゃったよー"
                                                					if ("オフ" in text or "消して" in text or "けして" in text):
                                                						res = subprocess.call(["python","/home/pi/irmcli/irmcli.py","-p","-f","air_off.json"])
                                                						if res == 0:
                                                							tweet = "@takamachi1saki はーい、消したよー"
                                                						else:
                                                							tweet = "@takamachi1saki なんだか失敗しちゃったよー"
                                                					else:
                                                						tweet = "@takamachi1saki 指示をうまく読み取れなかったよー。「エアコン」だけはわかった!"
                                                				else:
                                                					tweet = "@takamachi1saki 指示をうまく読み取れなかったよー"
                                                			else:
                                                				screen_name = msg['user']['screen_name'].encode('utf-8')
                                                				tweet = "@"+screen_name+" さきちゃんの言う事しか聞かないよー"
                                                			new_tw.statuses.update(status=tweet,in_reply_to_status_id=msg['id'])
                                            
                                        

こんな感じです。

私のアカウントからのみ操作可能

if文を駆使して、条件分岐しています。「takamachi1saki」が私のアカウントの「Screen Name」というものです。「@takamachi1saki」とか書いてあるアレです。プログラム上で扱う上では、「@」は要りません。

私のアカウントからのみ操作可能で、他のアカウントからリプライを飛ばしても、命令を拒否します!「takamachi1saki」の部分をご自分のScreen Nameに書き換えると、うまくいくかと思います。

また、私のアカウントからリプライを飛ばしても、特定の単語を含んでいない場合はエアコンを操作しません。具体的には、「エアコン」という単語を含み、さらに「オン、つけて」を含むと電源オン、「オフ、消して、けして」を含むと電源オフ、という具合になります。

res = subprocess.call(["~"])

Pythonからコマンドを実行するのに、「subprocess.call」を利用しました。subprocess.callは、コマンドを無事に実行できたら「0」を返してくれます!

res = subprocess.call~の部分がコマンド実行してる部分なのですが、「res」に「0」が返ってくるかどうかで、電源オンオフの信号を送信できたかどうか、という分岐が可能になります。

ここで実行しているコマンドは、1ページ目の動作テストで使用したコマンドと同じものです。ただ、書き方が少し特殊で、例えば

Copy
                                            
                                                $ abc -d -e
                                            
                                        

としたい時は、次のように書きます。

Copy
                                            
                                                subprocess.call(["abc","-d","-e"])
                                            
                                        
~.encode('utf-8')

ところどころに「encode('utf-8')」を使用していますが、これが無いと「UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0」というエラーが出てしまいました。

Unicodeをデコードする際、何でデコードしたらいいのかわからず、「ASCIIでデコードしようとしたけどこれASCIIじゃないからデコードできないよ」って怒られているようだったので、「UTF-8」でデコードをかけてみることに。

すると今度は「UnicodeEncodeError: 'ascii' codec can't encode characters in position 13-15」といったエラーが。調べてみると、PythonではUnicodeをUTF-8で日本語に戻す作業を「エンコード」としているようです。デコードじゃなかった。よって、「encode('utf-8')」を使用しています。

ファイルのパーミッションを変更

作成したPythonプログラム「tw.py」から「irmcli.py」をコマンドで呼び出しますが、実行権限を与えておきます。「irmcli.py」のパーミッションを「755」にしました。

また、リモコンの信号を記録したjsonファイルのパーミッションは、読み取り可能、「644」にしておきます。

作成したPythonプログラムを、バックグラウンドで動かす

作成したプログラムをコマンドで実行しますが、端末からログアウトすると動作が停止しちゃいます。

お手軽にバックグラウンドプロセス化する方法として、「nohup」と「&」をつけてコマンド実行する方法があります。以下のようなコマンドになります。

Copy
                                            
                                                nohup python /home/pi/tw.py&
                                            
                                        

これで、ログアウト後も作動します!

再起動しても自動起動、プロセス化したい場合、サービス登録する必要があります。そちらは今回この記事では触れません。

機器一式を、いい位置にセットする

せっかくデータのやりとりができても、赤外線LEDの光が届かないと意味がありません。棚や机の上など、いい位置を見つけて、そこにラズパイ、irMagicianをセッティングします。

これで、一通りの準備が整いました!!

botにお願いしてみる。

それでは、「さきのラズパイ」にツイッターでお願いしてみます。

エアコンをつけてくれました!!

まとめ

「」のアイキャッチ画像

「LoRaWANによるIoTハンズオンセミナー」に行きました!東京大学で行ったLT資料も公開!

こんにちは!さきです。1月5日に柏の葉IoTハッカソンの「LoRaWANによるIoTハンズオンセミナー」が行われました!場所は東京大学の本郷キャンパスでした!LoRaWANの通信の特徴や仕組みについて飛距離の計算方法や現在の実証実験結果も教えていただきました!「ラズパイでエアコンの操作」!なのでその発表を行いました

さきブログのアイコンsakiot.com
更新日:2018-01-26

こちらの記事でも少し書きましたが、私は以前にもラズパイからエアコン操作をやってみたことがあります。回路図を書いて、外付けで電池を用意して、と、赤外線関連の回路を組み立てるのでかなり大変でした。

今回、大宮技研さんの「irMagician」を使用してみて、かなり簡単にエアコン操作を行なうことができました!回路を作るのに使っていた労力をPythonに割くことができたので、前々からやりたかった「bot経由のエアコン操作」を実現することができて嬉しいです♪

エアコンに限らず、赤外線LEDを使用した家電はだいたいがirMagicianで操作可能です。操作方法も、ツイッター経由じゃなくてWebページ経由にしてもいいし、Androidであればアプリ化するのもいいかもしれませんね!

それではまたねー!!
さき

さきとラズパイとirMagician