作業中のメモ

よく「計算機」を使って作業をする.知らなかったことを中心にまとめるつもり.

音声認識による赤外線機器の操作 その 3【赤外線操作編】

どうも,筆者です.

音声認識も終わり,やっと赤外線操作ができる.ただし,ここで説明するのは,ADRSIR に向けた解説になるため,他の機器を使っている人は別サイトを参考にしてほしい.

以下のサイトを参考にさせていただいた.

Amazon Echoから赤外線リモコン機器(テレビ、照明など)をコントロールする(ラズベリー・パイ専用 学習リモコン基板 ADRSIRを使って) - Qiita

また,前回までの記事は以下にある.

workspacememory.hatenablog.com

前提

ここからは,プログラミングを行っていく.利用するライブラリが Python で書かれているため,Python を利用する.C 言語で開発しても良かったが,ライブラリを自分で作成するのは手間であるため,Python を利用することにした.

準備

まず,Raspberry Pi の電源を落とし,ADRSIR を GPIO ピンに接続する.利用するピンは決まっているため,他にも利用したいピンがある場合,ブレッドボードなどを用いて配線する. 筆者は,特に用途がなかった為,そのまま全部のピンを埋める形で接続した.

Raspberry Pi を起動後,以下のサイトから,「リモコンコードリスト(CSV)」をダウンロードする.また,有志の方が作成したライブラリを GitHub からダウンロードする.

ラズベリー・パイ専用学習リモコン基板

http://bit-trade-one.co.jp/support/download/

赤外線学習リモコン基板 ADRSIR 関連スクリプト

GitHub - you0708/adrsir: 赤外線学習リモコン基板 ADRSIR 関連スクリプト

# GitHub からダウンロードする
git clone https://github.com/you0708/adrsir.git

ダウンロードした「リモコンコードリスト(CSV)」は,adrsir に保存する.今後は,adrsir ディレクトリで作業する.

赤外線信号の作成

ADRSIR を利用して赤外線信号を登録する.ただ,筆者の環境の場合,テレビと電気は「リモコンコードリスト(CSV)」内にあったため,そのまま利用した.

ただ,どれがどれに対応するか分からなかったため,会社と対象機器の動作で grep をかけて,順番に試した.その手順を示す.ここでは,「ソニーのテレビ」を対象とする.また,「リモコンコードリスト(CSV)」は,「infrared_data_0171225.csv」という名前に変更して扱っている.

対象データの抽出

まず,ソニーのテレビに対し,対象機器の動作として,「電源」を抽出する.

~/adrsir  $ cat infrared_data_0171225.csv | grep "ソニー" | grep "デジタルテレビ" | grep "電源"
# === 出力結果 ===
# "ソニー","デジタルテレビ1","電源","..."
# "ソニー","デジタルテレビ2","電源","..."
# "ソニー","デジタルテレビ3","電源","..."

データをファイルへ書き込む

次に,抽出したリストから赤外線信号を取り出し,ファイルに保存する Shell Script を作成する.ここでのファイル名は createIrDataToFile.sh とした.

#!/bin/bash
# createIrDataToFile.sh

count=1
cat infrared_data_0171225.csv | grep "ソニー" | \
grep "デジタルテレビ" | grep "電源" | sed -e 's|"||g' | -e "s|,| |g" \
while read a b c d; do
    outName=machine${count}.dat
    echo ${b} "->" ${outName}
    echo ${d} > ${outName}
    count=$(expr ${count} \+ 1)
done

Python スクリプトの実行

後は,作成した Shell Script を実行し,生成されたファイルを順に Python スクリプトで実行する.以下に例を示す.

~/adrsir  $ chmod +x createIrDataToFile.sh
~/adrsir  $ ./createIrDataToFile.sh
~/adrsir  $ python3 ir_control.py send machine1.dat
~/adrsir  $ python3 ir_control.py send machine2.dat
~/adrsir  $ python3 ir_control.py send machine3.dat

筆者は実行も面倒だったため,createIrDataToFile.sh を exeIrData.sh として作成した.スクリプトの中身も以下のように変更した.

#!/bin/bash
# exeIrData.sh

