본문 바로가기
개발 공부/프로젝트

ESP32-HTTP request: GET and POST

by momo'sdad 2023. 11. 23.

ESP32 모듈을 이용해 외부 서버에 HTTP request 를 보내는 방법

HTTP request: GET and POST

웹 서버로 HTTP 요청을 보낼 때 두 가지 방식, GET 과 POST

GET 과 POST 의 차이

  • GET
  • URL 뒤에 ? 를 붙이고 데이터(파라미터 이름과 값)를 붙여 보냄
  • 예) www.abc.com/test?param1=myname&param2=myemail
  • URL 길이 제한이 있기 때문에 많은 양의 데이터 전송이 어려움. URL 만으로 데이터 송수신이 가능.
  • POST
  • 데이터를 HTTP request 의 Body 에 넣어 보냄
  • HTTP request 의 Header 에 Content-Type 이라는 필드를 넣고 Body 에 들어갈 데이터가 무엇인지 입력
  • 길이 제한이 없고 다양한 데이터 전송 가능. URL 에 데이터가 노출되지 않음.

HTTP request: GET

먼저 GET 방식으로 HTTP 요청을 보내려면 아래에서 스케치를 받은 뒤, ssid, password 변수를 공유기 설정에 맞게 변경.

ESP32 에 업로드 하고 [시리얼 모니터]를 실행 결과

이 예제는 아래 URL 로 HTTP request 를 계속 보내고 그에 대한 응답을 받아오는 예제

의역하자면 id 가 10 인 comment 를 응답으로 보내달라는 HTTP request . 이 요청에 대한 응답을 받아 시리얼 모니터에 표시.

시리얼 모니터에 표시된 내용 중 200 은 응답코드입니다. 200은 모든 것이 정상 처리되었다는 의미 (기타 응답코드는 링크 참고)

그리고 200 아래에 표시되는 내용들은 우리가 요청한 comment 의 상세 정보를 JSON 데이터 형식으로 보내준 것

JSON 은 서버 API 를 호출하거나 그에 대한 응답을 받을 때 자주 사용하는 데이터 형식이다. JSON 에 대한 상세 설명(링크의 내용을 참고하세요.)

초기화 함수인 setup().

