ハードウェアは準備出来たので、色々と機能を載せていこうと思います。まずは、irMagician をブラウザから操作して家電のOn/Offをできるようにして、PCやVPN接続でスマホで外出先からの制御ができるようにしたいと思います。また、ブラウザ操作相当の操作を音声認識により実現したいと思います。
この手の「Raspberry Piを学習リモコンにしてスマホ等で操作する」とか「音声認識学習リモコン」とかはすでによくやられていて、前例がたくさんあります。今回は、そういった有益な銃砲をネットに公開してくださっている先達の知恵に甘えます。参考にしたサイトを幾つか挙げておきます。感謝です。
今回は python + tornado でサーバ側でpostを受け取って、irMagicianの json形式リモコン信号データを再生するプログラムをテスト的に作成しました。といっても、上記リンク先やネットに公開されていたコードをつなぎあわせただけですが。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
また、julius 音声認識をモジュールモードで動かして、julius 側ポート 10500 とソケット通信で音声認識結果を受け取って、ブラウザページでの操作に相当するpostを送信するような以下のプログラムも走らせます。なお、juliusには認識してい欲しい言葉だけの辞書セットを作っています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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'}) | |