前回の続き。
前回までで、ローカルでの制御はできるようになっていたから、ここから先は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)