定型アクションによる自動チャンネル変更は節が変わる度に定型アクションのメンテナンスが必要でした。年間放送スケジュールは決まっているため、これを使ってチャンネルを変更する方法を考えてみました。 リモコンを自動化するNature RemoはAlexaと連携するだけではなく、Nature APIと呼ばれるHTTP通信でのリモコン機能も提供しています。これにより、個人が独自に作成したプログラムからNature Remoを制御できます。
Nature Developer Page https://developer.nature.global/
チャンネル変更のテスト
まず、Nature APIでチャンネルを変更するテストをしてみました。 以下のページを参考にしました。
Nature Remo を Python から操作する https://qiita.com/morinokami/items/6eb2ac6bed48d2c7534b
テスト環境はWindows10+VisualStudioCodeにしました。Pythonも含め、既に過去にインストールしていたからです。Pythonがインストールされていればどの環境でも問題ないと思われます。 とりあえず、PythonのNatureRemoライブラリをインストールしました。
>pip install -U nature-remo -Uオプションは、指定されたすべてのパッケージを、利用可能な最新バージョンにアップグレードするという意味のようです。
Nature APIを使用するには以下のサイトでアクセストークンと呼ばれるIDを取得しなければなりません。 https://home.nature.global/ アクセストークンは取得したときの画面でしか確認することができず、後で見ることができないので注意してください。画面に表示された文字列をコピーして保存しておきます。
リモコン操作を行うには、アクセストークンの他にもAppliance IDと呼ばれる家電IDも必要です。家電IDを取得するテストプログラムは以下のようになります。
Test1.py
from remo import NatureRemoAPI
api = NatureRemoAPI('XXXXXXXXX')
appliances = api.get_appliances()
print(appliances)
XXXXXXXXXの部分はNatureのWebサイトで取得したアクセストークンになります。使用したNatureRemoライブラリはHTTP通信が隠蔽されていて、とても簡単に使用できます。 テストプログラムを実行し、成功するとJSON文字列が出力されます。これをJSONを見やすくしてくれるサイトで整形します。 https://json.onl.jp/
得られた結果からテレビのAppliance IDを探し、メモします。我が家の場合、照明、エアコンの下にテレビの記載がありました。
また、必要なボタン名(name=で示される)もメモしておきます。本当はシーンを直接指定したかったのですが、私はNatureAPIからシーンを取得することはできませんでした。
上記で得られた情報でチャンネルを切り替えるテストプログラムです。 GAORA sports(CS254)に切り替えます。 ご自身で取得したアクセストークンとAppliance ID、ボタン名をコピーして実行してください。 チャンネルの切り替え操作はご自分のテレビの操作に合わせたプログラムにしてください。 Test2.py
from remo import NatureRemoAPI
access_token = '-----アクセストークン-----'
appliancees_id = '-----Appliance ID-----'
bs_button = 'input-bs'
cs_button = 'input-cs'
down_button = 'down'
ok_button = 'ok'
s_button = 'submenu'
ch1_button = 'ch-1'
ch2_button = 'ch-2'
ch3_button = 'ch-3'
ch4_button = 'ch-4'
ch5_button = 'ch-5'
ch6_button = 'ch-6'
ch7_button = 'ch-7'
ch8_button = 'ch-8'
ch9_button = 'ch-9'
ch0_button = 'ch-10'
api = NatureRemoAPI(access_token)
api.send_tv_infrared_signal(appliancees_id, cs_button)
api.send_tv_infrared_signal(appliancees_id, s_button)
api.send_tv_infrared_signal(appliancees_id, down_button)
api.send_tv_infrared_signal(appliancees_id, down_button)
api.send_tv_infrared_signal(appliancees_id, ok_button)
api.send_tv_infrared_signal(appliancees_id, ch2_button)
api.send_tv_infrared_signal(appliancees_id, ch5_button)
api.send_tv_infrared_signal(appliancees_id, ch4_button)
チャンネルが切り替わったでしょうか? 注意点があります。NatureRemoAPIは5分間に30回の使用制限があります。上記の場合は1回のチャンネル切り替えに8回の送信を行っていますので、連続して行うと3回までしか成功しません。4回目の途中でエラーになってしまいます。
次にその日のチャンネルを取得する方法です。Pythonのpandasというライブラリを使用すればExcelファイルを操作できるという事で、Excelに情報を格納することにしました。
その日のチャンネルを取得し、変更するプログラム
まず、以下のようなExcelファイルを作りました。月ごとにシートを作りました。 曜日、対戦相手はプログラムでは使いませんが、見やすくするために項目を作りました。ミスなく入力できるように、対戦相手とチャンネルは[channel]シート、[team]シートで定義したリストから選択するようにしています。 曜日は1日の曜日を入力後、ドラッグすれば以下の曜日が入ります。
[channel]シートにはチャンネル名とチャンネルへのリモコン操作も定義しました。ボタン操作数も汎用性を持たせるために定義しておきました。
Excelファイルはダウンロードできるようにしておきました。FightersCh.xlsxというファイル名です。
このExcelファイルを読み込み、チャンネルを変更するPythonプログラムは以下のようになりました。 BaseballCh.py
import pandas as pd
import openpyxl
import datetime
from remo import NatureRemoAPI
excel_file = './FightersCh.xlsx'
access_token = '-----アクセストークン-----'
appliancees_id = '-----Appliance ID-----'
bs_button = 'input-bs'
cs_button = 'input-cs'
down_button = 'down'
ok_button = 'ok'
s_button = 'submenu'
ch1_button = 'ch-1'
ch2_button = 'ch-2'
ch3_button = 'ch-3'
ch4_button = 'ch-4'
ch5_button = 'ch-5'
ch6_button = 'ch-6'
ch7_button = 'ch-7'
ch8_button = 'ch-8'
ch9_button = 'ch-9'
ch0_button = 'ch-10'
# 日付の取得
dt = datetime.datetime.today()
month = dt.month
day = dt.day
# 今日のチャンネルの取得
openpyxl.reader.excel.warnings.simplefilter('ignore')
df = pd.read_excel(excel_file, sheet_name=str(month))
ch = df.iloc[day-1, 3]
if ch == ch:
# チャンネルあり、チャンネル名の操作取得
df_ch = pd.read_excel(excel_file, sheet_name=str('channel'))
for row in range(len(df_ch)):
if ch == df_ch.iloc[row, 1]:
# chの操作数取得
num = df_ch.iloc[row, 2]
# Nature Remoオブジェクトの取得
api = NatureRemoAPI(access_token)
# 操作数でループ
for i in range(num):
# ボタン操作を送信
button = str(df_ch.iloc[row, 3+i]).upper()
if button == 'BS':
api.send_tv_infrared_signal(appliancees_id, bs_button)
elif button == 'CS':
api.send_tv_infrared_signal(appliancees_id, cs_button)
elif button == 'S':
api.send_tv_infrared_signal(appliancees_id, s_button)
elif button == 'DOWN':
api.send_tv_infrared_signal(appliancees_id, down_button)
elif button == 'OK':
api.send_tv_infrared_signal(appliancees_id, ok_button)
elif button == '0':
api.send_tv_infrared_signal(appliancees_id, ch0_button)
elif button == '1':
api.send_tv_infrared_signal(appliancees_id, ch1_button)
elif button == '2':
api.send_tv_infrared_signal(appliancees_id, ch2_button)
elif button == '3':
api.send_tv_infrared_signal(appliancees_id, ch3_button)
elif button == '4':
api.send_tv_infrared_signal(appliancees_id, ch4_button)
elif button == '5':
api.send_tv_infrared_signal(appliancees_id, ch5_button)
elif button == '6':
api.send_tv_infrared_signal(appliancees_id, ch6_button)
elif button == '7':
api.send_tv_infrared_signal(appliancees_id, ch7_button)
elif button == '8':
api.send_tv_infrared_signal(appliancees_id, ch8_button)
elif button == '9':
api.send_tv_infrared_signal(appliancees_id, ch9_button)
break
今月の月のシートを開き、今日のチャンネル名を取得します。 チャンネルがあればチャンネルシートで該当するチャンネルの行を見つけ、その行の操作数と操作を取得し、ボタン操作を送信します。 このプログラムを動作させるために、追加でpandas,numpy,openpyxlをインストールする必要があります。
>pip install pandas >pip install numpy >pip install openpyxl
このプログラムの場合BaseballCh.pyとFightersCh.xlsxは同じディレクトリになければなりません。 プログラムを実行させ、意図通りに機能することを確認します。
AlexaとPythonプログラムをNode-Redで繋げる1
AlexaとPythonプログラムを連携させるためにNode-REDを使います。 以前、以下のページを見たときは衝撃的でした。これに従って進めます。
WM×LI: Amazon Echo と Raspberry Pi を Node-RED Alexa Home Skill Bridge で連携させて声でパソコンを起動したりシャットダウンしたりする. https://nort-wmli.blogspot.com/2018/11/amazon-echo-raspberry-pi-node-red-alexa.html
以下のURLでNode-REDアカウントを作成し、デバイスを作成します。 Login or RegisterのRegisterでアカウントを作成してから、Loginします。 https://alexa-node-red.bm.hardill.me.uk/
Add Deviceを押下し、デバイスを追加します。 名前と動作を入力します。 今回は居間にある玄関カメラモニター用のラズパイでPythonプログラムを作動させる予定なのでRaspberryPiLivingという名前にしてみました。 ActionsはOnにしかチェックしませんでした。 Application Typeはよくわかりませんが、ACTIVITYにしてみました。 OKを選択し、デバイスを追加します。
次にNode-REDスキルを有効にして作成したデバイスを検出します。 スマホのAlexaアプリを起動して、「その他」-「スキル・ゲーム」-「検索」でNode-REDを検索します。
Node-REDを選択し、有効にします。
Node-REDのページで登録したユーザー名とパスワードを入力します。
正常にリンクができたことを確認し、閉じるボタンを押下します。
「端末の検出」を選択します。
シーンとしてデバイスが検出されたようです。「完了」を押します。 (2022/08/02追記) Application TypeをACTIVITYにしたためにシーンとして検出されたようです。 それ以外だとデバイスとして検出されます。
Alexaアプリの「デバイス」-「シーン」で確認すると、作成したデバイス「RaspberryPiLiving」が追加されたのが確認できました。
ラズベリーパイにNode-REDをインストール
ラズベリーパイにNode-REDをインストールします。 最初は以前セットアップした防犯カメラモニター用のラズベリーパイにNode-REDだけをインストールしようとしましたが、OSの再インストールからすることにしました。 (私の理解力が無く、最新のOSをインストールしないと実現できないと思ってしまったのです。)
Raspberry PiのホームページからRaspberry Pi Imagerをダウンロードし、インストールします。最新のOSをインストールするために最新のImagerをインストールします。 https://www.raspberrypi.com/software/ ImagerでDesktop(Recommended)を選択し、イメージをSDに書き込みます。
書き込んだSDをRaspberryPiにセットし電源を入れます。 画面の指示に従い、国設定、ユーザー/パスワード設定、画面ブランク設定、Wifi設定、Softwareアップデートを行い、再起動を行います。(スクリーンショットが撮れませんでした) メインメニューから「設定」-「Raspberry Piの設定」を選択し、インターフェースタブでSSHを有効にします。(有効にしないとftpが使えません)
メインメニューから「設定」-「Recommanded Software」を選択し、「Programming」カテゴリのNode-REDにチェックを入れ、「Apply」ボタンを押下します。 ダウンロードとインストールが始まり、成功したら「Installation complete」と表示されます。
ターミナルを開き、Node-REDの自動起動を有効にして、Node-REDを起動します。$ sudo systemctl enable nodered $ sudo systemctl start nodered
AlexaとPythonプログラムをNode-Redで繋げる2
ブラウザを起動し、http://xxx.xxx.xxx.xxx:1880を開きます。xxx.xxx.xxx.xxxはラズベリーパイのIPアドレスです。ラズベリーパイでも別のPCからでも構いません。
画面右上の三本線をクリックし、「パレットの管理」を選択します。 「ノードを追加」を選択して,「alexa-home-skill」と入力します。 「no-red-contrib-alexa-home-skill」が表示されたら「ノードを追加」ボタンを押下します。
「追加」ボタンを押下します。追加されたら「閉じる」ボタンでパレットの管理画面を閉じます。
画面左側のパレットの下にalexaが追加されます。
パレットから「alexa-home」と「debug」をフロー図に配置し、繋げます。 「debug」ノードは配置すると「msg.payload」の表示に変わってしまいました。 通信内容を表示する、という意味なのでしょう。
「Alexa Home」ノードをクリックします。Acount横の鉛筆アイコンをクリックします。
Node-REDのユーザー名とパスワードを入力し、「追加」ボタンを押下します。
DeviceにNode-REDのページで作成したデバイスを選択し、「完了」を押します。
Alexa Homeノードがデバイス名の表示に変わります。
右上の「デプロイ」ボタンを押下して設定内容を送信します。
テストしてみます。 スマホのAlexaアプリで「その他」-「定型アクション」で定型アクションを追加します。 「アクションを追加」を押下し、「スマートホーム」-「シーンをコントロール」と選択していき、デバイス「RaspberryPiLiving」を選択します。確認画面で「追加」を押します。
画面右上の虫アイコンを選択し、デバッグウインドウを表示します。 定型アクションを実行すると、デバッグウインドウにメッセージが表示されます。 AlexaとNode-REDが繋がったことが確認できました。
AlexaとPythonプログラムをNode-Redで繋げる3
次にRaspberryPiのPythonプログラムを転送します。 ftpアプリでBaseballCh.pyとFightersCh.xlsxを転送します。 ftpはバイナリモードになっていることを確認してください。テキストモードで転送するとファイルが壊れます。 転送先は適切なディレクトリを選択すべきですが、ここでは仮に/home/pi/にしておきます。
ターミナルで必要なPythonライブラリのpandas、numpy、openpyxl、NatureRemoAPIをインストールします$ pip install -U pandas $ pip install -U numpy $ pip install -U openpyxl $ pip install -U nature-remo
ここで転送したプログラムを起動してみます。$ python BaseballCh.py すると次のようなエラーが発生しました。
IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!
Importing the numpy C-extensions failed. This error can happen for
many reasons, often due to issues with your setup or how NumPy was
installed.
We have compiled some common reasons and troubleshooting tips at:
https://numpy.org/devdocs/user/troubleshooting-importerror.html
Please note and check the following:
* The Python version is: Python3.9 from "/usr/bin/python"
* The NumPy version is: "1.22.4"
and make sure that they are the versions you expect.
Please carefully study the documentation linked above for further help.
Original error was: libcblas.so.3: cannot open shared object file: No such file or directory
エラーメッセージ示されたページで確認すると、libatlas-base-devをインストールするか、numpyをアンインストールし、python3-numpyをインストールしてみろ、とのことでした。
指示通りlibatlas-base-devをインストールしたところ、エラーなく動作するようになりました。$ sudo apt install libatlas-base-dev
Node-REDに戻り、debugノードを削除して代わりに「exec」ノードを配置、接続します。 「exec」ノードをクリックします。
コマンドに「python /home/pi/BaseballCh.py」、名前に「チャンネル変更」と入力し、「完了」ボタンを押下します。
「デプロイ」ボタンでフローを送信します。
最後に「日ハムの試合にして」という定型アクションを変更します。チャンネルのシーンを削除し、Node-REDデバイスを追加します。これで作成完了です。
『アレクサ、日ハムの試合にして』と言うと北海道日本ハムファイターズを放送するチャンネルに切り替わるはずです。
課題
節の変わり目でいちいちメンテナンスする必要がないようにシステムを変更する事が出来ました。しかし、不満な点があります。
1)常に稼働するコンピュータが必要である。 自分の場合は防犯カメラで24時間稼働中のラズパイがありそれを使用しましたが、ない場合はこれだけのために稼働させることになるため、スマートな感じがしないです。 Alexaスキルを作成できれば解決するかもしれません。
2)NatureAPIの回数制限に引っかかりやすい。 1回のチャンネル変更に8回のNatureRemoサーバーとの通信が発生するので、5分間30回の制限に到達しやすいです。実際使用する上では1日1回程度しか使わないので規制に引っかかることは少ないと思いますが、昼間だと赤外線が通りにくいときがあり、何回も言ってしまうことがあるかもしれません。デバッグの時は動作確認が捗りませんでした。Nature Remoのサーバーをタダで使わせてもらっているので、制限自体は理解できます。もっと制限を緩くしてとは思いません。 解決策としては以下が思い浮かびます a.シーン指定をできる仕組みがあれば、1回の通信で済むので回数制限を意識することは殆どなくなると思います。 b.Nature RemoのLocal APIを使えればクラウドサーバーを経由せず、LAN内で完結するので回数制限と関係なくなります。NatureRemoサーバーがダウンしていても使えるという利点もあります。
3)雨天順延等のスケジュール変更に手間がかかる。 雨天順延でスケジュールが変更になった場合、Excelファイルを修正し、それをラズベリーパイにアップロードします。これは定型アクションでチャンネル操作をまとめたシーンを指定するやり方と比べ、手間がかかります。注意してExcelファイルを作成したつもりでも間違っている心配もあります。
4)家にいないと、メンテナンスできない ExcelファイルのアップロードはLAN内でしかできないため、家に不在のときは作業を行うことができません。発端は機械音痴の家族のためのシステムなので、これは片手落ちと言っても過言ではないかもしれません。 ただ、この場合は定型アクションで追加するアクションを一時的にNode-REDデバイスからチャンネルのシーン指定に戻すことで解決します。やはり、シンプル・イズ・ベスト。単純な方が良いシステムなのだと思わさります。