見出し画像

ラズパイをスマートホーム的運用③

https://note.com/tori29umai/n/n6f1d1d062dc1

https://note.com/tori29umai/n/n41fd2c94a99c

【追記】投稿5分後に気付いたのですが最初に公開したコードではmp3を止められませんでした。なのでTwitterのフォロワーてんななさんのご指導の下、書き直した改稿版を公開しておきます。

前回で終わるといったな。アレは嘘だ。
というわけでラズパイのSDカード以下に入っているmp3(サブディレクトリ込み)をランダムに選んでGoogleHomeで再生するスクリプトを書きました。
前提条件はいろいろあるのですが上記の記事二つを読んでいる前提で書きます。

①ラズパイをローカルwebサーバーにする

こちら参照。USBの中身をサーバー上に置きたいので
/var/www/html/以下にUSBメモリのシンボリックリンクを張る必要があります。やり方は以下。

自分は/mnt/usbmemという名前でマウントしたUSBを/var/www/html/usbという名前のシンボリックリンクで同期しています。
【追記:部屋片づけしていたら128GBのsdカードみつけたのでそっちにラズパイをインストールして直接/var/www/html/usbにmp3を置きました】

②Pythonスクリプトを書く

Googlehomeからmp3再生するのにpychromecast使うのでパッケージをインストールする

pip install pychromecast

以下のスクリプトを用意する。
/home/pi/google-home-player/mp3Play.py

# conding: utf-8
import subprocess
import time
import random
import urllib.parse
import glob
import pychromecast

#mp3を選択して再生する
def PlayMusic():
	# Chromecastデバイス名で検索する
	chromecasts, browser = pychromecast.get_listed_chromecasts(friendly_names=["MyRoom"])
	# castデバイスが見つからない場合、終了
	if len(chromecasts) == 0:
		print("Google Homeが見つかりません")

    # 最初に見つかったもの(同名のデバイスが複数あった場合)
	googleHome = chromecasts[0]

	# 喋らせる
	googleHome.wait()
	mc = googleHome.media_controller

   	# 他の音楽を再生中の場合
	if mc.status.player_is_playing:
		print("Music is running. Stop music.")
		mc.stop()
		mc.block_until_active(timeout=30)
		
	mp3_list = get_file_list()
	mp3_random = random.sample(mp3_list , len(mp3_list))
	play_list = get_play_list(mp3_random)
	
	mc.play_media(play_list[0], "audio/mp3")

	# Wait for Chromecast to start playing
	while mc.status.player_state != "PLAYING":
		time.sleep(0.1)
	
	#Queue next items
	for URL in play_list[1:]:
		mc.play_media(URL, "audio/mp3", enqueue=True)

#dir_path以下からmp3を無作為に抽出する関数
dir_path = "/var/www/html/usb/"	# webサーバーのパス
ip = "192.168.1.10"	# ラズパイのIPのIPアドレスを入力
def get_play_list(mp3_list):
	url_list = []
	for URL in mp3_list:
		url_list.append(URLenc(URL))
	return url_list

def get_file_list():
	files1 = glob.glob(dir_path + "**/*.mp3")
	files2 = glob.glob(dir_path + "**/**/*.mp3")
	return files1 + files2

#ファイルURL生成
def URLenc(mp3_list):
	#ファイルURL生成
	encfilePath = urllib.parse.quote(mp3_list)
	URL = encfilePath.replace( "/var/www/html", "http://" + ip )
	return URL

③スクリプトをIFTTTと連携させる。

前回の記事を参照。
IFTTTのBody部分は以下の内容にしてください。
【mp3をオンにする】

{"data":[{"comand":"PlayMusic"}]}

【照明を操作する】

{"data":[{"comand":"Light_Ctl"}]}

前回の記事で作ったhomeauto.pyも弄る必要があったので以下のように改変。
/home/pi/google-home-player/homeauto.py

# conding: utf-8
import paho.mqtt.client as mqtt
import json
import subprocess
import mp3Play
import Light_Ctl

