后期上传demo
步入正题了,如何做一款实时更新的天气预报software?
1.确定需要的数据,天气状况、最高/最低气温、当前气温、大气压、湿度、降水量、能见度、当前风向风速、PM2.5、卫星云图、雷达回波。
2.前面的我觉得只要能打开浏览器都能搞定,找相关的数据接口,api。网上有很多,收费,不收费,限量收费。各种各样的很多,大多数返回数据是json类型,就不多做累述了。自行查找。
3.最后两个卫星云图、雷达回波,没有对应的api接口,于是另寻出路。
4.中国气象台网站,第一次进来的时候我也是蒙圈的,html网页数据怎么获取,又没有指定接口,而且也不知道规律。很难搞。
5.对比数据,挨个下载图片进行循环播放,达到动态雷达图的效果。
通过上图不难看出,数据来源是按照分钟级别来刷新的。而且最近的一张图大约是当前时间往前推20分钟。最后一张图是当前时间往前推2小时20分钟。毕竟卫星传回地球,然后再解析上传,是需要时间的。所以能理解。但是这样不规律的数据是很头疼的。
只能通过一分一分的往前推,判断该时间是否有雷达图数据,有的话就下载(UnityWebRequestTexture)存储然后继续上一分钟判断,没有的话就继续上一分钟判断。从而达到获取2小时20分钟之内的所有雷达图数据。再进行循环播放,达到动态雷达图的效果。
每个周期有15张左右图片。
分析图片网址规律:
右键点击图片,新标签打开图片。
上图可以看出,有两个时间戳,第一个时间戳是UTC时间(国际时间)的 “年/月/日”,第二个时间戳是UTC时间(国际时间)的 “年月日时分00000”。.JPG之后的数据经过测试,属于无用数据,可以直接忽略。
注:把图片下载下来,注意图片的尺寸,ui尺寸对应上。
规律找到,通过计算、改变时间戳拼接成网址,就能挨个下载当前网站所有的雷达图数据了。
不说了,上实现代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class DownloadNephogram : MonoBehaviour
{
public RawImage rawImg;//显示图片的ui
public Dictionary Texture2DsDic = new Dictionary();//按照时间戳存储下载的图片
public List Texture2DsNum;//记录时间戳列表 后续排序使用
private int Year;
private int Month;
private int Day;
private int Hour;
private int Minute;
private int BeforeHour;
private int BackMinute;//回退时间,20分钟前有图像数据
public int TargetHour;//目标小时,回退2小时
public int CurrentHour;//当前小时
public int TargetMinute;//目标分钟,回退2小时
public int CurrentMinute;//当前分钟
public string UrlDateTime;//日期数据 第一个时间戳
public string UrlImageName;//图片名称数据 第二个时间戳
public bool IsLoaded;//已经下载完成
public float CurrentLoadNum;//当前加载的图片序列
Texture2D tex2d;
void Update()
{
TimeCalculate();
UpdateRawImg();
}
///
/// 时间戳计算、回退目标时间计算、刷新周期设置
///
void TimeCalculate()
{
Hour = DateTime.UtcNow.Hour;
if (BeforeHour != Hour)//达到每小时整点更新一次
{
StopCoroutine("DownLoadImage");
//Texture2Ds.Clear();
Texture2DsDic.Clear();
Texture2DsNum.Clear();
IsLoaded = false;
CurrentLoadNum = 0;
Year = DateTime.UtcNow.Year;
Month = DateTime.UtcNow.Month;
Day = DateTime.UtcNow.Day;
Hour = DateTime.UtcNow.Hour;
Minute = DateTime.UtcNow.Minute;
if (Minute < BackMinute)//时间回退判断
{
if (Hour == 0)//小时判断 如果是0点,回退就是23点
{
Hour = 23;
Minute = 60 - Minute + BackMinute;
DayJudge();
}
else
{
Hour--;
Minute = 60 - Minute + BackMinute;
}
}
FormatTime(Year, Month, Day, Hour, Minute);
if (Hour == 1)
TargetHour = 23;
else if (Hour == 0)
TargetHour = 22;
else
TargetHour = Hour - 2;
CurrentHour = Hour;
CurrentMinute = TargetMinute = Minute;
BeforeHour = Hour;
ForLoopDownLoad();//
}
}
///
/// 天数判断
///
void DayJudge()
{
if (Day == 1)//月份天数判断
{
if (Month == 1 || Month == 3 || Month == 5 || Month == 7 || Month == 8 || Month == 10 || Month == 12)//31天
{
if (Month == 1)//年份判断
Year--;
Day = 31;
}
else if (Month == 2)
{
if (Year % 4 == 0)//28天
Day = 28;
else//27天
Day = 27;
}
else//30天的月份
Day = 30;
}
}
///
/// 更新循环显示图片
///
void UpdateRawImg()
{
if (IsLoaded)
{
if (CurrentLoadNum > Texture2DsNum.Count-1)
CurrentLoadNum = 0;
if (Texture2DsDic.ContainsKey(Texture2DsNum[(int)CurrentLoadNum]))//判断该时间戳是否有图片,有就更新
{
rawImg.texture = Texture2DsDic[Texture2DsNum[(int)CurrentLoadNum]];
}
if (CurrentLoadNum >= 0)
{
CurrentLoadNum += 0.03f;
}
}
else
{
if (Texture2DsDic.Count>0)
{
Texture2DsNum.Sort();
/*因for循环下载,网速等原因使得字典存储无序;
所以用列表进行一次列表内的时间戳排序。
再用字典按序查找列表内的long类型时间戳。
达到顺序播放*/
IsLoaded = true;
}
}
}
///
/// 格式化时间戳
///
/// 年
/// 月
/// 日
/// 小时
/// 分钟
void FormatTime(int year, int month, int day, int hour, int minute)
{
UrlDateTime = $"{year:D4}/{month:D2}/{day:D2}";
UrlImageName = $"{year:D4}{month:D2}{day:D2}{hour:D2}{minute:D2}{"00000"}";
}
///
/// 利用for循环开启每一分钟的下载协程,同时下载这段时间内的所有图片。达到最快的下载速度。
/// 优点:下载速度快
/// 缺点:下载时无序,循环播放时需要考虑排序问题;性能消耗大,因暂时没想好怎么用线程开启网络下载,目前用的笨方法,希望大神指点。
/// 需要考虑临界时间的for循环判断,比如0点前2小时是23、22点。1点前2小时是0、23点。
///
void ForLoopDownLoad()
{
if (CurrentHour == 1)
{
for (int i = CurrentHour; i >= -1 && i <= 1; i--)
{
CurrentHour = i;
if (CurrentHour == -1)
{
CurrentHour = 23;
DayJudge();
}
//Debug.LogWarning(CurrentHour);
if (1 == CurrentHour)
{
if (CurrentMinute != 0)
{
for (int j = CurrentMinute; j > -1; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else
{
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else if (0 == CurrentHour)
{
for (int j = 59; j > -1; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else if (23 == CurrentHour)
{
for (int j = 59; j >= TargetMinute; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
if (CurrentMinute != TargetMinute)
{
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
else
{
StopCoroutine("DownLoadImage");
}
}
}
}
}
else if (CurrentHour == 0)
{
for (int i = CurrentHour; i >= -2 && i <= 0; i--)
{
CurrentHour = i;
if (CurrentHour == -1)
{
CurrentHour = 23;
DayJudge();
}
if (CurrentHour == -2)
CurrentHour = 22;
//Debug.LogWarning(CurrentHour);
if (0 == CurrentHour)
{
if (CurrentMinute != 0)
{
for (int j = CurrentMinute; j > -1; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else
{
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else if (23 == CurrentHour)
{
for (int j = 59; j > -1; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else if (22 == CurrentHour)
{
for (int j = 59; j >= TargetMinute; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
if (CurrentMinute != TargetMinute)
{
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
else
{
StopCoroutine("DownLoadImage");
}
}
}
}
}
else
{
for (int i = CurrentHour; i >= TargetHour; i--)
{
CurrentHour = i;
//Debug.LogWarning(CurrentHour);
if (TargetHour + 2 == CurrentHour)
{
if (CurrentMinute != 0)
{
for (int j = CurrentMinute; j > -1; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else
{
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else if (TargetHour + 1 == CurrentHour)
{
for (int j = 59; j > -1; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
}
else if (TargetHour == CurrentHour)
{
for (int j = 59; j >= TargetMinute; j--)
{
CurrentMinute = j;
//Debug.Log("现在是" + CurrentHour + "点" + CurrentMinute + "分");
if (CurrentMinute!=TargetMinute)
{
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
StartCoroutine("DownLoadImage");
}
else
{
StopCoroutine("DownLoadImage");
}
}
}
}
}
}
void ContinueLoad()
{
if (CurrentMinute == 0)
{
CurrentMinute = 59;
if (CurrentHour != 0)
CurrentHour--;
else
CurrentHour = 23;
}
else
{
CurrentMinute--;
}
FormatTime(Year, Month, Day, CurrentHour, CurrentMinute);
if (TargetHour != CurrentHour || TargetMinute != CurrentMinute)
StartCoroutine("DownLoadImage");
else
{
StopCoroutine("DownLoadImage");
IsLoaded = true;
}
}
///
/// 下载图片
///
///
IEnumerator DownLoadImage()
{
using (UnityWebRequest w = UnityWebRequestTexture.GetTexture("http://image.nmc.cn/product/" + UrlDateTime + Url + UrlImageName + ".JPG"))
{
long rec = long.Parse(UrlImageName);
yield return w.SendWebRequest();
if (w.isDone)
{
if (w.isNetworkError || w.isHttpError)
{
Debug.Log(w.error);
}
else
{
if (w.responseCode == 200)
{
tex2d = new Texture2D(width, height, TextureFormat.RGB24, false);
tex2d.LoadImage(w.downloadHandler.data);
if (Texture2DsDic.ContainsKey(rec))
{
Texture2DsDic[rec] = tex2d;
}
else
{
Texture2DsDic.Add(rec, tex2d);
}
Texture2DsNum.Add(rec);
}
}
}
}
}
}