HTML언어에서 버튼 태그를 사용하여 간단하게 키보드를 작성하는 프로그램을 이미 게재했었다. 이 프로그램에서 7 segment LED 그래픽을 위해서는 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F 까지를 대상으로 7 segment LED를 스마트폰 웹 화면에 출력해 보기로 한다.
단 출력 명령도 스마트 폰 웹화면에 생성된 키보드를 사용하여 16진수를 입력하면 정보가 버튼에서 웹브라우저 주소창을 통해 GET/ KEY=문자 HTTP/1.1이 아두이노 NodeMCU에 와이파이로 전달이 됨과 동시에 시리얼 모니터에서 확인 할 수 있다.
일단 전체 프로그램 구조를 설명해 보기로 하자.
사용되는 라이브러리는 유일하게 ESP8266WiFi.h 하나이다. 즉 NodeMCU 와이파이 지원 라이브러리이다.
WiFiServer server(80); 선언은 와이파이 웹서버 프로그램에서 절대적으로 필수이다.
그다음 String c;는 스마트폰 키보드로부터 전달된 문자를 저장 분별하기 위한 문자선언인데 loop() 내부의 if() 문에서 사용된다.
아두이노 NodeMCU에서는 절대로 통신속도 설정 Serial.begin(115200);을 9600으로 낮추면 안 된다는 점을 명심하자.
setup()에서 자신의 스마트폰 핫스팟 공유기와 와이파이 연결을 시도하고 연결되면 가상 ip를 부여 받는다. 이 가상 ip는 스마트폰 웹브라우저 주소창에 입력하여 자신의 아두이노 NodeMCU에서 실행되고 있는 웹서버 프로그램을 호출하는 데 필수적인 정보이면서 명령어거 된다.
loop() 초반에서 server.available()과 client.available()을 반드시 확인한 후에 즉 서로 연결이 확실하다면 클라이언트로부터의 request를 체크하게 된다.
클라이언트로부터의 request가 한번 씩 오는데 그때마다 연이어 favicon.ico request도 함께 오게 된다. 즉 중복적으로 2번 request가 이루어지는 셈이다. 이는 인터넷 웹브라우저 개발 초기부터 의무적으로 주소창 앞에 16X16 그래픽을 입력하도록 되어 있는바 웹서버에서는 최상위 루트 디렉토리에 이 favicon 이미지 파일을 설치해 두어야 favicom.ico request를 충족시키게 되는 것이다.
하지만 아두이노류의 마이크로콘트롤러 시스템에서는 여타의 제대로 된 컴퓨터처럼 디렉토리 구조를 가지지 못하기 때문에 또는 아예 루트 디렉토리라는 개념이 없기 때문에 별 문제가 없다면 그대로 내버려 두어도 된다. 하지만 사물인터넷의 근본 속성이 제어 즉 스위치 on OFF에서 출발하기 때문에 이를 방치할 경우 감당할 수 없을 정도의 위험한 상태 즉 화재를 비롯한 재난을 초래할 수도 있다.
이에 대한 근본 적인 대비책은 전달된 request문을 대상으로 substring(5,16) 문법을 사용하여 favicon.ico request 인지 여부를 검증해 보는 것이다. 이미 프로그램되어 있으니 조사해 보기 바란다.
substring(5,16)에서 5는 정확하게 favicon.ico의 f보다 한 자리 앞을 지정하는 반면에 substring(5,16)에서 16은 favicon.ico의 마지막 “o”를 지정한다. 명령어 사용에 착오 없기 바란다.
다음 스텝은 스마트폰으로부터의 request 내용으로부터 어떤 문자나 숫자가 입력되었는지를 조사해야 할 필요가 있다. 이는 indexOf() 명령을 써서 그 값이 –1 이라면 아무런 request가 없었다는 의미이며 실제 출력해 보면 4라는 값이 많이 들어 있다. 그렇다면 전송되어 온 문자를 걸러 String c에 저장하면 된다. 여기에는 키보드에 지정된 문자 수 만큼의 if() 문이 사용된다.
if (request.indexOf("/KEY=1") != -1) {
c ="1";
Serial.println(c);}
⚫⚫⚫
그 다음서 부터가 HTML 프로그램이다. 이 부분을 살펴보자. 현재의 프로그램에서는 3가지 경우 즉 “4”,“6”,“8” 만의 7세그먼트 그래픽을 제공하도록 프로그램 되어 있다. 특별한 이유는 없으나 프로그램 길이만 길어져 프로그램 이해에 도움이 안 된다는 측면이 있음을 지적한다. “8”을 출력하는 프로그램에서 불필요한 세그먼트 그래픽 명령을 지우면 된다. “4” 와 “6”세그먼트 프로그램에서 빈 줄이 바로 그런 곳이다.
반면에 버튼 키보드는 16진법의 모든 문자를 출력하고 있다. 만약 처음 프로그램 실행 시에 7세그먼트 그래픽 출력이 없다면 “4”,“6”,“8”키를 눌러 보도록 하자. 그런데 프로그램이 되어 있자 않은 나머지 키를 누르면 결과는 세그먼트 출력이 없다. 아두이노 loop() 프로그램은 계속 반복되므로 다시 “4”,“6”,“8”키를 누르면 세그먼트 출력을 볼 수 있을 것이다.
나머지 문자에 대한 프로그래밍은 각자의 몫으로 남겨둔다.
이것으로 지난번 프로그램되었던 키보드 프로그램과 HTML 7세그먼트 프로그램이 결합되어 하나의 완벽한 웹서버 프로그램으로 스마트폰 웹브라우저에서 입력하면 웹서버인 NodeMCU가 처리하여 결과를 다시 스마트폰 웹 화면에서 볼 수 있게 된다.
결국 아두이노는 NodeMCU의 도움으로 귀(와이파이)가 뚫렸고 눈(디스플레이)을 찾아 광명을 되찾았으며 손가락 키보드를 얻어 장애를 극복하게 되었다.
Webserver_nodemcu_IOT_keybd_7segment_01
#include <ESP8266WiFi.h>
const char* ssid = "AndroidHotspot1234";//자신의 스마트폰 핫스팟ID입력
const char* password = "00000000";//자신의 스마트폰 핫스팟 비밀번호 입력
WiFiServer server(80);
String c;
void setup() {
Serial.begin(115200);
delay(10);
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println("Setup done");
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");
}
void loop() {
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait until the client sends some data
Serial.println("new client");
while(!client.available()){
delay(1);
}
// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
// favicon.ico request는 중복이므로 건너 뛰도록 프로그램 한다.
if(request.substring(5,16) != "favicon.ico") {
client.flush();
// Match the request
// Key board input processing
if (request.indexOf("/KEY=1") != -1) {
c ="1";
Serial.println(c);}
if (request.indexOf("/KEY=2") != -1) {
c ="2";
Serial.println(c);}
if (request.indexOf("/KEY=3") != -1) {
c ="3";
Serial.println(c);}
if (request.indexOf("/KEY=4") != -1) {
c ="4";
Serial.println(c);}
if (request.indexOf("/KEY=5") != -1) {
c ="5";
Serial.println(c);}
if (request.indexOf("/KEY=6") != -1) {
c ="6";
Serial.println(c);}
if (request.indexOf("/KEY=7") != -1) {
c ="7";
Serial.println(c);}
if (request.indexOf("/KEY=8") != -1) {
c ="8";
Serial.println(c);}
if (request.indexOf("/KEY=9") != -1) {
c ="9";
Serial.println(c);}
if (request.indexOf("/KEY=0") != -1) {
c ="0";
Serial.println(c);}
if (request.indexOf("/KEY=A") != -1) {
c ="A";
Serial.println(c);}
if (request.indexOf("/KEY=B") != -1) {
c ="B";
Serial.println(c);}
if (request.indexOf("/KEY=C") != -1) {
c ="C";
Serial.println(c);}
if (request.indexOf("/KEY=D") != -1) {
c ="D";
Serial.println(c);}
if (request.indexOf("/KEY=E") != -1) {
Serial.println("E");}
if (request.indexOf("/KEY=F") != -1) {
c ="F";
Serial.println(c);}
// Return the response
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println(""); // do not forget this one
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head>");
//배경 색 문자 색 사이즈 HTML CSS 설정
client.println("<style>");
client.println("body {");
client.println("background-color: lightblue;");
client.println("}");
client.println("p {");
client.println("color:red;");
client.println("font-size:250%;");
client.println("}");
//버튼 HTML CSS 설정
client.println(".button {");
client.println("background-color: white;");
client.println("border: solid;");
client.println("color: black;");
client.println("padding: 15px 32px;");
client.println("text-align: center;");
client.println("text-decoration: none;");
client.println("display: inline-block;");
client.println("font-size: 50px;");
client.println("margin: 2px 2px;");
client.println("cursor: pointer;");
client.println("}");
client.println("</style>");
client.println("<title>Page Title</title>");
client.println("<h1> Arduino 7 Segment </h1>");
client.println("</head>");
client.println("<body>");
client.println("<p>");
client.println("<svg height='300' width='300'>");
if (c == "4") {
client.println("<polygon points='50,55 60,65 60,135 50,145 40,135 40,65' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='200,55 210,65 210,135 200,145 190,135 190,65' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,150 60,140 190,140 200,150 190,160 60,160' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='200,155 210,165 210,235 200,245 190,235 190,165' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='205,250 215,240 225,240 235,250 225,260 215,260' style='fill:red;stroke:black;stroke-width:3' />"); }
if (c == "6") {
client.println("<polygon points='50,50 60,40 190,40 200,50 190,60 60,60' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,55 60,65 60,135 50,145 40,135 40,65' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,150 60,140 190,140 200,150 190,160 60,160' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,155 60,165 60,235 50,245 40,235 40,165' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='200,155 210,165 210,235 200,245 190,235 190,165' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,250 60,240 190,240 200,250 190,260 60,260' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='205,250 215,240 225,240 235,250 225,260 215,260' style='fill:red;stroke:black;stroke-width:3' />"); }
// client.println("<polygon points='50,50 60,40 190,40 200,50 190,60 60,60' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,55 60,65 60,135 50,145 40,135 40,65' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='200,55 210,65 210,135 200,145 190,135 190,65' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,150 60,140 190,140 200,150 190,160 60,160' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,155 60,165 60,235 50,245 40,235 40,165' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='200,155 210,165 210,235 200,245 190,235 190,165' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,250 60,240 190,240 200,250 190,260 60,260' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='205,250 215,240 225,240 235,250 225,260 215,260' style='fill:red;stroke:black;stroke-width:3' />");
if (c == "8") {
client.println("<polygon points='50,50 60,40 190,40 200,50 190,60 60,60' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,55 60,65 60,135 50,145 40,135 40,65' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='200,55 210,65 210,135 200,145 190,135 190,65' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,150 60,140 190,140 200,150 190,160 60,160' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,155 60,165 60,235 50,245 40,235 40,165' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='200,155 210,165 210,235 200,245 190,235 190,165' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='50,250 60,240 190,240 200,250 190,260 60,260' style='fill:red;stroke:black;stroke-width:3' />");
client.println("<polygon points='205,250 215,240 225,240 235,250 225,260 215,260' style='fill:red;stroke:black;stroke-width:3' />"); }
// client.println("<polygon points='50,50 60,40 190,40 200,50 190,60 60,60' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,55 60,65 60,135 50,145 40,135 40,65' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='200,55 210,65 210,135 200,145 190,135 190,65' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,150 60,140 190,140 200,150 190,160 60,160' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,155 60,165 60,235 50,245 40,235 40,165' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='200,155 210,165 210,235 200,245 190,235 190,165' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='50,250 60,240 190,240 200,250 190,260 60,260' style='fill:red;stroke:black;stroke-width:3' />");
// client.println("<polygon points='205,250 215,240 225,240 235,250 225,260 215,260' style='fill:red;stroke:black;stroke-width:3' />");
client.println("</svg>");
// Key board input
client.println("<br><br>");
client.println("<a href=\"/KEY=1\"\" class='button'> 1 </button></a>");
client.println("<a href=\"/KEY=2\"\" class='button'> 2 </button></a>");
client.println("<a href=\"/KEY=3\"\" class='button'> 3 </button></a>");
client.println("<a href=\"/KEY=A\"\" class='button'> A </button></a>");
client.println("<br>");
client.println("<a href=\"/KEY=4\"\" class='button'> 4 </button></a>");
client.println("<a href=\"/KEY=5\"\" class='button'> 5 </button></a>");
client.println("<a href=\"/KEY=6\"\" class='button'> 6 </button></a>");
client.println("<a href=\"/KEY=B\"\" class='button'> B </button></a>");
client.println("<br>");
client.println("<a href=\"/KEY=7\"\" class='button'> 7 </button></a>");
client.println("<a href=\"/KEY=8\"\" class='button'> 8 </button></a>");
client.println("<a href=\"/KEY=9\"\" class='button'> 9 </button></a>");
client.println("<a href=\"/KEY=C\"\" class='button'> C </button></a>");
client.println("<br>");
client.println("<a href=\"/KEY=F\"\" class='button'> F </button></a>");
client.println("<a href=\"/KEY=0\"\" class='button'> 0 </button></a>");
client.println("<a href=\"/KEY=D\"\" class='button'> D </button></a>");
client.println("<a href=\"/KEY=E\"\" class='button'> E </button></a>");
//
client.println("</p>");
client.println("</body>");
client.println("</html>");
delay(1);
Serial.println("Client disonnected");
Serial.println("");
}// if문 괄호 닫기
}//프로그램 끝
'아두이노프로세싱 프로그래밍' 카테고리의 다른 글
아두이노 NodeMCU 7세그먼트 LED 프로그램:II (0) | 2017.03.02 |
---|---|
아두이노 우노 7세그먼트 LED 프로그램:I (0) | 2017.03.01 |
구글 맵 HTML 프로그램에 의한 아두이노 NodeMCU GPS 데이터 확인 (0) | 2017.02.26 |
HTML 웹 프로그램에 의한 아두이노 NodeMCU 안드로이드 스마트폰 키보드:III (0) | 2017.02.25 |
아두이노 NodeMCU 웹서버 문자열 입력 스마트폰 HTML 웹 버튼 키보드:II (0) | 2017.02.23 |