TOKEN = "token_XXXXXXXXXXXXXXX"
HOSTNAME = "mqtt.beebotte.com"
PORT = 8883
TOPIC = "RaspberryPi/SmartRemocon"
CACERT = "/home/pi/google-home-player/mqtt.beebotte.com.pem"

def on_connect(client, userdata, flags, respons_code):
    print('status {0}'.format(respons_code))
    client.subscribe(TOPIC)

def on_message(client, userdata, msg):
	data = json.loads(msg.payload.decode("utf-8"))["data"][0]
	cmd = data["comand"]
	if cmd == "PlayMusic":
		mp3Play.PlayMusic()
	elif cmd == "Light_Ctl":
		Light_Ctl.Light_ONOFF()

client = mqtt.Client()
client.username_pw_set("token:%s"%TOKEN)
client.on_connect = on_connect
client.on_message = on_message
client.tls_set(CACERT)
client.connect(HOSTNAME, port=PORT, keepalive=60)
client.loop_forever()

homeauto.pyの改変に伴い、前回書いたLight_Ctl.pyも改変
/home/pi/google-home-player/Light_Ctl.py

import subprocess
import cgsensor
import time
from datetime import datetime
from zoneinfo import ZoneInfo
import cgir

def Light_ONOFF():
	#-------------------------------------------
	# 何時から
	StartTime = 5
	# 何時まで
	EndTime = 10
	#照明の切り替わり時間(秒数)
	ONOFFtime = 3
	#-------------------------------------------
	tsl2572 = cgsensor.TSL2572()  # TSL2572制御クラスのインスタンス

	#照明のON/OFF信号を送る
	subprocess.run(['cgir', 'send', 'Lite'])

	#照明の切り替わり時間分待機
	time.sleep(ONOFFtime)

	#もしStartTime~EndTimeの時間帯であれば
	if (datetime.now(ZoneInfo("Asia/Tokyo")).hour in range(StartTime, EndTime, 1)):
		#部屋の明るさを測る
		tsl2572.single_auto_measure()
		#部屋が明るければ
		if(tsl2572.illuminance > 100):
			#GoogleHomeが朝の挨拶をする
			subprocess.run(['/usr/local/bin/node' , '/home/pi/google-home-player/GoogleCalendar.js']) 

IFTTTの設定画面のBody部分は以下のように書く必要があります。
【照明の操作】

{"data":[{"comand":"Light_Ctl"}]}

【mp3の操作】

{"data":[{"comand":"PlayMusic"}]}
↑の欄にいれるやつ

mp3を消すのは「OK、Google、静かにして」で大丈夫そうです。
これでとりあえず、
・OKGoogle、部屋の電気つけて(消して)
・OKGoogle、mp3つけて
・OK、Google、静かにして

で制御できるようになりました。
この書き方だとディスク中のmp3を再生し終わったら止まってしまうのですが、まぁ1000曲以上あるので杞憂でしょう。
なんか非同期処理?にするといい感じになるらしいですがわからないのでこうなりました。

ラズパイを再起動したときは

cd /home/pi/google-home-player
python /home/pi/google-home-player/homeauto.py

を起動したら上記のキーワードで制御できます。

おまけ

ラズパイを掘り出して遊んでいたら、いつぞやの記事で遊んだラズパイZweoWHがでてきたのでこれも活用できるなと思ってこんなものを作りました。

トイレに設置

いうてこっちは以下のコードを丸パクリしただけなので割愛。
フレームはダイソーの写真立ててです。結構様になっているのでは!?と時間自賛しています。
https://www.avancesys.co.jp/laboratory/article/%E9%9B%BB%E5%AD%90%E3%83%9A%E3%83%BC%E3%83%91%E3%83%BC%E3%81%A8%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%81%A7%E8%87%AA%E5%8B%95%E6%9B%B4%E6%96%B0%E3%81%99%E3%82%8B%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5/

この記事が気に入ったらサポートをしてみませんか?