[SKKU DT] 67일차 -유니티 Rest API 활용하기(날씨, 정보, 사진)

2024. 2. 5. 15:02SKKU DT

728x90
반응형

OpenWeatherMap에서 날씨 정보 받기

예전에도 했지만 OpenWeatherMap에서 날씨 API를 유니티로 받아올 것이다.

 

 

Сurrent weather and forecast - OpenWeatherMap

Access current weather data for any location on Earth including over 200,000 cities! The data is frequently updated based on the global and local weather models, satellites, radars and a vast network of weather stations. how to obtain APIs (subscriptions w

openweathermap.org

 

 

내 API를 확인한다.

 

 


 

 

WeatherAPI 스크립트 작성

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class WeatherAPI : MonoBehaviour
{
    private readonly string apiKey = "Your API";
    private readonly string city = "Seoul";

    void Start()
    {
        StartCoroutine(GetWeatherInfo());
    }

    IEnumerator GetWeatherInfo()
    {
        string url = $"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={apiKey}&units=metric";

        using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
        {
            yield return webRequest.SendWebRequest();

            if(webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.Log($"Error : {webRequest.error}");
            }
            else
            {
                ProcessWeatherInfo(webRequest.downloadHandler.text);
            }
        }
    }

    private void ProcessWeatherInfo(string jsonData)
    {
        //Json 파싱 로직 구현
        Debug.Log($"Received weather information: {jsonData}");
    }
}

 

잘 불러왔다면 Console 창에 아래와 같은 내용이 나온다.

 

url을 Postman에 넣으면 잘 정리된 JSON을 볼 수 있다.

 

파싱을 돌리면, 아래처럼 정렬시킬 수 있다.

*가장 바깥 Serializable인 WeatherData는 스스로 만들어야 하므로 잘 보고 익혀야 한다.

[System.Serializable]
public class WeatherData
{
    public Coord coord;
    public Weather[] weather;
    public string baseInfo;
    public Main main;
    public int visibility;
    public Wind wind;
    public Rain rain;
    public Clouds clouds;
    public long dt;
    public Sys sys;
    public int timezone;
    public int id;
    public string name;
    public int cod;
}

[System.Serializable]
public class Coord
{
    public float lon;
    public float lat;
}

[System.Serializable]
public class Weather
{
    public int id;
    public string main;
    public string description;
    public string icon;
}

[System.Serializable]
public class Main
{
    public float temp;
    public float feels_like;
    public float temp_min;
    public float temp_max;
    public int pressure;
    public int humidity;
    public int sea_level;
    public int grnd_level;
}

[System.Serializable]
public class Wind
{
    public float speed;
    public int deg;
    public float gust;
}

[System.Serializable]
public class Rain
{
    public float _1h; // 필드명 수정
}

[System.Serializable]
public class Clouds
{
    public int all;
}

[System.Serializable]
public class Sys
{
    public int type;
    public int id;
    public string country;
    public long sunrise;
    public long sunset;
}

 

 

파싱 돌린 코드도 WeatherAPI 스크립트에 넣어주고, 필요한 정보를 Debug.Log를 통해서 보면,

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class WeatherAPI : MonoBehaviour
{
    private readonly string apiKey = "Your API";
    private readonly string city = "Seoul";

    void Start()
    {
        StartCoroutine(GetWeatherInfo());
    }

    IEnumerator GetWeatherInfo()
    {
        string url = $"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={apiKey}&units=metric";

        using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
        {
            yield return webRequest.SendWebRequest();

            if(webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.Log($"Error : {webRequest.error}");
            }
            else
            {
                ProcessWeatherInfo(webRequest.downloadHandler.text);
            }
        }
    }

    private void ProcessWeatherInfo(string jsonData)
    {
        //Json 파싱 로직 구현
        WeatherData weatherData = JsonUtility.FromJson<WeatherData>(jsonData);

        Debug.Log($"City: {weatherData.name}");
        Debug.Log($"Temperature: {weatherData.main.temp}");
        Debug.Log($"Feels Like: {weatherData.main.feels_like}");

        //Debug.Log($"Received weather information: {jsonData}");
    }


    //Json 파싱
    [System.Serializable]
    public class WeatherData
    {
        public Coord coord;
        public Weather[] weather;
        public string baseInfo;
        public Main main;
        public int visibility;
        public Wind wind;
        public Rain rain;
        public Clouds clouds;
        public long dt;
        public Sys sys;
        public int timezone;
        public int id;
        public string name;
        public int cod;
    }
    
    [System.Serializable]
    public class Coord
    {
        public float lon;
        public float lat;
    }

    [System.Serializable]
    public class Weather
    {
        public int id;
        public string main;
        public string description;
        public string icon;
    }

    [System.Serializable]
    public class Main
    {
        public float temp;
        public float feels_like;
        public float temp_min;
        public float temp_max;
        public int pressure;
        public int humidity;
        public int sea_level;
        public int grnd_level;
    }

    [System.Serializable]
    public class Wind
    {
        public float speed;
        public int deg;
        public float gust;
    }

    [System.Serializable]
    public class Rain
    {
        public float _1h; // 필드명 수정
    }

    [System.Serializable]
    public class Clouds
    {
        public int all;
    }

    [System.Serializable]
    public class Sys
    {
        public int type;
        public int id;
        public string country;
        public long sunrise;
        public long sunset;
    }
}

 

Debug.Log로 찍은 세 정보가 잘 나오는 것을 볼 수 있다.

 

해당 API의 구조는, WeatherData라는 가장 바깥의 System.Serializable 안에 여러 정보들이 있고, 그 중 하나인 Main 이름의 System.Serializable안에 temps, feels_like 등의 정보들이 들어있는 것이다.

 

 


 

 

유니티 상에 Text로 나타내기 위해서 TMPro를 추가하여 수정하면 유니티에서도 text 형태로 값을 볼 수 있다.

using TMPro;
[SerializeField] TMP_Text text1;
text1.text = $"City: {weatherData.name}\nTemperature: {weatherData.main.temp}\nFeels Like: {weatherData.main.feels_like}";

 

 


 

 

Countries API 사용하기

https://restcountries.com/

 

REST Countries

 

restcountries.com

 

페이지 아래를 가면 엔드포인트 url들을 볼 수 있다.

 

 

Postman에서는 아래와 같이 볼 수 있다.

 

 

위 데이터의 JSON 파싱은 아래의 코드로 가져올 수 있다.

**여기서 가장 처음에 리스트로 시작하는 JSON을 가져오는 방법을 볼 수 있다.

System.Serializable로 가장 바깥의 List<CountryData>를 countries로 가져온 후 UpdateCountryInfo에 바로 countryDataArray.countries[0]을 넣어 함수 아래에는 [0]에 대한 인덱스의 정보만 가져오는 것으로 나타내었다.

[System.Serializable]
public class CountryDataArray
{
    public List<CountryData> countries;
}

[System.Serializable]
public class CountryData
{
    public Name name;
    public List<string> tld;
    public string cca2;
    public string ccn3;
    public string cca3;
    public string cioc;
    public bool independent;
    public string status;
    public bool unMember;
    public Currencies currencies;
    public Idd idd;
    public List<string> capital;
    public List<string> altSpellings;
    public string region;
    public string subregion;
    public Language languages;
    public Translations translations;
    public List<float> latlng;
    public bool landlocked;
    public List<string> borders;
    public float area;
    public Demonyms demonyms;
    public string flag;
    public Maps maps;
    public int population;
    public Gini gini;
    public string fifa;
    public Dictionary<string, string> car;
    public List<string> timezones;
    public List<string> continents;
    public Flags flags;
    public CoatOfArms coatOfArms;
    public string startOfWeek;
    public CapitalInfo capitalInfo;
    public PostalCode postalCode;
}

[System.Serializable]
public class Name
{
    public string common;
    public string official;
    public NativeName nativeName;
}

[System.Serializable]
public class NativeName
{
    public Deu deu;
}

[System.Serializable]
public class Deu
{
    public string official;
    public string common;
}

[System.Serializable]
public class Currencies
{
    public Eur eur;
}

[System.Serializable]
public class Eur
{
    public string name;
    public string symbol;
}

[System.Serializable]
public class Idd
{
    public string root;
    public List<string> suffixes;
}

[System.Serializable]
public class Language
{
    public string deu;
}

[System.Serializable]
public class Translations
{
    public Dictionary<string, NativeName> translations;
}

[System.Serializable]
public class Demonyms
{
    public NativeName eng;
    public NativeName fra;
}

[System.Serializable]
public class Maps
{
    public string googleMaps;
    public string openStreetMaps;
}

[System.Serializable]
public class Gini
{
    public float _2016;
}

[System.Serializable]
public class Flags
{
    public string png;
    public string svg;
    public string alt;
}

[System.Serializable]
public class CoatOfArms
{
    public string png;
    public string svg;
}

[System.Serializable]
public class CapitalInfo
{
    public List<float> latlng;
}

[System.Serializable]
public class PostalCode
{
    public string format;
    public string regex;
}

 

 

아래는 특정 부분만 가져오는 코드이다.

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;

public class RestCountries : MonoBehaviour
{
    //[SerializeField] TMP_Text text1;
    //[SerializeField] TMP_Text text2;
    //[SerializeField] TMP_Text text3;

    private readonly string country = "deutschland";

    void Start()
    {
        StartCoroutine(GetWeatherInfo());
    }

    IEnumerator GetWeatherInfo()
    {
        string url = $"https://restcountries.com/v3.1/name/{country}";

        using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
        {
            yield return webRequest.SendWebRequest();

            if (webRequest.result == UnityWebRequest.Result.ConnectionError || webRequest.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.Log($"Error : {webRequest.error}");
            }
            else
            {
                CountryDataArray countryDataArray = JsonUtility.FromJson<CountryDataArray>("{\"countries\":" + webRequest.downloadHandler.text + "}");
                UpdateCountryInfo(countryDataArray.countries[0]);
            }
        }
    }

    private void UpdateCountryInfo(CountryData countryData)
    {
        Debug.Log($"Name: {countryData.name.common}");
        Debug.Log($"Population: {countryData.population}");

        //Debug.Log($"Received country information: {jsonData}");
    }
}

 

 


 

 

API로 이미지(image), 사진 불러오기

https://api.nasa.gov/

 

NASA Open APIs

 

api.nasa.gov

 

아래의 url로 접근할 수 있다.

https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/latest_photos?api_key={apiKey}

 

잘 받아와진다면, Postman에 불러와지는 것을 볼 수 있다.

 

 

파싱하는 코드는 아래와 같다.

[Serializable]
public class Root
{
    public List<LatestPhoto> latest_photos;
}

[Serializable]
public class LatestPhoto
{
    public int id;
    public int sol;
    public Camera camera;
    public string img_src;
    public string earth_date;
    public Rover rover;
}

[Serializable]
public class Camera
{
    public int id;
    public string name;
    public int rover_id;
    public string full_name;
}

[Serializable]
public class Rover
{
    public int id;
    public string name;
    public string landing_date;
    public string launch_date;
    public string status;
    public int max_sol;
    public string max_date;
    public int total_photos;
    public List<Camera> cameras;
}

 

 

아래와 같이 코드를 적고 실행하면, RawImage에 사진이 뜬다!

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class ImageAPI : MonoBehaviour
{
    public RawImage imageDisplay;

    private const string apiKey = "Your API";
    private const string url = "https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/latest_photos?api_key=" + apiKey;

    private IEnumerator Start()
    {
        UnityWebRequest request = UnityWebRequest.Get(url);

        yield return request.SendWebRequest();

        if(request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError("NASA API 요청 실패: " + request.error);
            yield break;
        }

        //파싱하기
        Root root = JsonUtility.FromJson<Root>(request.downloadHandler.text);

        if(root.latest_photos != null && root.latest_photos.Length > 0)
        {
            //최신 사진 정보 출력하기
            LatestPhoto latestPhoto = root.latest_photos[0];
            Debug.Log("최신 사진의 ID: " + latestPhoto.id);
            Debug.Log("최신 사진의 날짜: " + latestPhoto.earth_date);
            Debug.Log("최신 사진의 URL: " + latestPhoto.img_src);

            //이미지 다운로드 및 표시
            StartCoroutine(LoadImage(latestPhoto.img_src));
        }
        else
        {
            Debug.Log("최신 사진이 없습니다.");
        }
    }

    private IEnumerator LoadImage(string url)
    {
        UnityWebRequest request = UnityWebRequestTexture.GetTexture(url);

        yield return request.SendWebRequest();

        if(request.result != UnityWebRequest.Result.Success)
        {
            Debug.Log("이미지 로드 실패: " + request.error);
            yield break;
        }

        //다운로드한 텍스쳐를 RawImage에 표시
        Texture2D texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
        imageDisplay.texture = texture;
    }

    //Json 파싱
    [Serializable]
    public class Root
    {
        public LatestPhoto[] latest_photos;
    }

    [Serializable]
    public class LatestPhoto
    {
        public int id;
        public int sol;
        public Camera camera;
        public string img_src;
        public string earth_date;
        public Rover rover;
    }

    [Serializable]
    public class Camera
    {
        public int id;
        public string name;
        public int rover_id;
        public string full_name;
    }

    [Serializable]
    public class Rover
    {
        public int id;
        public string name;
        public string landing_date;
        public string launch_date;
        public string status;
        public int max_sol;
        public string max_date;
        public int total_photos;
        public List<Camera> cameras;
    }
}

728x90
반응형