ワイヤレスリモコンを改造しよう4

前回の続き。
前回までで、ローカルでの制御はできるようになっていたから、ここから先はiPhoneで制御できるようにするのが目標。仕組みとしては、サーバー上とローカルでどちらも状態を保存しておいて、Raspberry Piは定期的にサーバーの値を確認しにいって、変更されていたら前回実装したコマンドを動かしてON/OFFする、サーバー上はWebページも作って、iPhoneはそこからON/OFFを切り替える、ということにした。

なんでも公開するのははずかしい気もするけど、まあ誰もみていないことにしよう。もし見られた方は、そっとブラウザを閉じるか、心優しいアドバイスをください。

iPhoneで開くページ。ラジオボタンをクリックしたらJavaScriptでup.phpにPOSTする。HttpXMLRequestじゃなくてfetchというのを使ってみた。あんまり理解していないけど、sw=on みたいな値がPOSTされるんだと思っている。

<form id="sw">
<input type='radio' name='sw' id="swon" value='on'>
<input type='radio' name='sw' id="swoff" value='off'>

</form>
</body>
<script type="text/javascript">
var url = "up.php";
var swhandler = function(){
        document.getElementById("status").innerHTML = this.value;
        fetch(url, {
                method: 'POST',
                body: new FormData(document.getElementById('sw'))
        }).then(function(response){
                return response.json();
        }).then(function(json){
                console.log(json);
        });
};
document.getElementById("swon").onclick = swhandler;
document.getElementById("swoff").onclick = swhandler;

</script>

POSTを受けるやつ。なんとなくJavaScriptを使うときってJSONにしないといけないのかな、って思ってJSONを使おうとしたけど、POSTのところでJSONを使っていない時点でもはやどうでもいい気がする。でも最初にJSONにしてしまったからそのまま。POSTされた値と保存しておいた現在の値を比べて、同じならファイルを書き換える。エラー処理無しの男らしさ。

<?php
$nextStatus = $_POST['sw'];
$filename = 'status.json';

$status = file($filename);
$sw = json_decode($status[0]);
$lastStatus = $sw->{"sw"};

$result = '{"sw":"on"}';
$update = false;

if($nextStatus == "on"){
        $result = '{"sw":"on"}';
        if($lastStatus == "off"){
                $update = true;
        }
}
else if ($nextStatus == "off"){
        $result = '{"sw":"off"}';
        if($lastStatus == "on"){
                $update = true;
        }
}
if($update){
        $fp = fopen($filename, 'w');
        fwrite($fp, $result);
        fclose($fp);
}
print $result;
?>

サーバー上の状態を確認するPython。これをRaspberry Pi上で python status.py loop って実行して無限ループさせている。

import requests
import json
import gpio
from time import sleep
import sys

def check():

	url = "https://himitsu/status.json"
	local = 'status.json'

	# Local
	r = open(local, 'r')
	data = json.load(r)
	print json.dumps(data)
	lastStatus = json.dumps(data["sw"])
	r.close()


	# Server
	r = requests.get(url)
	data = r.json()
	print json.dumps(data)
	currentStatus = json.dumps(data["sw"])
	
	if (lastStatus == currentStatus):
		print "No status change"
		print "Switch is %s" % (currentStatus)
	else:
		print "Status changed from %s to %s" % (lastStatus, currentStatus)
		gpio.modulate_out_str(currentStatus)
		r = open(local, 'wb')
		r.write(json.dumps(data))
		r.close()

	
if __name__ == '__main__':
	if sys.argv[1]  == "loop":
		while True:
			check()
			sleep(1)
	check()

前回からちょっと変えたスクリプト。他のファイルから呼び出してもらうために不要な部分はmainにいれた。あと、信号をそのまま引数にしてたから、on/offを引数にとる関数を追加した。

from gpiozero import LED
from time import sleep
import sys

led = LED(17)
adj   = 0.18 #msec. this value is to adjust too long sleep
adjlon= 0.11
adjin = 1.0
short = 0.39 -adj #msec
long  = 0.99 -adjlon #msec
inter = 9.93 -adjin  #msec
on    = "0001010100010101010101110"
off   = "0001010100010101010101000"
num   = 5

def short_out():
	led.on()
	sleep(short/1000)
	led.off()
	sleep(long/1000)

def long_out():
	led.on()
	sleep(long/1000)
	led.off()
	sleep(short/1000)
	
def modulate_out( str ):
	print "---"
	print str
	print "---"

	short_out()
	for x in range (0, num):
		sleep(inter/1000)
		for c in str:
			if c == '0':
				short_out()
			else:
				long_out()

def modulate_out_str( str ):
	if(str == '"on"'):
		modulate_out(on)
	else:
		modulate_out(off)

if __name__ == '__main__':
	if sys.argv[1] == "on":
		print "on"
		modulate_out(on)
	else:
		print "off"
		modulate_out(off)