読者です 読者をやめる 読者になる 読者になる

hsuetsugu’s diary

ITの技術的なことに関して主に書きます。Rとpythonとd3.jsとAWSとRaspberryPiあたりを不自由なく使いこなせるようになりたいです。

(35連休)13日目:Raspberry Pi(はじめての電子工作②:WEBIOPi、ApacheとphpでLEDを制御)

Raspberry Pi WEBIOPi 電子工作

前回の続きです。*1
http://hsuetsugu.hatenablog.com/entry/2014/08/27/005149

前回やったことと今回やりたいこと

前回は、下記の流れでRaspberry Piに接続したLEDを制御してみました。
 ①LEDをただただ光らせる
 ②LEDの点灯をRaspberry Piで制御してみる。
  1)コマンドラインでLEDを制御
  2)WiringPiでLEDを制御する
  3)RubyでLEDを制御してみる(プログラムでチカチカさせる)
 ③PWMでLEDの明るさを制御してみる
 ④スマートフォンでGPIOを制御してみる

④でWEBIOPiというフレームワークを使って用意されている画面を使って、スマホからLEDを制御するところまできました。
今回はWEBIOPiのREST APIを用いて画面を自分で作って、そこから制御したいと思います。
ちなみに、WEBIOPiの公式ドキュメントには、「Internet of Things framework」と書かれています。なんかかっこいい・・・。


以下、基本的には下記の書籍をトレースしています。

Raspberry Piで遊ぼう! 改訂第2版

Raspberry Piで遊ぼう! 改訂第2版

Javascriptライブラリの用意

WEBIOPi公式のjsライブラリ(JAVASCRIPT - webiopi - Internet of Things framework - Google Project Hosting)もあるのですが、これはWEBIOPiの簡易WEBサーバーでの使用が前提となっているようです。今回はApacheで動かすことを目指すので、jsライブラリを用意します。

ApiMapper.js

//functionの設定
function set_gpio_function(port,dir,callback) {
	var url = "/GPIO/"+port+"/function/"+dir;
	webiopi_api("POST",url,"text","string",callback);
}

//値の取得
function get_gpio_value(port,callback) {
	var url = "/GPIO/"+port+"/value";
	webiopi_api("GET",url,"text","numeric",callback);
}

//値の設定
function set_gpio_value(port,value,callback) {
	var url = "/GPIO/"+port+"/value/"+value;
	webiopi_api("POST",url,"text","numeric",callback);
}

//PWM値の設定(ratio=0〜100)
function set_gpio_pwm(port,ratio,callback) {
	var value = ratio / 100;
	var url = "/GPIO/"+port+"/pulseRatio/"+value;
	webiopi_api("POST",url,"text","float",callback);
}

//PWM値の設定(angle=0〜360)
function set_gpio_servo(port,angle,callback) {
	var url = "/GPIO/"+port+"/pulseAngle/"+angle;
	webiopi_api("POST",url,"text","numeric",callback);
}

//WebIOPi APIとの通信
function webiopi_api(method,url,dataType,convert,callback) {
	if(USE_API_PROXY) {
		url = "webiopi_proxy.php?arg=" + url;
	}
	$.ajax({
		type: method,
		url: url,
		data: "",
		dataType: dataType,
		success: function(data, dataType) {
			if(callback != undefined) {
				if(convert == "numeric") callback(parseInt(data));
				else if(convert == "float") callback(parseFloat(data));
				else callback(data);
			}
		}
	});
}

WEBIOPi簡易サーバでPWMで明るさ制御

pwm.js

PWMで明るさを制御するので、LEDをGPIO18(Pin12)に接続しておき、明るさをボタンとスライダーで制御するようにします。

var USE_API_PROXY = false;
var port = 18;	//GPIO18
var val = 0;	//初期値
$(function() {
	//初期設定: GPIO18をPWMモードにして、出力を0にする
	set_gpio_function(port,"pwm",function(){
		set_gpio_pwm(port,0);
	});

	//ボタンが押されたらPWMの値を変える
	$('#btn1').click( function(){
		set_gpio_pwm(port,0);
		$('#slider').val(0);
	});
	$('#btn2').click( function(){
		set_gpio_pwm(port,33);
		$('#slider').val(33);
	});
	$('#btn3').click( function(){
		set_gpio_pwm(port,66);
		$('#slider').val(66);
	});
	$('#btn4').click( function(){
		set_gpio_pwm(port,100);
		$('#slider').val(100);
	});

	//スライダーが動いたらPWMの値を変える
	$('#slider').change(function(){
		set_gpio_pwm(port, $(this).val());
	});

});

test.htmlファイルの用意

上記で設定したボタン1-4とスライダーをhtmlファイルで配置し、上記APIのjsとボタン/スライダーの設定のjsを読み込むようにします。
test.html

・・・
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="ApiMapper.js"></script>
<script type="text/javascript" src="pwm.js"></script>
	<ul>
		<li id="btn1" class="ledoff">GPIO<br />18<br />0%</li>
		<li id="btn2" class="ledoff">GPIO<br />18<br />33%</li>
		<li id="btn3" class="ledoff">GPIO<br />18<br />66%</li>
		<li id="btn4" class="ledoff">GPIO<br />18<br />100%</li>
	</ul>
	<form>
	<input type="range" id="slider" min="1" max="100" value="0" style="width:100%">
	</form>
・・・

接続

上記をまとめて/usr/share/webiopi/htdocs/[folder] を作ってそこに格納します。
ブラウザで、http://raspberrypi.local:8000/[folder]/test.htmlに接続すれば、画面上でLEDの明るさを変更できることが確認できました。

ApacheでPWMで明るさ制御

Apachephpのインストール(していない場合)

  • インストール
$ sudo apt-get install apache2 php5
  • 権限設定
$ sudo chown pi -R /var/www
  • 起動とシステム起動時の起動設定
$ sudo /etc/init.d/apache2 start
$ sudo update-rc.d apache2 defaults

クロスドメインの対応

WEBIOPiはポート8000、Apacheはポート80なので、Apacheで動いているjsから直接WEBIOPiにhttpリクエストを送信することができないようです。そのため、proxyプログラムをApache側におくことで、クロスドメインの制約を回避します。
proxy.php

<?
//WebIOPiの情報
$host = "localhost";	//ホスト名
$port = "8000";    //ポート
$auth_idpw = "webiopi:raspberry"; //ユーザー名:パスワード

$arg = (isset($_REQUEST['arg'])) ? $_REQUEST['arg'] : "";
$arg = str_replace(chr(0),"",$arg);
if(ereg("^/GPIO/[0-9]+/[-a-zA-Z0-9.,_/]+$",$arg)) {
	$url = "http://".$host.":".$port.$arg;
	$data = "";
	$options = array(
		"http" => array(
			"method" => $_SERVER['REQUEST_METHOD'],
			"header" => "Authorization: Basic ".base64_encode($auth_idpw),
			"content" => ""
		)
	);
	$data = @file_get_contents($url, false, stream_context_create($options));
	header("Content-length: ".strlen($data));
	header("Content-type: text/plain");
	echo $data;
} else {
	header("HTTP/1.0 403 Forbidden");
}
exit;
?>

pwm.jsの微修正

下記の部分のみtrueに変更します。

var USE_API_PROXY = True;

接続

先ほどと同様に、html、ApiMapper.js、pwm.js、proxy.phpをまとめて/var/www/[folder] を作ってそこに格納します。ブラウザで、http://raspberrypi.local/[folder]/配下のhtmlに接続すれば、画面上でLEDの明るさを変更できることが確認できました。

*1:RStanの計算はまだ終わりません。