using Backend.Models; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Quartz; using Repository.BackendRepository.Implement; using Repository.BackendRepository.Interface; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; using System.Linq; using NCrontab; using BackendWorkerService.Services.Implement; using RainApi; using System.Globalization; namespace BackendWorkerService.Quartz.Jobs { [DisallowConcurrentExecution] class WeatherAPIJob : IJob { private readonly ILogger logger; private readonly IBackgroundServiceRepository backgroundServiceRepository; private readonly IBackendRepository backendRepository; private readonly ILogger loggers; public WeatherAPIJob(ILogger logger, IBackgroundServiceRepository backgroundServiceRepository, IBackendRepository backendRepository, ILogger loggers) { this.logger = logger; this.backgroundServiceRepository = backgroundServiceRepository; this.backendRepository = backendRepository; this.loggers = loggers; } public string Fetch_PostWithJSONFormat(string url, string paramter) { try { string username = "stanGG"; string password = "St12345678"; string encoded = Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password)); HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(url); Postrequest.Method = "POST"; Postrequest.Headers.Add("Authorization", "Basic " + encoded); Postrequest.PreAuthenticate = true; using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream())) { if (paramter != "NULL") { string json = ""; streamWriter.Write(json); } else { string json = ""; streamWriter.Write(json); } } HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd(); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(responseString); string jsonText = JsonConvert.SerializeXmlNode(xmlDoc); //JObject resultVal = (JObject)JsonConvert.DeserializeObject(jsonText); return jsonText; } catch (Exception ex) { logger.LogError("【WeatherAPIJob】" + "Fetch_PostWithJSONFormat:" + ex.ToString()); throw ex; } } public async Task Execute(IJobExecutionContext context) { Task_Detail task_Detail = new Task_Detail(loggers, backendRepository); try { var obixApiConfig = new ObixApiConfig(); string encoded = string.Empty; #region 取得obix 設定 var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'"; var variableObix = await backgroundServiceRepository.GetAllAsync(sqlObix); obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault(); obixApiConfig.UserName = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault(); obixApiConfig.Password = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault(); encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); #endregion 取得obix 設定 //取得氣象預報 if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_weateher")) { try { await task_Detail.InsertWorkTime("WeatherAPI", "api_weateher"); var client = new HttpClient(); var DataNO = "F-D0047-061"; var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-D0047-061?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&format=JSON&locationName=%E4%BF%A1%E7%BE%A9%E5%8D%80&elementName=Wx,PoP12h,T,RH"; HttpResponseMessage response = client.GetAsync(UVUri).Result; String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString(); var observation = JsonConvert.DeserializeObject(jsonUVs); logger.LogInformation("【WeatherAPIJob】【取得成功氣象預報】"); if (observation.Success != "true") { logger.LogInformation("【WeatherAPIJob】【取得氣象預報資料不正確】"); } else { logger.LogInformation("【WeatherAPIJob】【開始存入氣象預報到資料庫】"); List> WeatherAPIdbS = new List>(); var Type_ALL = observation.Records.Locations[0].Location[0].WeatherElement; foreach (var a in Type_ALL) { foreach (var b in a.Time) { if (a.ElementName == "PoP12h" || a.ElementName == "Wx") { if (Convert.ToDateTime(b.StartTime) > DateTime.Now.AddDays(1)) { break; } } else { if (Convert.ToDateTime(b.DataTime) > DateTime.Now.AddDays(1)) { break; } } Dictionary WeatherAPIdb = new Dictionary() { { "@weather_type", a.ElementName}, { "@data_no", DataNO}, { "@get_value", b.ElementValue[0].Value}, { "@measures", b.ElementValue[0].Measures}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; if (a.ElementName == "PoP12h" || a.ElementName == "Wx") { WeatherAPIdb.Add("@start_time", b.StartTime); WeatherAPIdb.Add("@end_time", b.EndTime); } else { WeatherAPIdb.Add("@start_time", b.DataTime); WeatherAPIdb.Add("@end_time", null); } WeatherAPIdbS.Add(WeatherAPIdb); if (a.ElementName == "Wx") { Dictionary TWeatherAPIdb = new Dictionary() { { "@weather_type", "WxV"}, { "@data_no", DataNO}, { "@get_value", b.ElementValue[1].Value}, { "@measures", b.ElementValue[1].Measures}, { "@start_time", b.StartTime}, { "@end_time", b.EndTime}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; WeatherAPIdbS.Add(TWeatherAPIdb); } } } await backendRepository.AddMutiByCustomTable(WeatherAPIdbS, "api_weateher"); } await task_Detail.InsertWorkTime_End("WeatherAPI", "api_weateher"); } catch (Exception ex) { await task_Detail.WorkFail("WeatherAPI", "api_weateher", ex.Message.ToString()); } } if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_rain")) { try { await task_Detail.InsertWorkTime("WeatherAPI", "api_rain"); WebClient mywebClient = new WebClient(); mywebClient.DownloadFile("https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/W-C0033-003?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&downloadType=WEB&format=CAP", @"root/PowerfulRain.xml"); XmlDocument doc = new XmlDocument(); doc.Load("root/PowerfulRain.xml"); var json = JsonConvert.SerializeXmlNode(doc); var haveinfo = json.Split("info"); if (haveinfo.Length > 2) { var observation = JsonConvert.DeserializeObject(json); var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault(); var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'"; var NeedCallApi = await backendRepository.GetOneAsync(sql); Dictionary RainAPIdb = new Dictionary() { { "@msgType", observation.Alert.MsgType}, { "@headline", observation.Alert.Info.Headline}, { "@areaDesc", area}, { "@onset", observation.Alert.Info.Onset}, { "@expires", observation.Alert.Info.Expires}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain"); if (NeedCallApi != 0) { var val = RainValue(observation.Alert.MsgType, observation.Alert.Info.Headline); if (val < 5) { var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString()); UpdatedNiagara("api_rain", ReStr, id); } } FolderFunction folderFunction = new FolderFunction(); folderFunction.DeleteFile("root/PowerfulRain.xml"); await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain"); } else { var observation = JsonConvert.DeserializeObject(json); var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault(); var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'"; var NeedCallApi = await backendRepository.GetOneAsync(sql); Dictionary RainAPIdb = new Dictionary() { { "@msgType", observation.Alert.MsgType}, { "@headline", observation.Alert.Info.Headline}, { "@areaDesc", area}, { "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}, { "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain"); if (NeedCallApi != 0) { var val = RainValue(observation.Alert.MsgType, observation.Alert.Info.Headline); if (val < 5) { var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString()); UpdatedNiagara("api_rain", ReStr, id); } } FolderFunction folderFunction = new FolderFunction(); folderFunction.DeleteFile("root/PowerfulRain.xml"); await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain"); } } catch (Exception ex) { await task_Detail.WorkFail("WeatherAPI", "api_rain", ex.Message.ToString()); logger.LogError($"apirain error: {ex}, {ex.InnerException}, {ex.Message}"); } } if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_typhoon")) { try { await task_Detail.InsertWorkTime("WeatherAPI", "api_typhoon", null , new DateTime(DateTime.Now.AddDays(1).Year, DateTime.Now.AddDays(1).Month, DateTime.Now.AddDays(1).Day, 0, 25, 0)); WebClient mywebClient = new WebClient(); mywebClient.DownloadFile("https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/W-C0034-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&downloadType=WEB&format=CAP", @"root/Typhoon.xml"); XmlDocument doc = new XmlDocument(); doc.Load("root/Typhoon.xml"); var json = JsonConvert.SerializeXmlNode(doc); var haveinfo = json.Split("info"); if (haveinfo.Length > 2) { var observation = JsonConvert.DeserializeObject(json); var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault(); var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'"; var NeedCallApi = await backendRepository.GetOneAsync(sql); Dictionary EarthquakeAPIdb = new Dictionary() { { "@msgType", observation.Alert.MsgType}, { "@headline", observation.Alert.Info.Headline}, { "@areaDesc", area}, { "@urgency",observation.Alert.Info.Urgency}, { "@severity",observation.Alert.Info.Severity}, { "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}, { "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon"); if (NeedCallApi != 0) { if (observation.Alert.Info.Urgency != null && observation.Alert.Info.Urgency != "Expected") { var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency); UpdatedNiagara("api_typhoon", ReStr, id); } } FolderFunction folderFunction = new FolderFunction(); folderFunction.DeleteFile("root/Typhoon.xml"); await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon"); } else { var observation = JsonConvert.DeserializeObject(json); var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault(); var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'"; var NeedCallApi = await backendRepository.GetOneAsync(sql); Dictionary EarthquakeAPIdb = new Dictionary() { { "@msgType", observation.Alert.MsgType}, { "@headline", observation.Alert.Info.Headline}, { "@areaDesc", area}, { "@urgency",observation.Alert.Info.Urgency}, { "@severity",observation.Alert.Info.Severity}, { "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}, { "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon"); if (NeedCallApi != 0) { if (observation.Alert.Info.Urgency != null && observation.Alert.Info.Urgency != "Expected") { var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency); UpdatedNiagara("api_typhoon", ReStr, id); } } FolderFunction folderFunction = new FolderFunction(); folderFunction.DeleteFile("root/Typhoon.xml"); await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon"); } } catch (Exception ex) { await task_Detail.WorkFail("WeatherAPI", "api_typhoon", ex.Message.ToString()); } } if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_earthquake")) { try { await task_Detail.InsertWorkTime("WeatherAPI", "api_earthquake", null, new DateTime(DateTime.Now.AddDays(1).Year, DateTime.Now.AddDays(1).Month, DateTime.Now.AddDays(1).Day, 0, 25, 0)); var client = new HttpClient(); var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/E-A0015-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&format=JSON&areaName=%E8%87%BA%E5%8C%97%E5%B8%82"; HttpResponseMessage response = client.GetAsync(UVUri).Result; String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString(); var j = JsonConvert.DeserializeObject(jsonUVs); var observation = JsonConvert.DeserializeObject(jsonUVs); if (!observation.Success) { logger.LogInformation("【WeatherAPIJob】【取得地震觀測資料不正確】"); } else { logger.LogInformation("【WeatherAPIJob】【開始存入地震觀測到資料庫】"); List> EarthquakeAPIdbS = new List>(); var nowNo = await backendRepository.GetOneAsync("select if( Max(earthquakeNo) is null ,0,Max(earthquakeNo)) earthquakeNo from api_earthquake where newEarthquake = 1"); foreach (var a in observation.Records.Earthquake) { if (a.EarthquakeNo <= nowNo) { Dictionary EarthquakeAPIdb = new Dictionary() { { "@earthquakeNo", a.EarthquakeNo}, { "@newEarthquake", 0}, { "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)}, { "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue}, { "@areaName", null}, { "@areaIntensity", null}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; EarthquakeAPIdbS.Add(EarthquakeAPIdb); break; } else { if (a.Intensity.ShakingArea.Count > 0) { Dictionary EarthquakeAPIdb = new Dictionary() { { "@earthquakeNo", a.EarthquakeNo}, { "@newEarthquake", 1}, { "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)}, { "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue}, { "@areaName", a.Intensity.ShakingArea[0].CountyName}, { "@areaIntensity", a.Intensity.ShakingArea[0].AreaIntensity}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; var Nag = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/SeverityLEVL_LMI/set", a.Intensity.ShakingArea[0].AreaIntensity.ToString()); if (Nag.Contains("err")) { EarthquakeAPIdb.Add("@niagara", Nag); } else { EarthquakeAPIdb.Add("@niagara", "success"); } EarthquakeAPIdbS.Add(EarthquakeAPIdb); } else { Dictionary EarthquakeAPIdb = new Dictionary() { { "@earthquakeNo", a.EarthquakeNo}, { "@newEarthquake", 1}, { "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)}, { "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue}, { "@areaName", null}, { "@areaIntensity", null}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; var Nag = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/SeverityLEVL_LMI/set", "NULL"); if (Nag.Contains("err")) { EarthquakeAPIdb.Add("@niagara", Nag); } else { EarthquakeAPIdb.Add("@niagara", "success"); } EarthquakeAPIdbS.Add(EarthquakeAPIdb); } } } await backendRepository.AddMutiByCustomTable(EarthquakeAPIdbS, "api_earthquake"); } await task_Detail.InsertWorkTime_End("WeatherAPI", "api_earthquake"); } catch (Exception ex) { await task_Detail.WorkFail("WeatherAPI", "api_earthquake", ex.Message.ToString()); } } if (await task_Detail.GetNeedWorkTask("WeatherAPI", "set_weather")) { try { await task_Detail.InsertWorkTime("WeatherAPI", "set_weather"); var sql = @$"SELECT id, weather_type, get_value FROM api_weateher where id in (select MAX(id) from api_weateher where start_time < NOW() group by weather_type) order by start_time desc"; var types = await backendRepository.GetAllAsync(sql); var T = types.Where(a => a.weather_type == "T").FirstOrDefault(); var RbT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set", T.get_value); UpdatedNiagara("api_weateher", RbT, T.id); var RH = types.Where(a => a.weather_type == "RH").FirstOrDefault(); var RHT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set", RH.get_value); UpdatedNiagara("api_weateher", RHT, RH.id); var PoP12h = types.Where(a => a.weather_type == "PoP12h").FirstOrDefault(); var PoP12hT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set", PoP12h.get_value); UpdatedNiagara("api_weateher", PoP12hT, PoP12h.id); var Wx = types.Where(a => a.weather_type == "Wx").FirstOrDefault(); var WxT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set", Wx.get_value); UpdatedNiagara("api_weateher", WxT, Wx.id); await task_Detail.InsertWorkTime_End("WeatherAPI", "set_weather"); } catch (Exception ex) { await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message.ToString()); } } } catch (Exception exception) { logger.LogError("【WeatherAPIJob】【任務失敗】"); logger.LogError("【WeatherAPIJob】【任務失敗】[Exception]:{0}", exception.ToString()); } } public int RainValue(string Ty, string Headline) { var rint = 5; if (Ty == "") { return 0; } else { if (Headline.Contains("大雨")) { rint = 1; } else if (Headline.Contains("豪雨")) { rint = 2; } else if (Headline.Contains("大豪雨")) { rint = 3; } else if (Headline.Contains("超大豪雨")) { rint = 4; } } return rint; } public async void UpdatedNiagara(string DBTableName, string ResponseStr, int CheckNumId) { try { var Su = "success"; if (ResponseStr.Contains("err")) { Su = ResponseStr; } Dictionary RainAPIdb = new Dictionary() { { "@niagara", Su} }; await backendRepository.UpdateOneByCustomTable(RainAPIdb, DBTableName, " id = " + CheckNumId); } catch (Exception ex) { logger.LogError("【WeatherAPIJob】" + "UpdatedNiagara:" + ex.ToString()); throw ex; } } } }