2016年3月31日木曜日

irMagician と GrovePi でIoTリモコン - ブラウザ操作と音声認識によるリモコン操作 -


 ハードウェアは準備出来たので、色々と機能を載せていこうと思います。まずは、irMagician をブラウザから操作して家電のOn/Offをできるようにして、PCやVPN接続でスマホで外出先からの制御ができるようにしたいと思います。また、ブラウザ操作相当の操作を音声認識により実現したいと思います。
 この手の「Raspberry Piを学習リモコンにしてスマホ等で操作する」とか「音声認識学習リモコン」とかはすでによくやられていて、前例がたくさんあります。今回は、そういった有益な銃砲をネットに公開してくださっている先達の知恵に甘えます。参考にしたサイトを幾つか挙げておきます。感謝です。

 今回は python + tornado でサーバ側でpostを受け取って、irMagicianの json形式リモコン信号データを再生するプログラムをテスト的に作成しました。といっても、上記リンク先やネットに公開されていたコードをつなぎあわせただけですが。

# coding: utf-8
from __future__ import print_function
import os
import tornado.ioloop
import tornado.web
import sys
import serial
import time
import json
import argparse
here = os.path.abspath(os.path.dirname(__file__))
ir_serial = serial.Serial("/dev/ttyACM0", 9600, timeout = 1)
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
def post(self):
self.set_header("Content-Type", "text/plain")
btn = self.get_argument("btn")
self.write("You put" + btn)
if btn == '1' :
path = 'OHM_OCR-04_ON.json'
elif btn == '2' :
path = 'OHM_OCR-04_OFF.json'
elif btn == '3' :
path = 'Panasonic_AirConditioning_CS-E28K9_PowerOn.json'
elif btn == '4' :
path = 'Panasonic_AirConditioning_CS-E28K9_PowerOff.json'
playIR(path)
application = tornado.web.Application([
(r"/", MainHandler)
],
template_path = os.path.join(os.getcwd(), "templates"),
static_path = os.path.join(os.getcwd(), "static"),
)
def playIR(path):
if path and os.path.isfile(path):
sys.stdout.write("Playing IR with %s ..." % path)
f = open(path)
data = json.load(f)
f.close()
recNumber = len(data['data'])
rawX = data['data']
ir_serial.write("n,%d\r\n" % recNumber)
ir_serial.readline()
postScale = data['postscale']
ir_serial.write("k,%d\r\n" % postScale)
msg = ir_serial.readline()
sys.stdout.write(msg)
for n in range(recNumber):
bank = n / 64
pos = n % 64
if (pos == 0):
ir_serial.write("b,%d\r\n" % bank)
ir_serial.write("w,%d,%d\n\r" % (pos, rawX[n]))
ir_serial.write("p\r\n")
msg = ir_serial.readline()
else:
sys.stdout.write("Playing IR...")
ir_serial.write("p\r\n")
time.sleep(1.0)
msg = ir_serial.readline()
sys.stdout.write(msg)
if __name__ == "__main__":
application.listen(8888)
sys.stdout.write("Server is up ...")
tornado.ioloop.IOLoop.instance().start()
 部屋の照明のリモコンとエアコンのそれぞれのOn/Off信号のjsonファイルを下記のHTML(ブラウザ)側からpostされてくる 1 or 2 ・・の文字で判定してハードコーディングで処理しています。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>HomeMadePi リモコン</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script type="text/javascript">
function func_submit(value)
{
var form = document.createElement('form');
document.body.appendChild(form);
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', 'btn');
input.setAttribute('value', value);
form.appendChild(input);
form.setAttribute('method', 'post');
form.submit();
}
</script>
</head>
<body>
<section id="page1" data-role="page">
<header data-role="header"><h1>HomeMadePi IR</h1></header>
<div class="content" data-role="content">
<input type="submit" name="btn" value="照明 ON" onclick="func_submit(1);" />
<input type="submit" name="btn" value="照明 OFF" onclick="func_submit(2);" />
<input type="submit" name="btn" value="エアコン ON" onclick="func_submit(3);" />
<input type="submit" name="btn" value="エアコン OFF" onclick="func_submit(4);" />
</div>
<footer data-role="footer"><h1>irMagician with GrovePi</h1></footer>
</section>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
 スマートフォンでGrovePiにアクセスすると、次のような画面で操作できます。


 また、julius 音声認識をモジュールモードで動かして、julius 側ポート 10500 とソケット通信で音声認識結果を受け取って、ブラウザページでの操作に相当するpostを送信するような以下のプログラムも走らせます。なお、juliusには認識してい欲しい言葉だけの辞書セットを作っています。

# -*- coding: utf-8 -*-
import socket
import requests
host = 'http://localhost:8888/'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 10500))
sf = s.makefile('rb')
while True:
line = sf.readline().decode('utf-8')
if line.find('WHYPO') != -1:
print line
if line.find(u'パイ電気つけて') != -1:
r = requests.post(host, {'btn' : '1'})
elif line.find(u'パイ電気オン') != -1:
r = requests.post(host, {'btn' : '1'})
elif line.find(u'パイ電気消して') != -1:
r = requests.post(host, {'btn' : '2'})
elif line.find(u'パイ電気オフ') != -1:
r = requests.post(host, {'btn' : '2'})
elif line.find(u'パイエアコンつけて') != -1:
r = requests.post(host, {'btn' : '3'})
elif line.find(u'パイエアコンオン') != -1:
r = requests.post(host, {'btn' : '3'})
elif line.find(u'パイエアコン消して') != -1:
r = requests.post(host, {'btn' : '4'})
elif line.find(u'パイエアコンオフ') != -1:
r = requests.post(host, {'btn' : '4'})
 これで、julius -音声認識結果→ test_recognition_client.py -post→ test_irMagicianServer.py と連携して、音声で家電操作ができるようになりました。でも、静かな状態ならいいんですが、BGMとかをかけたりすると誤認識して、勝手にエアコンがOn/Off したり、突然部屋の明かりが消えたり・・・。う~ん、実用には遠い状態。認識語の組み合わせやマイク感度調整等で向上するのかな?




0 件のコメント:

コメントを投稿