14주차_참고 : 코드 설명 - dhryu60/SmartDevice_2025-1 GitHub Wiki
#include <WiFi.h>
#include <HTTPClient.h>
-
WiFi.h
: ESP32에서 Wi-Fi 기능 사용 -
HTTPClient.h
: HTTP 요청(POST, GET 등)을 보내기 위한 라이브러리
const char *ssid = "Your_SSID"; // Wi-Fi 이름
const char *password = "Your_Password"; // Wi-Fi 비밀번호
const String rest_api_key = "REST API KEY";
String access_token = "Access token";
String refresh_token = "Refresh token";
#define MsgSendInterval 3600 // 60 * 60초 = 1시간
long timeout = 3600; // loop()에서 시간 경과 측정을 위한 변수
int sensorValue = 0;
int sensorPin = 34; // 아날로그 센서 핀 번호
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nConnected to WiFi : ");
Serial.println(WiFi.localIP());
}
- Wi-Fi 연결을 시도하고, 연결될 때까지 대기한다.
- 연결 성공 시 로컬 IP를 출력한다.
void loop() {
if (timeout++ > MsgSendInterval) {
if (isAccessTokenExpired() == true) {
if (update_access_token() == false) {
Serial.println("Access token update failed");
}
}
sensorValue = analogRead(sensorPin);
send_message();
timeout = 0;
}
delay(1000);
}
-
1초마다
timeout
을 증가시킨다. -
1시간(3600초)마다 다음 작업 수행:
- Access Token 만료 여부 확인
- 만료 시 Refresh Token으로 재발급 시도
- 센서값 읽고 메시지 전송
bool isAccessTokenExpired() {
HTTPClient http;
bool returnVal = true;
http.begin("https://kapi.kakao.com/v1/user/access_token_info");
http.addHeader("Authorization", "Bearer " + access_token);
int httpCode = http.GET();
if (httpCode > 0 && httpCode == HTTP_CODE_OK) {
String payload = http.getString();
String expireT = extract_string(payload, "\"expires_in\":", ",");
if (expireT.toInt() > 0) returnVal = false;
}
http.end();
return returnVal;
}
- 카카오 API로 현재 Access Token이 유효한지 확인한다.
- JSON 응답에서
"expires_in"
값을 추출하여 0보다 크면 아직 유효하다고 판단한다.
void send_message() {
HTTPClient http;
String url = "https://kapi.kakao.com/v2/api/talk/memo/default/send";
http.begin(url);
http.addHeader("Authorization", "Bearer " + access_token);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String data = String("template_object={") +
"\"object_type\": \"text\"," +
"\"text\": \"토양 센서 값 :" + String(sensorValue) + "\"," +
"\"link\": {}}";
http.POST(data);
String response = http.getString();
Serial.println(response);
http.end();
}
- 카카오톡 메시지를 전송하는 API 호출
- 메시지 내용은
"토양 센서 값 : [숫자]"
로 구성 - 링크 항목이 비어 있어도 구조는 있어야 한다 (
"link": {}
)
bool update_access_token() {
HTTPClient http;
bool retVal = false;
String url = "https://kauth.kakao.com/oauth/token";
http.begin(url);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String data = "grant_type=refresh_token&client_id=" + rest_api_key +
"&refresh_token=" + refresh_token;
int http_code = http.POST(data);
String response = http.getString();
access_token = extract_string(response, "{\"access_token\":\"", "\"");
String new_refresh_token = extract_string(response, "\"refresh_token\":\"", "\"");
if (new_refresh_token != "") {
refresh_token = new_refresh_token;
}
retVal = true;
http.end();
return retVal;
}
- 현재 보유 중인 Refresh Token으로 Access Token을 재발급받는다.
- 응답에 새로운 Refresh Token이 포함되어 있다면 갱신한다.
String extract_string(String str, String start_string, String end_string) {
int index1 = str.indexOf(start_string) + start_string.length();
int index2 = str.indexOf(end_string, index1);
String value = str.substring(index1, index2);
return value;
}
- 응답 본문 문자열에서 특정 구간의 텍스트를 추출하는 함수
- 예:
access_token
또는expires_in
값을 JSON에서 따로 파싱 없이 문자열로 추출
-
ESP32가 Wi-Fi에 연결된다.
-
loop()
에서 1시간마다:- 토큰 유효성 확인
- 만료 시 새 토큰 갱신
- 토양 센서값 읽기
- 카카오톡 메시지 전송
-
JSON 파싱은 사용하지 않고
extract_string()
으로 단순 추출만 수행한다.