リモートLED制御
リモートでブラウザからRaspberry PiのLEDを制御する。
同時にストリームでRaspberry piから動画をストリーミングする。
Raspberry pi上のHTTPサーバとして
1) node.js
2) MJPG-Streamer
を導入。
ポートがぶつからないように
それぞれの待ち受けポートを
1) 8088
2) 8080
とする。
node.js側をメインのHTTPサーバとして、MJPG-Streamerを動画ストリーミング用とする。
ブラウザで表示させた画面。
制御するLEDを写すようにカメラを向けている。
(1)ブラウザで表示するHTML
・imgタグで動画の表示を行う。
・ボタンが押されたらPOSTメッセージをXMLHttpRequestにて送信する。
<html> <head> <meta charset="UTF-8"> <title>STREAM VIEW</title> </head> <body> <img src="http://192.168.11.200:8080/?action=stream" /> <br> <form name="control"> <input type="button" value="RED" onClick="button('red')"> <input type="button" value="GREEN" onClick="button('green')"> <input type="button" value="YELLOW" onClick="button('yellow')"> </form> <script type="text/javascript"> var color_red = 'off'; var color_green = 'off'; var color_yellow = 'off'; function button(value){ console.log(value); var request = false; request = new XMLHttpRequest(); if(!request){ alert("This browser does not support XMLHttpRequest"); return false; } var led_value = 'off'; switch(value){ case 'red': color_red = (color_red == 'off') ? 'on' : 'off'; led_value = color_red; break; case 'green': color_green = (color_green == 'off') ? 'on' : 'off'; led_value = color_green; break; case 'yellow': color_yellow = (color_yellow == 'off') ? 'on' : 'off'; led_value = color_yellow; break; } var send = 'color=' + value + '&' + 'set=' + led_value; request.open('POST', '/serial', true); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); request.send(send); } </script> </body> </html>
(2)node.jsのスクリプト
・上記のHTMLを返す。
・LED制御のPOSTリクエストに応答する。
// controlLED.js var http = require('http'); var path = require('path'); var fs = require('fs'); var sys = require('sys'); var fs = require('fs'); var spawn = require('child_process').spawn; var url = require('url'); var querystring = require('querystring'); var util = require('util'); http.createServer(function (request, response){ var lookup = path.basename(decodeURI(request.url)); if(request.method == 'GET'){ switch(lookup){ case 'controlLED.html': lookup = '/home/pi/RemoteControlLed/' + lookup; fs.readFile(lookup, function(err, data){ if(err){ response.writeHead(500); response.end('Server Error!'); return; } var headers = {'Content-Type': 'text/html'}; response.writeHead(200, headers); response.end(data); }); break; default: response.writeHead(404); response.end('The page cannot be found'); console.log('file not found : ' + lookup); break; } } else if (request.method == 'POST'){ switch(lookup){ case 'serial': var postData = ''; request.on('data', function(chunk){ postData += chunk; }).on('end', function(){ var postDataObject = querystring.parse(postData); if(postDataObject.hasOwnProperty('color') && postDataObject.hasOwnProperty('set')){ controlLED(postDataObject.color, postDataObject.set); } else{ console.log('connot found "color / set"'); } }); sendResponse(response); break; } } }).listen(8088); function sendResponse(response) { var headers = {'Content-Type': 'test/html'}; response.writeHead(200, headers); response.end('OK'); } function controlLED(color, set) { var ctrl = spawn('./controlLED/controlLED', [color, set]); ctrl.stdout.on('data', function(data){ sys.print('stdout:' + data); }); ctrl.stderr.on('data', function(data){ sys.print('stderr: ' + data); }); ctrl.on('exit', function(code){ sys.print('exit: ' + code); }); }
(3)LED制御のためのCプログラム
・GPIOを制御しLEDのON/OFFを行う。
・GPIOの制御はデバイスファイルへの1/0書き込み。
// controlLED.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <time.h> #include <sys/time.h> int gpio_write(int gpio_number, int value); int writeValue(char *file, char *value); int readValue(char *file, char *buff, int length); #define PRINTLINE printf("%s, %d\n", __FUNCTION__, __LINE__); // GPIO PIN ASSIGN #define GPIO_RED 23 #define GPIO_GREEN 24 #define GPIO_YELLOW 25 //------------------------------ // Expected command line is as below. // ex. // $ controlLED red on // $ controlLED green off int main(int argc, char *argv[]) { int i; int gpio; int value; for(i=0;i<argc;i++){ printf("argv[%d] : %s\n", i, argv[i]); } if(argc < 3){ PRINTLINE printf("illegal argument\n"); return 0; } if(strcmp("red", argv[1]) == 0) { gpio = GPIO_RED; } else if(strcmp("green", argv[1]) == 0) { gpio = GPIO_GREEN; } else if(strcmp("yellow", argv[1]) == 0) { gpio = GPIO_YELLOW; } else { PRINTLINE printf("illegal argument\n"); return 0; } if(strcmp("on", argv[2]) == 0){ value = 1; } else if(strcmp("off", argv[2]) == 0){ value = 0; } else{ PRINTLINE printf("illegal argument\n"); return 0; } gpio_write(gpio, value); return 0; } //------------------------------ int gpio_write(int gpio_number, int value) { int ret; char wbuff[32]; char str[128]; PRINTLINE printf("gpio : %d , value : %d\n", gpio_number, value); sprintf(str, "%d", gpio_number); ret = writeValue("/sys/class/gpio/export", str); sprintf(str, "/sys/class/gpio/gpio%d/direction", gpio_number); ret = writeValue(str, "out"); sprintf(str, "/sys/class/gpio/gpio%d/value", gpio_number); sprintf(wbuff, "%d", value); ret = writeValue(str, wbuff); return 0; } //------------------------------ int writeValue(char *file, char *value) { int fd; int ret; printf("%s : %s\n",file, value); // return; fd = open(file, O_WRONLY); if(fd < 0){ PRINTLINE perror("GPIO open error"); return -1; } ret = write(fd, value, strlen(value)); if(ret < 0){ PRINTLINE perror("GPIO write error"); return -1; } ret = close(fd); if(ret < 0){ PRINTLINE perror("GPIO close error"); return -1; } return 0; } //------------------------------ int readValue(char *file, char *buff, int length) { int fd; int ret; fd = open(file, O_RDONLY); if(fd < 0){ PRINTLINE perror("GPIO open error"); return -1; } ret = read(fd, buff, length); if(ret < 0){ PRINTLINE perror("GPIO read error"); return -1; } ret = close(fd); if(ret < 0){ PRINTLINE perror("GPIO close error"); return -1; } printf("%s : %s\n",file, buff); return 0; }