Я пытаюсь использовать API weatherbit.io для доступа к информации AQI в моем приложении для Android. Сценарий AqiInfoScript используется для доступа к API, а сценарий Update AQI используется для вывода значения.

AqiInfoScript:

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

public class AqiInfoScript : MonoBehaviour
{
    private float timer;
    public float minutesBetweenUpdate;
    private float latitude;
    private float longitude;
    private bool locationInitialized;
    public static string cityName;
    public static double currentAqi;

    private readonly string baseWeatherbitURL = "https://api.weatherbit.io/v2.0/current/airquality?";
    private readonly string key = "*********************";

    public void Begin()
    {
        latitude = GPS.latitude;
        longitude = GPS.longitude;
        locationInitialized = true;

    }
    void Update()
    {
        if (locationInitialized)
        {
            if (timer <= 0)
            {
                StartCoroutine(GetAqi());
                timer = minutesBetweenUpdate * 60;
            }
            else
            {
                timer -= Time.deltaTime;
            }
        }
    }
    private IEnumerator GetAqi()
    {
        string weatherbitURL = baseWeatherbitURL + "lat=" + latitude + "&lon=" + longitude + "&key=" 
        + key;
        UnityWebRequest aqiInfoRequest = UnityWebRequest.Get(weatherbitURL);

        yield return aqiInfoRequest.SendWebRequest();

        //error
        if (aqiInfoRequest.isNetworkError || aqiInfoRequest.isHttpError)
        {
            Debug.LogError(aqiInfoRequest.error);
            yield break;
        }

        JSONNode aqiInfo = JSON.Parse(aqiInfoRequest.downloadHandler.text);

        cityName = aqiInfo["city_name"];
        currentAqi = aqiInfo["data"]["aqi"];
    }
}

Сценарий UpdateAQI

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

public class UpdateAQI : MonoBehaviour
{
    public Text airquality;
    //public Text coordinates;

    private void Update()
    {
        airquality.text = "Current Aqi:  " + AqiInfoScript.currentAqi.ToString();
    }
}

Текущий выход : текущий AQI: 0 Желаемый результат : текущий AQI: 129,0000

-2
parthshukla 4 Сен 2020 в 11:56

1 ответ

Лучший ответ

Проблема

Насколько я понимаю, API возвращает ваш запрос < / a> например для lat=42, lon=-7 следующий JSON

{
    "data":[
               {
                   "mold_level":1,
                   "aqi":54,
                   "pm10":7.71189,
                   "co":298.738,
                   "o3":115.871,
                   "predominant_pollen_type":"Molds",
                   "so2":0.952743,
                   "pollen_level_tree":1,
                   "pollen_level_weed":1,
                   "no2":0.233282,
                   "pm25":6.7908,
                   "pollen_level_grass":1
               }
           ],
    "city_name":"Pías",
    "lon":-7,
    "timezone":"Europe\/Madrid",
    "lat":42,
    "country_code":"ES",
    "state_code":"55"
}

Как видите, "data" на самом деле является массивом . Вы относитесь к нему как к единственному значению.

За кулисами

К сожалению, используемая вами библиотека SmipleJson весьма подвержена ошибкам, потому что она не генерирует никаких исключений для опечаток, а просто не работает и использует значение по умолчанию.

Вы можете увидеть это, например, в

public override JSONNode this[string aKey]
{
    get
    {
        if (m_Dict.ContainsKey(aKey))
            return m_Dict[aKey];
        else
            return new JSONLazyCreator(this, aKey);
    }
    ....
}

А также

public static implicit operator double(JSONNode d)
{
    return (d == null) ? 0 : d.AsDouble;
}

Решение

Скорее должно быть

cityName = aqiInfo["city_name"];
currentAqi = aqiInfo["data"][0]["aqi"].AsDouble;

Debug.Log($"cityName = {cityName}\ncurrentAqi = {currentAqi}");

В общем, я бы предложил использовать JsonUtility.FromJson и лучше реализовать необходимая структура данных в C #, например:

[Serializable]
public class Data   
{
    public int mold_level;
    public double aqi;
    public double pm10;
    public double co;
    public double o3;
    public string predominant_pollen_type;
    public double so2;
    public int pollen_level_tree;
    public int pollen_level_weed;
    public double no2;
    public double pm25;
    public int pollen_level_grass;
}

[Serializable]
public class Root    
{
    public List<Data> data;
    public string city_name;
    public int lon;
    public string timezone;
    public int lat;
    public string country_code;
    public string state_code;
}

А затем вы использовали бы

var aqiInfo = JsonUtility.FromJson<Root>(aqiInfoRequest.downloadHandler.text);

cityName = aqiInfo.city_name;
currentAqi = aqiInfo.data[0].aqi;

Debug.Log($"cityName = {cityName}\ncurrentAqi = {currentAqi}");

Для меня, как сказано с фиктивными значениями lat=42, lon=-7, оба раза он распечатывает, как ожидалось

cityName = Pías
currentAqi = 54
UnityEngine.Debug:Log(Object)
<GetAqi>d__18:MoveNext() (at Assets/Example.cs:109)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
0
derHugo 4 Сен 2020 в 14:14