초급 예제

누구나 쉽게 따라해볼 수 있는 쉬운 예제들입니다. 가볍게 도전~!

OpenWeatherMap API를 사용하여 날씨데이터 받아오기

2021-11-22 11:55:57

 

OrangeBoard WiFi​+는 기존 OrangeBoard WiFi의 성능을 보완하여 유저들이 더 쉽게 사용하고 다양한 프로젝트로 확장할 수 있도록 개선한 보드입니다.

WiFi모듈은 WizFi250대신 WizFi360으로 변경되었고 MCU또한 Uno에서 쓰이던 ATmega328p대신 Mega에서 쓰이는 ATmega2560을 사용합니다.

 

 


 

 

 

1. API란

 

API란 Application Programming Interface의 약자로 프로그램이나 어플리케이션이 정보처리를 위해 운영체제에 호출하는 함수나 서브루틴의 집합을 말합니다. 서버에서는 API를 제공함으로써 클라이언트가 손쉽게 원하는 정보를 가져갈 수 있도록 도와줍니다. 

 

식당으로 비유하자면 고객(클라이언트)부엌(서버)에서 원하는 요리(데이터)를 주문하기 위해 웨이터(API)를 불러 쉽게 주문하는 것을 생각하면 됩니다.

 

 

 

 

 

 

 

 

 

Web에서 데이터를 읽기 위해 사용되는 API는 좀 더 자세히 말하자면 RESTful API(Representational State Transfer-ful API)라고 하며

httpRequest를 통해 JSON이나 XML형식의 데이터를 읽어오게 됩니다.

웹프로토콜을 준수하여 데이터를 읽어오며, OrangeBoard WiFi+에서도 GET/POST를 주로 사용해 데이터를 읽어옵니다.

 

 

 

여러 웹사이트들은 이런 RESTful API를 제공하고 있으며 API를 통해 제공되는 데이터는 수천 수만가지로 다양하게 존재합니다.

만약에 예를 들어 어떤 특정한 지역의 교통정보를 알고 싶다면 교통 정보API를 가져와서 정보를 입력만 한다면 교통정보를 받아올 수 있습니다. 

 

 

 

이번에 사용할 OpenWeatherMap사이트는 날씨정보 API를 제공하는 사이트로써, OrangeBoard WiFi+에서도 간단하게 날씨 데이터를 읽어올 수 있습니다.

예제 코드를 실행해보고 시리얼 모니터에 날씨정보를 받아오는 작업을 해보겠습니다.

 

 

 

 

 

 

 

 

2. OpenWeatherMap사용하기

 

먼저 OpenWeatherMap사이트(https://openweathermap.org)에 접속합니다.

 

 

 

 

 

 

 

 

 

사이트 회원가입을 마치고 로그인한 뒤에 API Keys를 눌러 API Key를 얻을 수 있는 페이지로 들어갑니다.

 

 

 

 

 

 

 

 

API Key를 복사합니다.

 

 

 

 

 

 

 

 

 

복사한 API Key를 소스코드의 #define VARID에 붙여넣습니다.

 

 

 

 

 

API사용법 확인하기

 

OpenWeatherMap의 API doc을 보면 어떻게 쓸 수 있는지 볼 수 있습니다.

 

 

사이트 상단에서 API버튼을 클릭합니다.

 

 

 

 

 

 

 

현재 날씨 데이터를 받아오는 API를 사용하기 때문에 Current Weather DataAPI doc을 클릭합니다.

 

 

 

 

 

 

 

 

By city name의 API call을 확인합니다.

 

도시 이름(city name)과 API key값만 있으면 API를 호출할 수 있음을 알 수 있습니다.

 

 

 

 

 

 

 

소스 코드

 

 

#include "WizFi360.h"

#define SERIAL_BAUDRATE   115200
#define SERIAL1_BAUDRATE  115200

#define VARID  "9cbe77b703b0c172de8e80ade55ae511"

char ssid[] = "nepes_wireless_guest";
char pass[] = "gu@st12345";
int status = WL_IDLE_STATUS;

char server[] = "api.openweathermap.org";  // Openweathermap API 주소

unsigned long lastConnectionTime = 0;         // 서버에 접속한 마지막 시간 (MilliSecond)
const unsigned long postingInterval = 10000L; // 서버에 데이터를 요청할 Delay (MilliSecond)

boolean readingVal;
boolean getIsConnected = false;
int val, temp;
int tempVal;
int pos = 0;
int count = 0;

String rcvbuf;

// WiFiClient 오브젝트 선언        
WiFiClient client;

void httpRequest();
void printWifiStatus();

void setup() {
  // initialize serial for debugging
  Serial.begin(SERIAL_BAUDRATE);
  // initialize serial for WizFi360 module
  Serial3.begin(SERIAL1_BAUDRATE);
  // initialize WizFi360 module
  WiFi.init(&Serial3);

  if (WiFi.status() == WL_NO_SHIELD) {  // WiFi보드에 문제가 있다면
    Serial.println("WiFi board error");  // 시리얼 모니터에 WiFi board error 출력
    while (true);
  }

  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);

    status = WiFi.begin(ssid, pass);
  }

  Serial.println("You're connected to the network");
  printWifiStatus();
}

