https://bugwhale.tistory.com/entry/nodemuc-webserver-webpage-led-control
https://m.blog.naver.com/tius1234/220217312519
https://www.arduino.cc/en/Reference/ServerAvailable
https://www.arduino.cc/en/Reference/WiFiClient
https://opentutorials.org/module/3621/21674
위 링크들을 참고해 공부하고 작성했습니다.
앞에서 익힌 http를 이용해 통신하고 html로 웹에 하이퍼텍스트를 만든뒤
하이퍼텍스트 클릭을 통해서 LED를 제어하는 기능을 수행해 보겠습니다.
우선 Wemos D1 보드에 기본으로 장착되어있는 LED를 사용합니다.
Uno 보드에서는 디지털13번 이었지만 이 보드에서는 14번핀을 사용합니다
아두이노 코드의 loop 전 부분까지는
#define led 14와
LED의 pinMode 설정 정도만 추가해줍시다.
#include <ESP8266WiFi.h>
#define led 14 //1
const char* ssid = "와이파이이름";
const char* password = "와이파이비밀번호";
WiFiServer server(80);
void setup() {
pinMode(led, OUTPUT); //2
Serial.begin(115200);
delay(1000);
Serial.println();
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print(ssid);
Serial.println("에 접속중");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("");
Serial.println("연결되었습니다.");
server.begin();
Serial.println(WiFi.localIP());
}
void loop() {
WiFiClient client = server.available();
if(!client) return; //윗줄에서 WiFiClient를 통해 만든 클라이언트(client)가 접속해있는상태가 아니라면 loop로 도로 return 해서 접속할 때 까지 다른 기능을 수행하지 않습니다.
String request = client.readStringUntil('\r'); //문자열 request에 client가 서버에 요청한 리퀘스트 헤더를 \r이 나올때까지 읽어서 저장합니다
if(request.indexOf("/ledoff")!=-1){ //문자열의 위치(index)를 찾는 indexof함수(찾지못하면 -1을 return 합니다.)를 이용해 request에 /ledoff라는 문자열이 있으면 14번핀을 끕니다(led를끕니다)
digitalWrite(led,LOW);
}
else if(request.indexOf("/ledon")!=-1){ // 위와 유사합니다.
digitalWrite(led,HIGH);
}
else{
digitalWrite(led,digitalRead(led)); //다른경우라면 led의 현상태를 읽어 유지합니다.
}
while(client.available()){ //그외의 정보는 이 구현에선 필요하지 않으므로 버퍼를 비우기 위해 수신된 데이터를 모두읽습니다.
client.read();
}
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.println("<!DOCTYPE html>");
client.println("<html>");
client.println("<head>");
client.println("<meta charset=\"UTF-8\">");
client.println("<title>LED 제어</title>");
client.println("</head>");
client.println("<body>");
client.println("<h1>LED 제어콘솔</h1>");
client.println("<a href='/ledon'>LED ON</a>");
client.println("<a href='/ledoff'>LED OFF</a>");
client.println("LED 상태: ");
client.println((digitalRead(led)) ? "ON" : "OFF");
client.println("</body>");
client.println("</html>");
delay(10);
}
loop전부분은 저번 Hello World 출력과 달라진 부분은 간단한 주석만 달아두었고
loop문의 추가된 부분은 주석을 참고바랍니다.
String request = client.readStringUntil('\r');
문자열 request 속에 전송받은 데이터에서 \r이 나올 때 까지 읽어서 저장하는 코드입니다.
이 부분은 HTTP Request 형식을 보면 이해하기 좋습니다.
client.readStringUntil('\r');
이 부분에서 \r까지 읽는 이유는
우리가 텍스트를 적다가 한줄을 내리는것
html에서 br 태그를 이용해 개행하는것, 아두이노 ide에서 println을 사용하여 표시 후 개행하는것이
HTTP 헤더 에서는 \r(캐리지리턴)과 \n(라인피드)를 함께 사용해서 작동하기 때문입니다.
즉 가장먼저 \r\n (개행)이 오는 부분은 Requset Line 마지막부분 입니다.
클라이언트가 서버에 요청한 정보 중 /1.1 부분 까지 읽습니다 우리의 예시에서는
a href='/ledon 부분 때문에 하이퍼텍스트를 누를때 URL 뒤에 /ledon이 붙게 되고
그로인해 문자열 request에 /ledon 부분도 저장되게 됩니다.
그렇기 때문에 if(request.indexof("/ledon")!=-1) 부분에서 문자열에 ledon이나 ledoff를 찾게 되고
하이퍼텍스트를 누름에 따라 보드에 연결된 LED를 제어하는 기능을 구현할 수 있는 것입니다.
앞서 넘어갔던 내용인데 print가 아닌 println을 사용하는데도
client.println("Content-Type: text/html");
client.println();
와 같이 따로 한줄을 삽입하는 이유는
client.println("Content-Type: text/html"); 에서 다음 줄로 커서를 내린 것 뿐이고
client.println();를 하나 더 삽입해두어야 header 뒤에 빈 줄이 한줄 생기기 때문입니다.
위와 같이 코드를 작성 후 실행해보면 앞선 예와 마찬가지로 공유기에 접속 된 뒤 브라우저에 입력할 URL이 나옵니다.
LED ON 을 누르고 관리자 도구로 리퀘스트 헤더를 확인했을 때
첫줄이
GET /ledon HTTP/1.1 \r\n 으로 되어 있는 것을 확인할 수 있습니다
잘 작동하는 것을 확인할 수 있습니다.
이제 다른 액추에이터를 작동하는데 응용할 수 있고
변수를 선언해 anarodRead값을 저장해둔 뒤
client.println(변수)를 넣으면 웹상에서 센서가 읽은 값을 모니터링 하는 등으로 응용할 수 있습니다.
외부망 사용하기 (0) | 2022.01.19 |
---|---|
아두이노를 웹서버로 사용하기 (0) | 2022.01.16 |
esp8266 thingspeak (0) | 2022.01.14 |
Wemos D1 아두이노 보드 사용법 (0) | 2022.01.14 |