824 lines
42 KiB
C#
824 lines
42 KiB
C#
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<bool> SyncDevice(ILogger logger, List<device> data, ObixApiConfig obixApiConfig, string bql, List<site> 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 = "<str val='" + bql + "'/>";
|
||
|
||
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<bool> ImportDevice(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, List<device> 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<bool> SyncData (ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, ObixApiConfig obixApiConfig,
|
||
List<device> deviceData, List<device_point> devicePointData, string startTimeStamp, string endTimeStamp, string intervalValue,
|
||
List<data_value> 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<string>(sql);
|
||
string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
|
||
var data = new List<data>();
|
||
|
||
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||
<abstime name='start' val='{startTimeStamp}' />
|
||
<abstime name='end' val='{endTimeStamp}' />
|
||
<reltime name='interval' val = '{intervalValue}' />
|
||
</obj>";
|
||
|
||
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<string, decimal>();
|
||
var realValue = new Dictionary<string, decimal>();
|
||
|
||
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<string, decimal>() { { 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<string, decimal>();
|
||
var realValue = new Dictionary<string, decimal>();
|
||
|
||
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<string, decimal>() { { 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<string>(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<device>() { 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<bool> SyncDevicePoint(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, List<device_point> 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 = "<str val='" + bql + "'/>";
|
||
|
||
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<bool> ImportDevicePoint(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, List<device_point> 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<bool> SyncDataValue(ILogger logger, List<data_value> 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 = "<str val='" + b + "'/>";
|
||
|
||
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<bool> SyncSiteInfo(ILogger logger, List<site> 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 = "<str val='neql:solar:id and n:type=\"baja:Folder\"'/>";
|
||
|
||
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<bool> CheckLastData(ILogger logger, IBackgroundServicePostgresqlRepository backgroundServiceRepository, ObixApiConfig obixApiConfig,
|
||
List<device> deviceData, List<device_point> devicePointData, string startTimeStamp, string endTimeStamp, string intervalValue,
|
||
List<data_value> 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<string>(sql);
|
||
string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
|
||
var data = new List<data>();
|
||
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||
<abstime name='start' val='{startTimeStamp}' />
|
||
<abstime name='end' val='{endTimeStamp}' />
|
||
<reltime name='interval' val = '{intervalValue}' />
|
||
</obj>";
|
||
|
||
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<string, decimal>();
|
||
var realValue = new Dictionary<string, decimal>();
|
||
|
||
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<string, decimal>();
|
||
var realValue = new Dictionary<string, decimal>();
|
||
|
||
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;
|
||
}
|
||
}
|
||
} |