using Backend.Models; using BackendWorkerService.Models; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Threading.Tasks; using System.Xml; using Repository.Models; using System.Linq; using System.Web; using Repository.BackendRepository.Interface; using System.Text; using Newtonsoft.Json.Linq; namespace BackendWorkerService.Services.Implement { public class SolarService { public async Task SyncDevice(ILogger logger, List data, ObixApiConfig obixApiConfig, string bql, List sites) { bool result = false; try { string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/config/Program/ObixQuery/query/"); Postrequest.Method = "POST"; Postrequest.Headers.Add("Authorization", "Basic " + encoded); Postrequest.PreAuthenticate = true; using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream())) { 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); var jsonData = Welcome.FromJson(jsonText); if (jsonData.Obj != null && jsonData.Obj.Str != null) { foreach (var jd in jsonData.Obj.Str) { var value = jd.Val.Split(","); if (value.Length > 0) { var device = new device(); string tmpPath = value[0].Substring(0, value[0].Length - 1); int lastIndex = tmpPath.LastIndexOf('/'); device.path_n4 = tmpPath.Substring(0, lastIndex + 1); device.site_id = value[0].Split("/")[2].Trim(); device.device_sys_tag = value[0].Split("/")[3].Trim(); device.device_id = value[0].Split("/")[value[0].Split("/").Length - 3].Trim(); device.site_name = sites.Where(x => x.site_id == device.site_id).FirstOrDefault()?.site_name ?? ""; if (!data.Any(x => x.site_id == device.site_id && x.device_sys_tag == device.device_sys_tag && x.device_id == device.device_id)) data.Add(device); } } } result = true; } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【SyncDevice】[Exception]:{ex.ToString()}"); } return result; } public async Task ImportDevice(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, List data) { bool result = false; try { string sql = string.Empty; #region clear data sql = "delete from import_device"; await backgroundServiceRepository.ExecuteSql(sql); #endregion #region insert data if (data.Any()) { sql = @$"insert into import_device (site_id, site_name, device_sys_tag, path_n4, device_id, created_at) values "; int index = 1; foreach (var d in data) { sql += $"('{d.site_id}', '{d.site_name}', '{d.device_sys_tag}', '{d.path_n4}', '{d.device_id}', now()){(index == data.Count ? ";" : ", ")}"; index++; } await backgroundServiceRepository.ExecuteSql(sql); } #endregion #region compare device data with import_device //update sql = @"UPDATE device SET is_link = idev.is_link, site_name = idev.site_name FROM ( select d.site_id, d.device_sys_tag, d.device_id, CASE WHEN idev.site_id IS NULL THEN b'0' ELSE b'1' END is_link, idev.site_name from device d left join import_device idev on d.site_id = idev.site_id and d.device_sys_tag = idev.device_sys_tag and d.device_id = idev.device_id ) idev WHERE device.site_id = idev.site_id AND device.device_sys_tag = idev.device_sys_tag AND device.device_id = idev.device_id;"; await backgroundServiceRepository.ExecuteSql(sql); //insert sql = @"insert into device (site_id, site_name, device_sys_tag, archive_lastdate, path_n4, device_Id, is_link, created_at) select idev.site_id, idev.site_name, idev.device_sys_tag, now(), idev.path_n4, idev.device_Id, b'1', now() from import_device idev left join device d on d.site_id = idev.site_id and d.device_sys_tag = idev.device_sys_tag and d.device_id = idev.device_id where d.site_id is null; update device set is_link = b'0' where is_link is null or is_link = '';"; await backgroundServiceRepository.ExecuteSql(sql); #endregion result = true; } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【ImportDevice】[Exception]:{ex.ToString()}"); } return result; } public async Task SyncData (ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, ObixApiConfig obixApiConfig, List deviceData, List devicePointData, string startTimeStamp, string endTimeStamp, string intervalValue, List dataValue, bool isRecord) { bool result = true; string sql = string.Empty; string path = string.Empty; try { XmlDocument xmlDocument = new XmlDocument(); sql = "select system_value from variable where deleted = 0 and system_type = 'obixConfig' and system_key = 'niagara status'"; string station = await backgroundServiceRepository.GetOneAsync(sql); string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); var data = new List(); var historyQueryFilter = $@" "; foreach (var dd in deviceData) { #region update device archive_lastActionDate sql = @$"update device set archive_lastactiondate = now() where site_id = '{dd.site_id}' and device_sys_tag = '{dd.device_sys_tag}' and device_id = '{dd.device_id}'"; await backgroundServiceRepository.ExecuteSql(sql); #endregion #region main process foreach (var dpd in devicePointData.Where(x => x.site_id == dd.site_id && x.device_sys_tag == dd.device_sys_tag && x.device_id == dd.device_id)) { path = dd.site_id + "_" + dd.device_sys_tag + (dd.device_id == dd.device_sys_tag ? "" : "_" + dd.device_id) + "_" + dpd.point; HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{path}/~historyRollup/"); archiveHourRequest.Method = "POST"; archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded); archiveHourRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveHourRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveHourResponse = (HttpWebResponse)archiveHourRequest.GetResponse(); var archiveHourResponseContent = new StreamReader(archiveHourResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveHourResponseContent); string archiveHourJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject jsonResult = (JObject)JsonConvert.DeserializeObject(archiveHourJson); if (jsonResult.ContainsKey("err")) //抓取錯誤 { result = false; } else { var rawdateCount = Convert.ToInt32(jsonResult["obj"]["int"]["@val"].ToString()); var histories = jsonResult["obj"]["list"]["obj"]; if (rawdateCount > 1) { foreach (var history in histories) { var d = new data(); d.site_id = dd.site_id; d.device_id = dd.device_id; d.device_sys_tag = dd.device_sys_tag; d.value = new Dictionary(); var realValue = new Dictionary(); if (history["abstime"] != null && history["abstime"].HasValues) { foreach (var abstime in history["abstime"]) { var name = abstime["@name"].ToString(); switch (name) { case "start": d.timestamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss"); break; } } } if (history["real"] != null && history["real"].HasValues) { foreach (var real in history["real"]) { var name = real["@name"].ToString(); if (name == (dataValue.Where(x => x.site_id == dd.site_id && x.device_id == dd.device_id && x.device_sys_tag == dd.device_sys_tag && x.point == dpd.point).FirstOrDefault()?.value_unit ?? "")) { var value = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float); realValue = new Dictionary() { { dpd.point.ToUpper(), value } }; } } } if (realValue.Count > 0) { if (data.Any(x => x.site_id == d.site_id && x.device_id == d.device_id && x.device_sys_tag == dd.device_sys_tag && x.timestamp == d.timestamp)) data.Where(x => x.site_id == d.site_id && x.device_id == d.device_id && x.device_sys_tag == dd.device_sys_tag && x.timestamp == d.timestamp).FirstOrDefault().value.Add(realValue.First().Key, realValue.First().Value); else { d.value.Add(realValue.First().Key, realValue.First().Value); data.Add(d); } } } } else { var d = new data(); d.site_id = dd.site_id; d.device_id = dd.device_id; d.device_sys_tag = dd.device_sys_tag; d.value = new Dictionary(); var realValue = new Dictionary(); if (histories["abstime"] != null && histories["abstime"].HasValues) { foreach (var abstime in histories["abstime"]) { var name = abstime["@name"].ToString(); switch (name) { case "start": d.timestamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss"); break; } } } if (histories["real"] != null && histories["real"].HasValues) { foreach (var real in histories["real"]) { var name = real["@name"].ToString(); if (name == (dataValue.Where(x => x.site_id == dd.site_id && x.device_id == dd.device_id && x.device_sys_tag == dd.device_sys_tag && x.point == dpd.point).FirstOrDefault()?.value_unit ?? "")) { var value = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float); realValue = new Dictionary() { { dpd.point.ToUpper(), value } }; } } } if (realValue.Count > 0) { if (data.Any(x => x.site_id == d.site_id && x.device_id == d.device_id && x.device_sys_tag == dd.device_sys_tag && x.timestamp == d.timestamp)) data.Where(x => x.site_id == d.site_id && x.device_id == d.device_id && x.device_sys_tag == dd.device_sys_tag && x.timestamp == d.timestamp).FirstOrDefault().value.Add(realValue.First().Key, realValue.First().Value); else { d.value.Add(realValue.First().Key, realValue.First().Value); data.Add(d); } } } } } #endregion #region update device archive_lastDate if (isRecord && (DateTime.Parse(endTimeStamp) - DateTime.Parse(startTimeStamp)).Days == 1) { #region check range of archive_lastdate sql = $@"select archive_lastdate from device where site_id = '{dd.site_id}' and device_sys_tag = '{dd.device_sys_tag}' and device_id = '{dd.device_id}'"; var archive_lastdate = await backgroundServiceRepository.GetOneAsync(sql); if (!string.IsNullOrEmpty(archive_lastdate)) { int index = (DateTime.Parse(startTimeStamp) - DateTime.Parse(archive_lastdate)).Days; var now = DateTime.Parse(archive_lastdate); while (index > 0) { var preHour = now.AddDays(-1); //取得前一天 var chkStartTimestamp = $"{preHour.ToString("yyyy-MM-dd")}T00:00:00.000+08:00"; var chkEndTimestamp = $"{now.ToString("yyyy-MM-dd")}T00:00:00.000+08:00"; var chkIntervalValue = "PT1H"; await SyncData(logger, backgroundServiceRepository, obixApiConfig, new List() { dd }, devicePointData, chkStartTimestamp, chkEndTimestamp, chkIntervalValue, dataValue, false); index--; now = now.AddDays(1); } } #endregion sql = @$"update device set archive_lastDate = now() where site_id = '{dd.site_id}' and device_sys_tag = '{dd.device_sys_tag}' and device_id = '{dd.device_id}'"; await backgroundServiceRepository.ExecuteSql(sql); } #endregion } if (data.Any()) { var types = data.GroupBy(x => x.device_sys_tag).Select(x => x.Key.ToLower()); sql = ""; string table_name = string.Empty; string[] cusTypes = { "inverter", "sensor", "meter", "site" }; foreach (var t in types) { var currData = data.Where(x => x.device_sys_tag.ToLower() == t).ToList(); if (currData.Any(x => x.value.Count > 0)) { #region check column if (cusTypes.Contains(t)) { table_name = t == "inverter" ? "inverter_history_hour" : t == "sensor" ? "sensoravg_history_hour" : t == "meter" ? "meter_history_hour" : t == "site" ? "station_history_hour" : ""; sql += @$" DO $$ DECLARE columns_to_add TEXT[] := ARRAY['{string.Join("','", currData.SelectMany(x => x.value.Keys).Distinct())}']; col TEXT; BEGIN FOREACH col IN ARRAY columns_to_add LOOP IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_name = '{table_name}' AND column_name = col ) THEN EXECUTE format('ALTER TABLE {table_name} ADD COLUMN %I FLOAT(53)', col); ELSE END IF; END LOOP; END $$; "; } #endregion foreach (var d in currData) { int i = 1; var orderDic = d.value.OrderBy(x => x.Key).ToList(); if (cusTypes.Contains(t)) { sql += @$" WITH updated_rows AS ( UPDATE {table_name} SET "; foreach (var v in orderDic) { sql += $@" ""{v.Key}"" = {v.Value} "; if (i++ != orderDic.Count) sql += ", "; } #region different type insert sql += $@" WHERE site_id = '{d.site_id}' and ""device_Id"" = '{d.device_id}' and ""TIMESTAMP"" = '{d.timestamp}' RETURNING * ) insert into {table_name} (site_id, ""device_Id"", ""TIMESTAMP"", ""{string.Join(@""",""", orderDic.Select(x => x.Key))}"") select '{d.site_id}', '{d.device_id}', '{d.timestamp}', "; #endregion i = 1; foreach (var v in orderDic) { sql += $@"{v.Value}"; if (i++ != orderDic.Count) sql += ", "; } sql += " WHERE NOT EXISTS (SELECT 1 FROM updated_rows); "; } } } } if (!string.IsNullOrWhiteSpace(sql)) { await backgroundServiceRepository.ExecuteSql(sql, null); } } } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【SyncData】[Exception]:{ex.ToString()}"); } return result; } public async Task SyncDevicePoint(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, List data, ObixApiConfig obixApiConfig, string bql) { bool result = false; string sql = string.Empty; try { string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/config/Program/ObixQuery/query/"); Postrequest.Method = "POST"; Postrequest.Headers.Add("Authorization", "Basic " + encoded); Postrequest.PreAuthenticate = true; using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream())) { 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); var jsonData = Welcome.FromJson(jsonText); if (jsonData.Obj != null && jsonData.Obj.Str != null) { foreach (var jd in jsonData.Obj.Str) { var value = jd.Val.Split(","); if (value.Length > 0) { var devicePoint = new device_point(); devicePoint.site_id = value[0].Split("/")[2].Trim(); devicePoint.device_sys_tag = value[0].Split("/")[3].Trim(); devicePoint.point = value[0].Split("/")[value[0].Split("/").Length - 2].Trim(); devicePoint.device_id = value[0].Split("/")[value[0].Split("/").Length - 3].Trim(); devicePoint.history_path = value[0].Trim(); devicePoint.is_link = 1; data.Add(devicePoint); } } } result = true; } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【SyncDevicePoint】[Exception]:{ex.ToString()}"); } return result; } public async Task ImportDevicePoint(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, List data) { bool result = false; try { string sql = string.Empty; #region clear data sql = "delete from import_device_point"; await backgroundServiceRepository.ExecuteSql(sql); #endregion #region insert data if (data.Any()) { sql = @$"insert into import_device_point (device_sys_tag, point, site_id, device_id, history_path, created_at) values "; int index = 1; foreach (var d in data) { sql += $"('{d.device_sys_tag}', '{d.point}', '{d.site_id}', '{d.device_id}', '{d.history_path}', now()){(index == data.Count ? ";" : ", ")}"; index++; } await backgroundServiceRepository.ExecuteSql(sql); } #endregion #region compare device data with import_device //update sql = @"UPDATE device_point SET is_link = idev.is_link FROM ( select d.site_id, d.device_sys_tag, d.device_id, CASE WHEN idev.site_id IS NULL THEN b'0' ELSE b'1' END is_link from device_point d left join import_device_point idev on d.site_id = idev.site_id and d.device_sys_tag = idev.device_sys_tag and d.device_id = idev.device_id ) idev WHERE device_point.site_id = idev.site_id AND device_point.device_sys_tag = idev.device_sys_tag AND device_point.device_id = idev.device_id;"; await backgroundServiceRepository.ExecuteSql(sql); //insert sql = @"insert into device_point (device_sys_tag, point, site_id, device_id, history_path, is_link) select idev.device_sys_tag, idev.point, idev.site_id, idev.device_id, idev.history_path, b'1' from import_device_point idev left join device_point d on d.site_id = idev.site_id and d.device_sys_tag = idev.device_sys_tag and d.device_id = idev.device_id where d.site_id is null; update device_point set is_link = b'0' where is_link is null or is_link = '';"; await backgroundServiceRepository.ExecuteSql(sql); #endregion result = true; } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【ImportDevicePoint】[Exception]:{ex.ToString()}"); } return result; } public async Task SyncDataValue(ILogger logger, List data, ObixApiConfig obixApiConfig) { bool result = false; string[] bql = new string[] { "neql:solar:archive=\"max\" and solar:archivetime=\"minute\"", "neql:solar:archive=\"avg\" and solar:archivetime=\"minute\"", "neql:solar:archive=\"sum\" and solar:archivetime=\"minute\"", "neql:solar:archive=\"max\" and solar:archivetime=\"hour\"", "neql:solar:archive=\"avg\" and solar:archivetime=\"hour\"", "neql:solar:archive=\"sum\" and solar:archivetime=\"hour\"" }; try { string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); foreach (var b in bql) { HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/config/Program/ObixQuery/query/"); Postrequest.Method = "POST"; Postrequest.Headers.Add("Authorization", "Basic " + encoded); Postrequest.PreAuthenticate = true; using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream())) { 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); var jsonData = Welcome.FromJson(jsonText); if (jsonData.Obj != null && jsonData.Obj.Str != null) { foreach (var jd in jsonData.Obj.Str) { var value = jd.Val.Split(","); if (value.Length > 0) { var devicePoint = new data_value(); devicePoint.site_id = value[0].Split("/")[2].Trim(); devicePoint.device_sys_tag = value[0].Split("/")[3].Trim(); devicePoint.point = value[0].Split("/")[value[0].Split("/").Length - 2].Trim(); devicePoint.device_id = value[0].Split("/")[value[0].Split("/").Length - 3].Trim(); devicePoint.value_unit = b.Contains("\"max\"") ? "max" : b.Contains("\"avg\"") ? "avg" : b.Contains("\"sum\"") ? "sum" : ""; data.Add(devicePoint); } } } } result = true; } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【SyncDataValue】[Exception]:{ex.ToString()}"); } return result; } public async Task SyncSiteInfo(ILogger logger, List data, ObixApiConfig obixApiConfig) { bool result = false; try { string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/config/Program/ObixQuery/query/"); Postrequest.Method = "POST"; Postrequest.Headers.Add("Authorization", "Basic " + encoded); Postrequest.PreAuthenticate = true; using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream())) { 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); var jsonData = Welcome.FromJson(jsonText); if (jsonData.Obj != null && jsonData.Obj.Str != null) { foreach (var jd in jsonData.Obj.Str) { var value = jd.Val.Split(","); if (value.Length > 0) { var device = new site(); device.site_id = value[0].Split("/")[2].Trim(); device.site_name = HttpUtility.HtmlDecode(value[1].Split("=")[1]?.Trim() ?? ""); data.Add(device); } } } result = true; } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【SyncSiteInfo】[Exception]:{ex.ToString()}"); } return result; } public async Task CheckLastData(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, ObixApiConfig obixApiConfig, List deviceData, List devicePointData, string startTimeStamp, string endTimeStamp, string intervalValue, List dataValue) { bool result = true; string sql = string.Empty; string path = string.Empty; try { XmlDocument xmlDocument = new XmlDocument(); sql = "select system_value from variable where deleted = 0 and system_type = 'obixConfig' and system_key = 'niagara status'"; string station = await backgroundServiceRepository.GetOneAsync(sql); string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); var data = new List(); var historyQueryFilter = $@" "; foreach (var dd in deviceData) { result = true; #region main process foreach (var dpd in devicePointData.Where(x => x.site_id == dd.site_id && x.device_sys_tag == dd.device_sys_tag && x.device_id == dd.device_id)) { path = dd.site_id + "_" + dd.device_sys_tag + (dd.device_id == dd.device_sys_tag ? "" : "_" + dd.device_id) + "_" + dpd.point; HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{path}/~historyRollup/"); archiveHourRequest.Method = "POST"; archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded); archiveHourRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveHourRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveHourResponse = (HttpWebResponse)archiveHourRequest.GetResponse(); var archiveHourResponseContent = new StreamReader(archiveHourResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveHourResponseContent); string archiveHourJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject jsonResult = (JObject)JsonConvert.DeserializeObject(archiveHourJson); if (jsonResult.ContainsKey("err")) //抓取錯誤 { result = false; } else { var rawdateCount = Convert.ToInt32(jsonResult["obj"]["int"]["@val"].ToString()); var histories = jsonResult["obj"]["list"]["obj"]; if (rawdateCount > 1) { foreach (var history in histories) { var d = new data(); d.site_id = dd.site_id; d.device_id = dd.device_id; d.device_sys_tag = dd.device_sys_tag; d.value = new Dictionary(); var realValue = new Dictionary(); if (history["real"] != null && history["real"].HasValues) { foreach (var real in history["real"]) { var name = real["@name"].ToString(); if (name == (dataValue.Where(x => x.site_id == dd.site_id && x.device_id == dd.device_id && x.device_sys_tag == dd.device_sys_tag && x.point == dpd.point).FirstOrDefault()?.value_unit ?? "")) { if (result) result = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float) > 0; } } } } } else { var d = new data(); d.site_id = dd.site_id; d.device_id = dd.device_id; d.device_sys_tag = dd.device_sys_tag; d.value = new Dictionary(); var realValue = new Dictionary(); if (histories["real"] != null && histories["real"].HasValues) { foreach (var real in histories["real"]) { var name = real["@name"].ToString(); if (name == (dataValue.Where(x => x.site_id == dd.site_id && x.device_id == dd.device_id && x.device_sys_tag == dd.device_sys_tag && x.point == dpd.point).FirstOrDefault()?.value_unit ?? "")) { if (result) result = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float) > 0; } } } } } } #endregion if (!result) { deviceData.FirstOrDefault(x => x == dd).isSuccess = result; } } deviceData.RemoveAll(x => !x.isSuccess); } catch (Exception ex) { result = false; logger.LogError($"【ArchiveSolarHourJob】【SolarService】【CheckLastData】[Exception]:{ex.ToString()}"); } return result; } } }