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; using System.Text.RegularExpressions; using System.Xml.Linq; 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 { var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'"; var variableObix = backgroundServiceRepository.GetAllAsync(sqlObix).Result; string username = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault(); string password = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault(); 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", "ClearWeatherData")) { try { await task_Detail.InsertWorkTime("WeatherAPI", "ClearWeatherData", null, new DateTime(DateTime.Now.AddDays(1).Year, DateTime.Now.AddDays(1).Month, DateTime.Now.AddDays(1).Day, 0, 0, 0)); await ClearData("api_weateher", 1); await task_Detail.InsertWorkTime_End("WeatherAPI", "ClearWeatherData"); } catch (Exception ex) { await task_Detail.WorkFail("WeatherAPI", "ClearWeatherData", ex.Message.ToString()); logger.LogError($"ClearWeatherData error: {ex}, {ex.InnerException}, {ex.Message}"); } } 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.cwa.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); // Use Root3 here 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[1].WeatherElement; // Location[1]是信義區 foreach (var a in Type_ALL) { foreach (var b in a.Time) { Dictionary WeatherAPIdb = new Dictionary() { { "@weather_type", a.ElementName}, { "@data_no", DataNO}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} }; ProcessElementValue(a, b, WeatherAPIdb, WeatherAPIdbS); } } string sql = @" INSERT INTO api_weateher (weather_type, data_no, get_value, get_value2, created_by, created_at, start_time, end_time) VALUES (@weather_type, @data_no, @get_value, @get_value2, @created_by, @created_at, @start_time, @end_time) ON DUPLICATE KEY UPDATE get_value = VALUES(get_value), get_value2 = VALUES(get_value2);"; foreach (var item in WeatherAPIdbS) { await backendRepository.ExecuteSql(sql, item); } } 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", null, new DateTime(DateTime.Now.AddDays(1).Year, DateTime.Now.AddDays(1).Month, DateTime.Now.AddDays(1).Day, 0, 25, 0)); await task_Detail.InsertWorkTime("WeatherAPI", "api_rain"); await ClearData("api_rain", 3); WebClient mywebClient = new WebClient(); mywebClient.DownloadFile("https://opendata.cwa.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 observation = JsonConvert.DeserializeObject(json); var taipeiInfo = observation.Alert.Info .Where(info => info.Area .Any(area => area.AreaDesc == "臺北市" || area.AreaDesc == "臺北市信義區")) //.Any(area => area.Geocode.Value == "63" || area.Geocode.Value == "6300200")) .FirstOrDefault(); var result = ""; if (taipeiInfo != null) { var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{taipeiInfo.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'"; var NeedCallApi = await backendRepository.GetOneAsync(sql); if (NeedCallApi == 0) { var area = taipeiInfo.Area.Where(a => a.AreaDesc == "臺北市" || a.AreaDesc == "臺北市信義區").Select(x => x.AreaDesc).FirstOrDefault(); var severity_level = taipeiInfo.Parameter .Where(x => x.ValueName == "severity_level") .Select(x => x.Value) .FirstOrDefault(); Dictionary RainAPIdb = new Dictionary() { { "@msgType", observation.Alert.MsgType}, { "@headline", taipeiInfo.Headline}, { "@severity_level", severity_level }, { "@areaDesc", area}, { "@onset", taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")}, { "@expires", taipeiInfo.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"); var val = RainValue(severity_level, taipeiInfo.Headline); if (val < 5) { var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/ALMLEVL_RAIN/set", val.ToString()); UpdatedNiagara("api_rain", ReStr, id); result = ReStr.Contains("err") ? "fail" : "success"; logger.LogInformation($"set niagara rain value {result}"); } } } else { // 目前看起來只有全縣市都無警報才會有解除警報的資訊,故若警報中途更新後沒臺北了則應視為解除,table裡的紀錄只留發生跟解除的紀錄 var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/ALMLEVL_RAIN/set", "0"); result = ReStr.Contains("err") ? "fail" : "success"; logger.LogInformation($"set niagara rain value {result}"); } FolderFunction folderFunction = new FolderFunction(); folderFunction.DeleteFile(@"root/PowerfulRain.xml"); await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain"); //var haveinfo = json.Split("info"); //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")}'"; //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); // logger.LogInformation($"set niagara rain value success"); // } // } // 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); // logger.LogInformation($"set niagara rain value success"); // } // } // 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)); await task_Detail.InsertWorkTime("WeatherAPI", "api_typhoon"); await ClearData("api_typhoon", 3); WebClient mywebClient = new WebClient(); mywebClient.DownloadFile("https://opendata.cwa.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 observation = JsonConvert.DeserializeObject(json); var taipeiInfo = observation.Alert.Info .Where(info => info.Area .Any(area => area.AreaDesc == "臺北市")) .FirstOrDefault(); var result = ""; if (taipeiInfo != null) { var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{taipeiInfo.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'"; var NeedCallApi = await backendRepository.GetOneAsync(sql); if (NeedCallApi == 0) { var area = taipeiInfo.Area.Where(a => a.AreaDesc == "臺北市").Select(x => x.AreaDesc).FirstOrDefault(); Dictionary EarthquakeAPIdb = new Dictionary() { { "@msgType", observation.Alert.MsgType}, { "@headline", taipeiInfo.Headline}, { "@areaDesc", area}, { "@urgency",taipeiInfo.Urgency}, { "@severity",taipeiInfo.Severity}, { "@onset", taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")}, { "@expires", taipeiInfo.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 (taipeiInfo.Urgency != null && taipeiInfo.Urgency != "Expected") { var val = taipeiInfo.Urgency; var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/ALMLEVL_Typhoon/set", val); UpdatedNiagara("api_typhoon", ReStr, id); result = ReStr.Contains("err") ? "fail" : "success"; logger.LogInformation($"set niagara typhoon value {result}"); } } } else { // 目前看起來只有全縣市都無警報才會有解除警報的資訊,故若警報中途更新後沒臺北了則應視為解除,table裡的紀錄只留發生跟解除的紀錄 var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/ALMLEVL_Typhoon/set", "Past"); result = ReStr.Contains("err") ? "fail" : "success"; logger.LogInformation($"set niagara typhoon value {result}"); } FolderFunction folderFunction = new FolderFunction(); folderFunction.DeleteFile(@"root/Typhoon.xml"); await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon"); //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/ALMLEVL_Typhoon/set", observation.Alert.Info.Urgency); // UpdatedNiagara("api_typhoon", ReStr, id); // logger.LogInformation($"set niagara typhoon value success"); // } // } // 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/ALMLEVL_Typhoon/set", observation.Alert.Info.Urgency); // UpdatedNiagara("api_typhoon", ReStr, id); // logger.LogInformation($"set niagara typhoon value success"); // } // } // 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"); await ClearData("api_earthquake", 3); var client = new HttpClient(); var UVUri = "https://opendata.cwa.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 result = ""; var observation = JsonConvert.DeserializeObject(jsonUVs); if (!observation.Success) { logger.LogInformation("【WeatherAPIJob】【取得地震觀測資料不正確】"); } else { logger.LogInformation("【WeatherAPIJob】【開始存入地震觀測到資料庫】"); List> EarthquakeAPIdbS = new List>(); var maxEarthquakeNo = observation.Records.Earthquake.Max(eq => eq.EarthquakeNo); var eq = observation.Records.Earthquake.Where(eq => eq.EarthquakeNo == maxEarthquakeNo).FirstOrDefault(); var exist = eq.Intensity.ShakingArea.Where(area => area.CountyName == "臺北市").FirstOrDefault(); if (exist != null) { var sql = $"select id from api_earthquake where earthquakeNo = {eq.EarthquakeNo}"; var NeedCallApi = await backendRepository.GetOneAsync(sql); if (NeedCallApi == 0) { Dictionary EarthquakeAPIdb = new Dictionary() { { "@earthquakeNo", eq.EarthquakeNo}, { "@newEarthquake", 1}, { "@originTime", DateTime.Parse(eq.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)}, { "@magnitudeValue", eq.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue}, { "@areaName", exist.CountyName}, { "@areaIntensity", exist.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/ALMLEVL_LMI/set", Regex.Match(exist.AreaIntensity, @"\d+").ToString()); if (Nag.Contains("err")) { EarthquakeAPIdb.Add("@niagara", Nag); logger.LogInformation($"set niagara earthquake value fail: {Nag}"); } else { EarthquakeAPIdb.Add("@niagara", "success"); logger.LogInformation($"set niagara earthquake value success"); } EarthquakeAPIdbS.Add(EarthquakeAPIdb); } } else { var Nag = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/ALMLEVL_LMI/set", "0"); result = Nag.Contains("err") ? "fail" : "success"; logger.LogInformation($"set niagara earthquake value {result}"); } //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/ALMLEVL_LMI/set", a.Intensity.ShakingArea[0].AreaIntensity.ToString()); // if (Nag.Contains("err")) // { // EarthquakeAPIdb.Add("@niagara", Nag); // logger.LogInformation($"set niagara earthquake value fail: {Nag}"); // } // else // { // EarthquakeAPIdb.Add("@niagara", "success"); // logger.LogInformation($"set niagara earthquake value 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/ALMLEVL_LMI/set", "NULL"); // if (Nag.Contains("err")) // { // EarthquakeAPIdb.Add("@niagara", Nag); // logger.LogInformation($"set niagara earthquake value fail: {Nag}"); // } // else // { // EarthquakeAPIdb.Add("@niagara", "success"); // logger.LogInformation($"set niagara earthquake value success"); // } // EarthquakeAPIdbS.Add(EarthquakeAPIdb); // } // } //} EarthquakeAPIdbS.Reverse(); if (EarthquakeAPIdbS.Count != 0) { 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()); } } // Niagara批次寫法 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 urlMapping = new Dictionary { { "溫度", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set" }, { "相對濕度", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set" }, { "3小時降雨機率", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set" }, { "天氣現象", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set" } }; // 建立批次請求 var batchRequests = types .Where(t => urlMapping.ContainsKey(t.weather_type)) .Select(t => ( url: obixApiConfig.ApiBase + urlMapping[t.weather_type], value: t.get_value )) .ToList(); // 呼叫批次請求 var batchResponse = await ProcessBatchRequestAsync(obixApiConfig, batchRequests); // 解析回應 XML var batchResponseXml = XDocument.Parse(batchResponse); var listElement = batchResponseXml.Descendants().FirstOrDefault(e => e.Name.LocalName == "list"); if (listElement == null) { throw new Exception("Batch response XML does not contain a 'list' element."); } var childElements = listElement.Elements().ToList(); // 使用 urlMapping 的值反向找對應的 weather_type for (int i = 0; i < childElements.Count; i++) { var tag = childElements[i].Name.LocalName; var responseStr = childElements[i].ToString(); var currentRequest = batchRequests[i]; // 找到當前 URL 在 urlMapping 中的 key (weather_type) var weatherTypeKey = urlMapping.FirstOrDefault(x => currentRequest.url.Contains(x.Value)).Key; if (weatherTypeKey != null) { var weatherType = types.FirstOrDefault(t => t.weather_type == weatherTypeKey); if (weatherType != null) { if (tag == "err") { UpdatedNiagara("api_weateher", responseStr, weatherType.id); } else { UpdatedNiagara("api_weateher", "success", weatherType.id); } } else { logger.LogWarning($"No matching weather type found for key: {weatherTypeKey}"); } } else { logger.LogWarning($"No matching URL found for request: {currentRequest.url}"); } } await task_Detail.InsertWorkTime_End("WeatherAPI", "set_weather"); logger.LogInformation($"Set Niagara weather value success"); } catch (Exception ex) { logger.LogError($"Set Niagara weather value fail: {ex.Message}"); await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message); } } // Niagara單次寫法 //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"); // logger.LogInformation($"set niagara weather value success"); // } // catch (Exception ex) // { // logger.LogInformation($"set niagara weather value fail"); // 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 severity_level, string Headline) { var rint = 5; if (severity_level == null) { return 0; } else { if (Headline.Contains("解除")) rint = 0; else if (severity_level.Contains("大雨")) { rint = 1; } else if (severity_level.Contains("豪雨")) { rint = 2; } else if (severity_level.Contains("大豪雨")) { rint = 3; } else if (severity_level.Contains("超大豪雨")) { rint = 4; } } return rint; } public async Task ProcessBatchRequestAsync(ObixApiConfig obixApiConfig, List<(string url, string value)> batchRequests) { try { var batchRequestData = new StringBuilder(); string authInfo = Convert.ToBase64String(Encoding.Default.GetBytes($"{obixApiConfig.UserName}:{obixApiConfig.Password}")); // 組合批次請求的資料 foreach (var request in batchRequests) { var jsonData = $""; batchRequestData.AppendLine($"" + jsonData + ""); } // 最終的批次請求資料 var batchRequestXml = $@"{batchRequestData}"; // 建立 HTTP 請求 var requestBacth = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/batch"); requestBacth.Method = "POST"; requestBacth.Headers.Add("Authorization", "Basic " + authInfo); // 寫入請求資料 using (var streamWriter = new StreamWriter(requestBacth.GetRequestStream())) { streamWriter.Write(batchRequestXml); } // 獲取回應 using (var response = (HttpWebResponse)await requestBacth.GetResponseAsync()) using (var streamReader = new StreamReader(response.GetResponseStream())) { return await streamReader.ReadToEndAsync(); } } catch (Exception) { return "BatchRequestg失敗"; } } //Helper Method to process Element Values private void ProcessElementValue(WeatherElement3 a, Time b, Dictionary WeatherAPIdb, List> WeatherAPIdbS) { //Common parameters for element value if (a.ElementName.Contains(ElementName.小時降雨機率.ToString()) || a.ElementName.Contains(ElementName.天氣現象.ToString()) || a.ElementName.Contains(ElementName.天氣預報綜合描述.ToString())) { if (Convert.ToDateTime(b.StartTime) > DateTime.Now.AddDays(1)) { return; // Skip to next element } WeatherAPIdb.Add("@start_time", Convert.ToDateTime(b.StartTime).ToString("yyyy-MM-dd HH:mm:ss")); WeatherAPIdb.Add("@end_time", Convert.ToDateTime(b.EndTime).ToString("yyyy-MM-dd HH:mm:ss")); } else { if (Convert.ToDateTime(b.DataTime) > DateTime.Now.AddDays(1)) { return; // Skip to next element } WeatherAPIdb.Add("@start_time", Convert.ToDateTime(b.DataTime).ToString("yyyy-MM-dd HH:mm:ss")); WeatherAPIdb.Add("@end_time", null); } //Switch statement to handle different element names and their values switch (a.ElementName) { case "溫度": WeatherAPIdb.Add("@get_value", b.ElementValue[0].Temperature); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "露點溫度": WeatherAPIdb.Add("@get_value", b.ElementValue[0].DewPoint); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "相對濕度": WeatherAPIdb.Add("@get_value", b.ElementValue[0].RelativeHumidity); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "體感溫度": WeatherAPIdb.Add("@get_value", b.ElementValue[0].ApparentTemperature); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "舒適度指數": WeatherAPIdb.Add("@get_value", b.ElementValue[0].ComfortIndex); WeatherAPIdb.Add("@get_value2", b.ElementValue[0].ComfortIndexDescription); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "風速": WeatherAPIdb.Add("@get_value", b.ElementValue[0].WindSpeed); WeatherAPIdb.Add("@get_value2", b.ElementValue[0].BeaufortScale); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "風向": WeatherAPIdb.Add("@get_value", b.ElementValue[0].WindDirection); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "3小時降雨機率": WeatherAPIdb.Add("@get_value", b.ElementValue[0].ProbabilityOfPrecipitation); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "天氣現象": WeatherAPIdb.Add("@get_value", b.ElementValue[0].Weather); WeatherAPIdb.Add("@get_value2", b.ElementValue[0].WeatherCode); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; case "天氣預報綜合描述": WeatherAPIdb.Add("@get_value", b.ElementValue[0].WeatherDescription); WeatherAPIdbS.Add(new Dictionary(WeatherAPIdb)); break; } } 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; } } public async Task ClearData(string tableName, int monthNumber) { try { string sql = $@"delete from {tableName} WHERE created_at < DATE_SUB(NOW(), INTERVAL {monthNumber} MONTH)"; await backgroundServiceRepository.ExecuteSql(sql); } catch (Exception e) { logger.LogError($"[ClearData] clear {tableName} data error"); throw e; } } } }