Intel Edison board 웹에서 LED 제어하기
소스 입력하기
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void * on_connect(void *arg);
void sendData(FILE *response, char *file_name);
void sendHead(FILE *response,int status, char *mime_type);
void sendNoService(FILE *response);
int main(int argc, char **argv){
int serv_sock;
pthread_t thread;
struct sockaddr_in serv_addr, clnt_addr;
socklen_t clnt_addr_size;
int port = 8000;
if(argc >= 2){
port = atoi(argv[1]);
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(serv_sock == -1){
perror("fail to open socker");
return 1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
if(bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))==-1){
perror("fail to bind");
return 1;
}
if(listen(serv_sock, 10) ==-1){
perror("fail to listen");
return 1;
}
printf("server is running on %d\n", port);
while(1){
int clnt_sock;
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
if(clnt_sock == -1){
perror("fail to accep");
continue;
}
printf("client ip:%s\n", inet_ntoa(clnt_addr.sin_addr));
pthread_create(&thread, NULL, on_connect, &clnt_sock);
pthread_join(thread, 0);
close(clnt_sock);
}
printf("server has been shutdown\n");
return 0;
}
void * on_connect(void *arg){
int clnt_sock = *((int *)arg);
FILE *request, *response;
char line[BUFSIZ];
char method[10];
char file_name[256]="/home/root/public", url[256];
request = fdopen(clnt_sock, "r");
response = fdopen(dup(clnt_sock), "w");
fgets(line, BUFSIZ, request);
printf("%s", line);
strcpy(method, strtok(line, " "));
if(strcmp(method, "GET") == 0){
strcpy(url, strtok(NULL, " "));
if(strcmp(url, "/") == 0){
strcat(url, "index.html");
}
strcat(file_name, url);
while(1){
memset(line, 0, sizeof(line));
fgets(line, BUFSIZ, request);
if(strcmp(line,"\r\n") == 0){
break;
}
printf("%s", line);
}
sendData(response, file_name);
}else{
sendNoService(response);
}
fclose(request);
fclose(response);
return (void *)NULL;
}
void sendData(FILE *response, char *file_name){
char buff[BUFSIZ];
int len;
int fd;
fd = open(file_name, O_RDONLY);
if(fd == -1){
perror(file_name);
sendHead(response, 404, "text/html");
}else{
sendHead(response, 200, "text/html");
while( (len = read(fd, buff, BUFSIZ))>0){
fwrite(buff, sizeof(char), len, response);
}
}
fflush(response);
}
void sendHead(FILE *response,int status, char *mime_type){
char res_line[80] = "HTTP/1.1";
char content_type[1024] = "Conent-Type:";
char body[1024] = "<html><body><h1>";
strcat(content_type, mime_type);
strcat(content_type, "\r\n\r\n");
switch(status){
case 200:
strcat(res_line, " 200 OK\r\n");
break;
case 404:
strcat(res_line, " 404 Not Fount\r\n");
strcat(body, "404 Not Found</h1></body></html>");
break;
default:
strcat(res_line, " 500 Interanl server error\r\n");
strcat(body, "500 Internal server error</h1></body></html>");
break;
}
fputs(res_line, response);
fputs(content_type, response);
if(status != 200){
fputs(body, response);
}
}
void sendNoService(FILE *response){
sendHead(response, 200, "text/html");
char *body = "<html><body><h1>Sorry. Only GET method available</h1></body></html>";
fputs(body, response);
fflush(response);
}
라이브러리 추가하기
링커 라이브러리에서 pthread 라이브러리 추가
컴파일해본다.
컴파일 완료
Target SSH Conections 창에서 Launch Terminal 실행
index.html 생성
<!Doctype html>
<html>
<body>
<h1>Welcome to Edison</h1>
<p>Made by Jeongchul</p>
<form method="GET" action="/cgi/cmd">
<button name = "led" value="on">On</button>
<button name = "led" value="on">Off</button>
</form>
</body>
</html>
mkdir명령어로 public 디렉터리 생성
Eclipse 창의 perspective에서 Remote Systems로 변경
My Home에 생성된 public에 index.html을 복사 붙여넣기한다.
명령어를 통해 확인한다
보드에 업로드 해보자
완료가 되면 웹서버 주소로 접근해보자
192.168.0.246:8000
자신의 ip는 ifconfig로 확인하자
192.168.0.246:8000 로 접근
LED 제어를 위한 index.html 수정하기
<!Doctype html>
<html>
<body>
<h1>Welcome to Edison</h1>
<p>Made by Jeongchul</p>
<form method="GET" action="/cgi/cmd">
<button name = "led" value="on">On</button>
<button name = "led" value="off">Off</button>
</form>
</body>
</html>
수정된 내용을 Remote System Explorer를 통해 갱신한다.
웹 브라우저로 주소에 접근한다.
이제 C 언어 파일을 수정한다.
소스 코드 수정
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "mraa.h"
#define CGI "/cgi/"
void * on_connect(void *arg);
void sendData(FILE *response, char *file_name);
void sendHead(FILE *response,int status, char *mime_type);
void sendNoService(FILE *response);
void doCGI(FILE *response, char *url);
int turn_led(int pin, int isOn);
int main(int argc, char **argv){
int serv_sock;
pthread_t thread;
struct sockaddr_in serv_addr, clnt_addr;
socklen_t clnt_addr_size;
int port = 8000;
if(argc >= 2){
port = atoi(argv[1]);
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(serv_sock == -1){
perror("fail to open socker");
return 1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
if(bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))==-1){
perror("fail to bind");
return 1;
}
if(listen(serv_sock, 10) ==-1){
perror("fail to listen");
return 1;
}
printf("server is running on %d\n", port);
while(1){
int clnt_sock;
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
if(clnt_sock == -1){
perror("fail to accep");
continue;
}
printf("client ip:%s\n", inet_ntoa(clnt_addr.sin_addr));
pthread_create(&thread, NULL, on_connect, &clnt_sock);
pthread_join(thread, 0);
close(clnt_sock);
}
printf("server has been shutdown\n");
return 0;
}
void * on_connect(void *arg){
int clnt_sock = *((int *)arg);
FILE *request, *response;
char line[BUFSIZ];
char method[10];
char file_name[256]="/home/root/public", url[256];
request = fdopen(clnt_sock, "r");
response = fdopen(dup(clnt_sock), "w");
fgets(line, BUFSIZ, request);
printf("%s", line);
strcpy(method, strtok(line, " "));
if(strcmp(method, "GET") == 0){
strcpy(url, strtok(NULL, " "));
if(strncmp(url,CGI,strlen(CGI)) == 0){ // Is it start /cgi/?
printf("\ncgi : %s\n",url);
doCGI(response, url + strlen(CGI)); // move pointer /cgi/
} else {
if(strcmp(url, "/") == 0){
strcat(url, "index.html");
}
strcat(file_name, url);
while(1){
memset(line, 0, sizeof(line));
fgets(line, BUFSIZ, request);
if(strcmp(line,"\r\n") == 0){
break;
}
printf("%s", line);
}
sendData(response, file_name);
}
}else{
sendNoService(response);
}
fclose(request);
fclose(response);
return (void *)NULL;
}
void sendData(FILE *response, char *file_name){
char buff[BUFSIZ];
int len;
int fd;
fd = open(file_name, O_RDONLY);
if(fd == -1){
perror(file_name);
sendHead(response, 404, "text/html");
}else{
sendHead(response, 200, "text/html");
while( (len = read(fd, buff, BUFSIZ))>0){
fwrite(buff, sizeof(char), len, response);
}
}
fflush(response);
}
void sendHead(FILE *response,int status, char *mime_type){
char res_line[80] = "HTTP/1.1";
char content_type[1024] = "Conent-Type:";
char body[1024] = "<html><body><h1>";
strcat(content_type, mime_type);
strcat(content_type, "\r\n\r\n");
switch(status){
case 200:
strcat(res_line, " 200 OK\r\n");
break;
case 404:
strcat(res_line, " 404 Not Fount\r\n");
strcat(body, "404 Not Found</h1></body></html>");
break;
default:
strcat(res_line, " 500 Interanl server error\r\n");
strcat(body, "500 Internal server error</h1></body></html>");
break;
}
fputs(res_line, response);
fputs(content_type, response);
if(status != 200){
fputs(body, response);
}
}
void sendNoService(FILE *response){
sendHead(response, 200, "text/html");
char *body = "<html><body><h1>Sorry. Only GET method available</h1></body></html>";
fputs(body, response);
fflush(response);
}
void doCGI(FILE *response, char *url){
char cmd[256], key[256], value[256];
printf("cgi url : %s",url);
strcpy(cmd, strtok(url,"?"));
strcpy(key, strtok(NULL,"="));
strcpy(value,strtok(NULL,"="));
printf("cmd : %s, key : %s, value : %s\n",cmd,key,value);
int result = 0;
char *body;
if(strcmp(cmd,"cmd") == 0) {
if(strcmp(key,"led") == 0) {
if(strcmp(value,"on") == 0) {
result = turn_led(13,1);
body="<html><body><h1>Led On</h1><p>led on successfully</p>\
</body></html>";
}else if(strcmp(value,"off") == 0){
result = turn_led(13,0);
body="<html><body><h1>Led Off</h1><p>led off successfully</p>\
</body></html>";
}
}
if(result == 0) {
sendHead(response, 200, "text/html");
fputs(body,response);
}else {
sendHead(response, 500, "text/html");
}
}
fflush(response);
}
int turn_led(int pin, int isOn){
mraa_gpio_context led = mraa_gpio_init(pin);
if(led == NULL) {
perror("gpio init error");
return 1;
}
if(mraa_gpio_dir(led,MRAA_GPIO_OUT) != MRAA_SUCCESS) {
perror("fail to set led : out");
return 1;
}
if(isOn) {
mraa_gpio_write(led,1);
}else {
mraa_gpio_write(led,0);
}
return 0;
}
테스트
빌드해보고 테스트해봅시다
버튼 Led Off 누를 시
버튼 Led On 누를 시
'사물인터넷' 카테고리의 다른 글
Intel Edison board XDK IoT (0) | 2016.03.08 |
---|---|
Intel Edison board Eclipse Java LED 제어하기 (0) | 2016.03.08 |
Intel Edison Board IoT mraa API 사용 (0) | 2016.03.08 |
Intel Edison Board IoT Eclipse (0) | 2016.03.08 |
Intel Edison Board GPIO Control (0) | 2016.03.08 |