void loop() {
  String rcvbuf;
  String valString;
  while (client.available()) {

    if ( rcvbuf.endsWith("{\"temp\":")) {
      readingVal = true;
      valString = "";
    }

    char c = client.read();
    //Serial.write(c);


    if ( c != NULL ) {
      if (rcvbuf.length() > 200)
        rcvbuf = "";
      rcvbuf += c;
      //Serial.write(c);
    }

    if (readingVal) {
      if (c != ',' ) {
        valString += c;
        //Serial.write(c);
      }
      else {
        readingVal = false;
        tempVal = valString.toInt(); // 온도값를 String에서 Integer로 변환
        Serial.print("현재 온도는 ");
        Serial.print(tempVal-273);  
        Serial.println("C 입니다.");
      }
    }
  }

  tempVal = 0;

  if (millis() - lastConnectionTime > postingInterval) { // interval 시간이 충족되었다면
    httpRequest(); //데이터 호출
  }
}

// 서버에 날씨 데이터 호출 함수
void httpRequest() {
  Serial.println();
  client.stop();

  // 제대로 서버에 연결되었을 경우
  if (client.connect(server, 80)) {
    Serial.println("Connecting...");

    // HTTP 요청을 보냄
    client.print("GET /data/2.5/weather?q=Seoul,kr&appid=");  // 서울의 날씨를 확인 (다른 지역의 날씨를 확인할려면 중간에 Seoul,kr 부분을 "지역,나라"로 바꿔주시면 됩니다.)
    //client.print("GET /data/2.5/weather?q=london,uk&appid=");  // 지역 변경 참고
    client.print(VARID);
    client.println(" HTTP/1.1");
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();

    // note the time that the connection was made
    lastConnectionTime = millis();
    getIsConnected = true;

  }

  // 제대로 서버에 연결이 되지 않았으면 Connection failed 메세지 출력
  else {
    Serial.println("Connection failed");
    getIsConnected = false;
  }
}

// WiFi 연결 상태 정보 출력 함수
void printWifiStatus() {
  // print the SSID of the network you're attached to
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength
  long rssi = WiFi.RSSI();
  Serial.print("Signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

 

 

 

 

 

코드의 아래 두 부분에 API Key과 현재 사용 중인 WiFi의 ssid와 password를 입력합니다.

 

#define VARID  ""  //API Key값 입력

char ssid[] = "ssid";   //ssid 입력
char pass[] = "pass";   //password 입력

 

 

 

 

 

지역 변경이 필요한 경우에는 아래 부분에서 Seoul,kr을 지운 뒤 변경하면 됩니다.

※ 지역은 OpenWeatherMap사이트내에서 검색이 되는 곳만 입력할 수 있습니다.

client.print("GET /data/2.5/weather?q=Seoul,kr&appid="); 

 

 

 

 

 

 

 

 

위 코드를 업로드하고 실행하면 아래와 같이 현재 지역의 온도가 출력됩니다.

 

 

 

 

 

 

 

 

 

 

 

OpenWeatherMap에서 데이터를 호출하면 아래와 같이 JSON형식의 데이터를 응답받습니다.

 

 

 

 

 

 

 

 

이때 이번 예제에서 구하고자 하는 값은 온도이기 때문에 아래 이미지 부분을 문자열 함수를 통해 추출합니다.

 

 

 

 

 

 

코드에서는 myString.endsWith(myString2)함수를 통해 값을 추출합니다.

만일 온도가 아닌 다른 값을 추출하고자 하는 경우에는 "temp":가 아닌 다른 값을 입력하면 됩니다.

 

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!