corpName="ソニー"
machine="デジタルテレビ"
operation="電源"
outName=tmp.$$
cat infrared_data_0171225.csv | grep "${corpName}" | \
grep "${machine}" | grep "${operation}" | sed -e 's|"||g' | -e "s|,| |g" \
while read a b c d; do
    echo ${b} "->" ${outName}
    echo ${d} > ${outName}
    python3 ir_control.py send ${outName}
    sleep 3
done
rm -f ${outName}

JSON ファイルの生成

対象機器が分かれば,後は関連する信号をすべて出力すればよい.ただ,「ir_control.py」をそのまま利用するとファイル数が膨大になるため,JSON 形式でまとめることにした.

まず,「リモコンコードリスト(CSV)」から対象機器の信号一覧を取得する.ここでは,「ソニーのデジタルテレビ2」を利用する場合を考える.処理自体は難しくなく,grep コマンドで該当のものをすべて抽出すればよい.

cat infrared_data_0171225.csv | grep "ソニー" | grep "デジタルテレビ2" | sed -e 's|"||g' > ret.data

次に,抽出したデータをコマンドとして扱えるように名前を付ける.手間ではあるが,日本語をそのまま扱うのは後々辛そうであるため,ここで変換しておく.例えば,「電源」は「power」,「音量」は「volume」というように名前を付ける.

最後に,以下のような Python スクリプトを作成し,JSON 形式に変換する.ここで,スクリプト名は createJson.py とした.

スクリプト

#!/usr/bin/python3
#coding: utf-8

# createJson.py

import json
import sys, os

def createDictData(filename):
    listData = []
    for line in open(filename):
        data = line.replace('\n', '').split(',')
        listData.append((data[2], data[3]))
    return dict(listData)

if __name__ == "__main__":
    argv = sys.argv
    argc = len(argv)

    if argc < 2:
        print('Usage: {0} [infra red data file]'.format(argv[0]))
    else:
        filename = argv[1]
        rootName, _ = os.path.splitext(filename)
        dicData = createDictData(filename)
        with open(rootName + '.json', 'w') as fout:
            json.dump(dicData, fout)

変換方法

python3 createJson.py ret.data # ret.json が生成される

この JSON ファイルは,名前(power や volume)をキー(key)とし,赤外線信号を値(val)として持つ.Python で読み込めば,連想配列として利用できる.

赤外線信号の送信

JSON 形式で保存したファイルを用いて,赤外線を送信する.そのための Python スクリプトを以下に示す.ファイル名は irControl.py とした.

スクリプト

#!/usr/bin/python3
#coding: utf-8

# irControl.py

import adrsirlib
import sys, json

# ===============
# display command
# ===============
def display_list(jsonFile):
    try:
        with open(jsonFile, 'r') as fin:
            dictData = json.load(fin)
            print("print json file data")
            listData = [key for key, _ in dictData.items()]

            for i, key in enumerate(sorted(listData)):
                print("No.{0:03d}: {1}".format(i, key))
    except json.JSONDecodeError as e:
        print('JSONDecodeError: ', e)

# =====
# Usage
# =====
def usage():
    print("\nUsage: {0} <send|list> [json file] [options...]\n".format(__file__))
    print("  command")
    print("    send : send data to ADRSIR")
    print("        ex) {0} send [json file] [send command]".format(__file__))
    print("    list : print json file data")
    print("        ex) {0} list [json file] all".format(__file__))

# ===========
# execute cmd
# ===========
def executeCmd(jsonFile, cmd):
    retVal = 1

    try:
        with open(jsonFile, 'r') as fin:
            jsonData = json.load(fin)

            try:
                adrsirlib.write(jsonData[sendCmd])
                retVal = 0
            except:
                print('command not found')
    except json.JSONDecodeError as e:
        print('JSONDecodeError: ', e)

if __name__ == '__main__':
    argv = sys.argv
    argc = len(argv)

    if argc < 4:
        usage()
    else:
        command = argv[1]
        jsonFile = argv[2]

        if command == 'send':
            sendCmd = argv[3]
            executeCmd(jsonFile, sendCmd)

        elif command == 'list':
            display_list(jsonFile)
        else:
            usage()

実行方法

python3 irControl.py list ret.json all # コマンドの一覧表示
python3 irControl.py send ret.json power # 電源ボタンの赤外線信号を送信

以上で,赤外線機器の操作ができるようになった.後は,音声認識結果と組み合わせればよい.次回以降で,組み合わせ方を解説する.