const char* ssid = "yourNetworkName"; const char* password = "yourPassword"; void setup() { Serial.begin(115200); delay(4000); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi.."); } Serial.println("Connected to the WiFi network"); }

WiFi.begin() 호출을 통해 공유기에 연결하고, 연결이 완료될 때까지 기다리고 wifi의 ssid, password가 맞아야 한다.

메인 루프 역할을 하는 loop() 함수

void loop() { if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status HTTPClient http; http.begin("http://jsonplaceholder.typicode.com/comments?id=10"); //Specify the URL int httpCode = http.GET(); //Make the request if (httpCode > 0) { //Check for the returning code String payload = http.getString(); Serial.println(httpCode); Serial.println(payload); } else { Serial.println("Error on HTTP request"); } http.end(); //Free the resources } delay(10000); }

HTTP request 를 보내기 위해 HTTPClient 클래스를 이용. HTTPClient.begin(URL_string) 을 호출하고 HTTPClient.GET() 만 호출해주면 GET 방식으로 request 를 전송. 그리고 response 를 받을 때 까지 blocking 됨.

http.begin("http://jsonplaceholder.typicode.com/comments?id=10"); //Specify the URL int httpCode = http.GET();

Response를 받으면 아래 구문이 실행. 단순히 response 의 body 에 담겨져온 내용을 시리얼로 출력한다..

if (httpCode > 0) { //Check for the returning code String payload = http.getString(); Serial.println(httpCode); Serial.println(payload); }

이처럼 HTTPClient 클래스를 이용하면 HTTP request 를 처리할 수 있다.

HTTP request: GET – JSON 처리

HTTP GET 예제에서 response 데이터가 JSON 형태의 string. 일반 HTML 페이지에 GET 요청을 보냈다면 response 데이터는 HTML string 형태 일 것이다.

하지만 센서장치가 브라우저를 탑재한 것이 아니기 때문에 HTML 응답을 위해 HTTP 요청을 보내지는 않는다. 보통은 서버에 데이터를 전송하거나 받기 위해 HTTP 요청을 보낼 것이다. 그리고 서버에 따라 다르겠지만 많은 경우 JSON 형태로 데이터를 주고 받는다.

JSON string 으로 응답을 받은 경우 JSON string 을 소스코드에서 인식하기 좋게 파싱해서 사용해야 한다.

파싱을 위해 아두이노용 JSON 파싱 라이브러리를 설치해야 한다.

아두이노 개발환경에서 [상단 메뉴 – 스케치 – 라이브러리 포함하기 – 라이브러리 관리] .

그리고 상단에 ArduinoJson 을 입력하고 검색 => ArduinoJson 라이브러리 => 우측 아래 버튼을 눌러 설치.

  • 주의!!ArduinoJson 최신 Beta 버전을 설치하지 않는다. 안정화된 버전을 설치. 추천 버전은 5.13.2

아래에서 스케치를 받아 HTTP GET 예제와 같은 방식으로 테스트.

테스트 결과.

JSON string 을 파싱해서 postId, id, name, email, body 파라미터에 값을 분리해서 넣음

HTTP response 로 받는 JSON string.

[ { "postId": 1, "id": 1, "name": "id labore ex et quam laborum", "email": "Eliseo@gardner.biz", "body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium" }, { "postId": 1, "id": 2, "name": "quo vero reiciendis velit similique earum", "email": "Jayne_Kuhic@sydney.com", "body": "est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et" }, { "postId": 1, "id": 3, "name": "odio adipisci rerum aut animi", "email": "Nikita@garfield.biz", "body": "quia molestiae reprehenderit quasi aspernatur\naut expedita occaecati aliquam eveniet laudantium\nomnis quibusdam delectus saepe quia accusamus maiores nam est\ncum et ducimus et vero voluptates excepturi deleniti ratione" }, { "postId": 1, "id": 4, "name": "alias odio sit", "email": "Lew@alysha.tv", "body": "non et atque\noccaecati deserunt quas accusantium unde odit nobis qui voluptatem\nquia voluptas consequuntur itaque dolor\net qui rerum deleniti ut occaecati" }, { "postId": 1, "id": 5, "name": "vero eaque aliquid doloribus et culpa", "email": "Hayden@althea.biz", "body": "harum non quasi et ratione\ntempore iure ex voluptates in ratione\nharum architecto fugit inventore cupiditate\nvoluptates magni quo et" } ]

Root element 로 배열이 들어가 있다. 그리고 배열 안에 Object 가 1 개 이상 나오는 구조. 이걸 처리하는 아두이노 스케치 코드.

if (httpCode > 0) { //Check for the returning code String payload = http.getString(); StaticJsonBuffer<500> JSONBuffer; //Memory pool JsonArray &root = JSONBuffer.parseArray(payload); for(int i=0; i<root.size(); i++) { JsonObject& parsed = root[i]; const char * postId = parsed["postId"]; // Get postId const char * id = parsed["id"]; // Get id const char * tname = parsed["name"]; // Get name const char * email = parsed["email"]; // Get email const char * body = parsed["body"]; // Get body Serial.println(httpCode); Serial.print("postId: "); Serial.println(postId); Serial.print("id: "); Serial.println(id); Serial.print("tname: "); Serial.println(tname); Serial.print("email: "); Serial.println(email); Serial.print("body: "); Serial.println(body); Serial.println("------------------------------"); Serial.println(); } }

JSON string 의 root element 가 배열. 그래서 파싱할 때 JSONBuffer.parseArray(payload) 를 사용. 그리고 JsonArray 포인터를 얻는다. 이제 JsonArray 에 포함된 object 수만큼 for 루프를 돌면서 Object 를 하나씩 꺼낸다. 그리고 Object 에 담긴 parameter 들을 가져와서 출력.

만약 JSON string 의 root element 가 배열이 아니라 Object 라면, JSONBuffer.parseObject(payload) 를 사용.

HTTP request: POST

이번에는 POST 방식을 사용해서 HTTP request 를 보내는 예제. 이런 HTTP POST 를 테스트할 수 있도록 해주는 jsonplaceholder.typicode.com 서버가 있다. 이 서버에 게시글을 등록하는 HTTP request 를 보내려면 아래 스케치에서 HTTP GET 예제와 같은 방식으로 테스트.

테스트 결과.

201 은 “created” 라는 의미를 가진 서버 응답코드. 즉, 우리가 보낸 HTTP request 에 담긴 데이터로 새로운 글을 작성했다는 의미. 그리고 HTTP response 에는 작성된 글의 ID 값이 JSON 형태로 들어있다.

소스코드를 살펴보면 초기화 함수 setup() 의 진행은 동일.

loop() 에서의 처리만 확인.

void loop() { if(WiFi.status()== WL_CONNECTED){ //Check WiFi connection status HTTPClient http; http.begin("http://jsonplaceholder.typicode.com/posts"); //Specify destination for HTTP request http.addHeader("Content-Type", "text/plain"); //Specify content-type header int httpResponseCode = http.POST("POSTING from ESP32"); //Send the actual POST request if(httpResponseCode>0){ String response = http.getString(); //Get the response to the request Serial.println(httpResponseCode); //Print return code Serial.println(response); //Print request answer } else { Serial.print("Error on sending POST: "); Serial.println(httpResponseCode); } http.end(); //Free resources } else { Serial.println("Error in WiFi connection"); } delay(10000); //Send a request every 10 seconds }

POST 방식도 HTTPClient 클래스를 이용. http.begin() 을 호출하면서 우리가 접근할 URL 을 입력.

HTTPClient http; http.begin("http://jsonplaceholder.typicode.com/posts"); //Specify destination for HTTP request

그리고 http.POST() 를 호출할 때 우리가 전송할 텍스트 데이터를 입력. 우리는 서버에 게시할 글의 내용을 보내야 하기 때문에 단순히 텍스트만 HTTP – body 에 넣으면 된다. 그리고 HTTP – body 에 담긴 데이터가 어떤 타입의 데이터인지 서버가 알 수 있도록 해야한다. http.addHeader() 의 역할이 서버가 HTTP-body에 담긴 데이터가 어떤 타입의 데이터인지 서버가 알 수 있도록 하는 것이다. HTTP – body 에 담긴 데이터가 text/plain 타입임을 헤더에 입력. (자세한 내용은 Mime type 을 검색하기)

http.addHeader("Content-Type", "text/plain"); //Specify content-type header int httpResponseCode = http.POST("POSTING from ESP32"); //Send the actual POST request

http.POST() 함수는 blocking call 이다. 서버에서 응답이 올때까지 코드 진행은 여기서 멈춘다. 이후 응답이 오면 다음 코드가 진행. 나머지의 진행은 HTTP GET 테스트 때와 같다.

반응형