ibms-MCUT/FrontendWebApi/ApiControllers/HistoryController.cs
jay.chang b86a6ff42f [WebApi]歷史資料2調整成隨棟別變動
[Backend]同步邏輯調整
[BGService]歸檔調整過濾項及新設備預設最後歸檔日
2024-12-25 16:26:44 +08:00

2777 lines
156 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using FrontendWebApi.Models;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Repository.BackendRepository.Interface;
using Repository.FrontendRepository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Diagnostics;
using Microsoft.CodeAnalysis;
namespace FrontendWebApi.ApiControllers
{
public class HistoryController : MyBaseApiController<EmergencyRecordController>
{
private readonly IBackendRepository backendRepository;
private readonly IFrontendRepository frontendRepository;
private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository;
public HistoryController
(
IBackendRepository backendRepository,
IFrontendRepository frontendRepository,
IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository
)
{
this.backendRepository = backendRepository;
this.frontendRepository = frontendRepository;
this.backgroundServiceMsSqlRepository = backgroundServiceMsSqlRepository;
}
/// <summary>
/// 匯出excel
/// </summary>
/// <param name="lhe"></param>
/// <returns></returns>
[HttpPost]
[Route("api/ExportHistory")]
public FileResult OpeExportExcel([FromBody] HistoryExport lhe)
{
ApiResult<string> apiResult = new ApiResult<string>();
//if (lhe == null)
//{
// apiResult.Code = "0001";
// apiResult.Msg = "沒有資料匯入";
// return apiResult;
//}
string fileDateName = lhe.dateType == "today" ? lhe.starttime.ToString("yyyy-MM-dd")
: lhe.dateType == "month" ? lhe.starttime.ToString("yyyy-MM")
: lhe.starttime.ToString("yyyy-MM-dd") + "_" + ((DateTime)lhe.endtime).ToString("yyyy-MM-dd");
string fileName = "歷史資料_" + fileDateName + ".xlsx";
lhe.device_number = char.IsDigit(lhe.device_number.Split("_")[1][0])
? lhe.device_number.Replace(lhe.device_number.Split("_")[1], "$3" + lhe.device_number.Split("_")[1])
: lhe.device_number;
XSSFWorkbook workbook = new XSSFWorkbook();
try
{
#region obix
EDFunction ed = new EDFunction();
var obixApiConfig = new ObixApiConfig();
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
var variableObix = backendRepository.GetAllAsync<KeyValue>(sqlObix).Result;
obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
obixApiConfig.UserName = ed.AESDecrypt(variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
obixApiConfig.Password = ed.AESDecrypt(variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
#endregion obix
var building = backendRepository.GetAllAsync<BuildList>("select * from building where deleted = 0").Result;
var buildStation = backendRepository.GetAllAsync<BuildStation>("select SUBSTRING_INDEX(system_value, '/', 1) system_value, system_key from variable where system_type = 'dashboard_total_elec' and deleted = 0 and (SUBSTRING_INDEX(system_value, '/', 1) != '' and SUBSTRING_INDEX(system_value, '/', 1) is not null)").Result;
#region get device and device_item(point)
var device = backendRepository.GetAllAsync<Device>($"select * from device where deleted = 0 and is_link = 1 and device_number = '{lhe.device_number}'").Result;
var devicePoint = backendRepository.GetAllAsync<Device_item>($"select * from device_item where deleted = 0 and is_link = 1 and is_show_history = 1 and device_building_tag = '{lhe.device_number.Split("_")[1]}' and device_system_tag = '{lhe.device_number.Split("_")[2]}' and device_name_tag = '{lhe.device_number.Split("_")[3]}'").Result;
#endregion
List<DeviceNumberPoint> listDevicePoint = new List<DeviceNumberPoint>();
#region combine device and point
var dp = devicePoint.Where(x => x.device_building_tag == lhe.device_number.Split("_")[1]).ToList();
foreach (var point in dp)
{
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
deviceNumberPoint.DeviceNumber = lhe.device_number;
deviceNumberPoint.Point = point.points;
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", lhe.device_number, point.points);
listDevicePoint.Add(deviceNumberPoint);
}
#endregion
#region get data from niagara
lhe.endtime = lhe.dateType == "today" ? lhe.starttime : lhe.dateType == "month" ? lhe.starttime.AddMonths(1).AddDays(-1) : lhe.endtime;
var startTimestamp = string.Format("{0}T00:00:00.000+08:00", lhe.starttime.ToString("yyyy-MM-dd"));
var endTimestamp = string.Format("{0}T23:59:59.000+08:00", lhe.endtime?.ToString("yyyy-MM-dd"));
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{startTimestamp}' />
<abstime name='end' val='{endTimestamp}' />
<reltime name='interval' val='PT1M' />
</obj>";
List<HistoryExport> he = new List<HistoryExport>();
List<JsonDevice> jd = new List<JsonDevice>();
if (listDevicePoint.Count > 0)
{
foreach (var d in listDevicePoint)
{
string buildingTag = d.DeviceNumber.Split("_")[1];
var station = backendRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history where device_building_tag = '{d.FullDeviceNumberPoint.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{d.FullDeviceNumberPoint.Split("_")[2]}' and device_name_tag = '{d.FullDeviceNumberPoint.Split("_")[3]}'
and device_floor_tag = '{d.FullDeviceNumberPoint.Split("_")[4]}' and device_master_tag = '{d.FullDeviceNumberPoint.Split("_")[5]}'
and device_last_name_tag = '{d.FullDeviceNumberPoint.Split("_")[6]}' and device_serial_tag = '{d.FullDeviceNumberPoint.Split("_")[7]}'
and device_point_name = '{d.FullDeviceNumberPoint.Split("_")[8]}'").Result;
if (!string.IsNullOrEmpty(station))
{
var archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{d.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/");
archiveRequest.Method = "POST";
archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
archiveRequest.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = archiveRequest.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
var archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
var archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
archiveResponse.Dispose();
archiveResponse.Close();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(archiveResponseContent);
var archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
var archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
if (!archiveJsonResult.ContainsKey("err"))
{
var jsonDevice = new JsonDevice();
jsonDevice.deviceNumberPoint = d;
jsonDevice.json = archiveJsonResult;
jsonDevice.building_tag = buildingTag;
jd.Add(jsonDevice);
}
}
else
{
Logger.LogError("【Device GetWay Error】, device_number: " + d.FullDeviceNumberPoint);
}
}
}
if (jd != null && jd.Count > 0)
{
foreach (var d in jd)
{
var ArrangeRawDatas = ArrangeRawData(d.deviceNumberPoint, d.json);
if (ArrangeRawDatas != null && ArrangeRawDatas.Count > 0)
{
foreach (var ard in ArrangeRawDatas)
{
HistoryExport hed = new HistoryExport();
hed.type = devicePoint.Where(x => x.device_building_tag == d.building_tag && x.points == ard["@point"].ToString()).Select(x => x.full_name).FirstOrDefault();
hed.deviceName = device.Where(x => x.device_number == ard["@device_number"].ToString()).Select(x => x.full_name).FirstOrDefault();
// 四捨六入
//hed.value = ard["@avg_rawdata"].ToString() == "-1" ? "NaN" : Math.Round((decimal.Parse(ard["@avg_rawdata"].ToString(), System.Globalization.NumberStyles.Float)), 2).ToString();
// 四捨五入
//ref: Math.Round(Convert.ToDecimal(45.365), 2, MidpointRounding.AwayFromZero)
hed.value = ard["@avg_rawdata"].ToString() == "-1" ? "NaN" : Math.Round(Convert.ToDecimal(ard["@avg_rawdata"].ToString()), 2, MidpointRounding.AwayFromZero).ToString();
hed.timestamp = Convert.ToDateTime(ard["@start_timestamp"].ToString());
hed.building_tag = d.building_tag;
he.Add(hed);
}
}
}
}
#endregion
#region export file progress
#region excel設定
IFont font12 = workbook.CreateFont();
font12.FontName = "新細明體";
font12.FontHeightInPoints = 12;
ICellStyle style12 = workbook.CreateCellStyle();
style12.SetFont(font12);
style12.Alignment = HorizontalAlignment.Center;
style12.VerticalAlignment = VerticalAlignment.Center;
IFont font12Times = workbook.CreateFont();
font12Times.FontName = "Times New Roman";
font12Times.FontHeightInPoints = 12;
IFont font18 = workbook.CreateFont();
font18.FontName = "新細明體";
font18.FontHeightInPoints = 18;
font18.IsBold = true;
ICellStyle styleTitle18 = workbook.CreateCellStyle();
styleTitle18.SetFont(font18);
styleTitle18.Alignment = HorizontalAlignment.Center;
styleTitle18.VerticalAlignment = VerticalAlignment.Center;
ICellStyle styleLeft12 = workbook.CreateCellStyle();
styleLeft12.SetFont(font12);
styleLeft12.Alignment = HorizontalAlignment.Left;
styleLeft12.VerticalAlignment = VerticalAlignment.Center;
ICellStyle styleLine12 = workbook.CreateCellStyle();
styleLine12.SetFont(font12);
styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
styleLine12.VerticalAlignment = VerticalAlignment.Center;
styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
ICellStyle stylein12 = workbook.CreateCellStyle();
stylein12.SetFont(font12Times);
stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;
stylein12.VerticalAlignment = VerticalAlignment.Center;
stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.WrapText = true;
#endregion
var data = he.ToList();
if (data.Count > 0)
{
string lastDeviceItem = string.Empty;
int RowPosition = 0;
IRow row;
ISheet sheet;
#region set cell
sheet = workbook.CreateSheet($"{building.Where(x => x.building_tag == lhe.device_number.Split("_")[1]).Select(x => x.full_name).FirstOrDefault()}{"_" + data[0].type}");
row = sheet.CreateRow(RowPosition);
sheet.SetColumnWidth(0, 4 * 160 * 12);
sheet.SetColumnWidth(1, 4 * 160 * 12);
sheet.SetColumnWidth(2, 4 * 160 * 12);
sheet.SetColumnWidth(3, 4 * 160 * 12);
ICell cell = row.CreateCell(0);
cell.SetCellValue("類型");
cell.CellStyle = styleLine12;
cell = row.CreateCell(1);
cell.SetCellValue("設備名稱");
cell.CellStyle = styleLine12;
cell = row.CreateCell(2);
cell.SetCellValue("數值");
cell = row.CreateCell(3);
cell.SetCellValue("記錄時間");
cell.CellStyle = styleLine12;
#endregion
foreach (var d in data)
{
if (RowPosition == 0 && lastDeviceItem == "")
{
lastDeviceItem = d.type; //第一次不用建立 sheet;
}
if (d.type != lastDeviceItem)
{
RowPosition = 0;
lastDeviceItem = d.type;
sheet = workbook.CreateSheet($"{building.Where(x => x.building_tag == lhe.device_number.Split("_")[1]).Select(x => x.full_name).FirstOrDefault()}{"_" + d.type}");
//sheet = workbook.CreateSheet($"{d.deviceName}{"_" + d.type}");
#region set cell
row = sheet.CreateRow(RowPosition);
sheet.SetColumnWidth(0, 4 * 160 * 12);
sheet.SetColumnWidth(1, 4 * 160 * 12);
sheet.SetColumnWidth(2, 4 * 160 * 12);
sheet.SetColumnWidth(3, 4 * 160 * 12);
cell = row.CreateCell(0);
cell.SetCellValue("類型");
cell.CellStyle = styleLine12;
cell = row.CreateCell(1);
cell.SetCellValue("設備名稱");
cell.CellStyle = styleLine12;
cell = row.CreateCell(2);
cell.SetCellValue("數值");
cell = row.CreateCell(3);
cell.SetCellValue("記錄時間");
cell.CellStyle = styleLine12;
#endregion
RowPosition = 1;
}
else
{
RowPosition += 1;
}
row = sheet.CreateRow(RowPosition);
for (var i = 0; i < 4; i++)
{
cell = row.CreateCell(i);
if (i == 0)
{
cell.SetCellValue(d.type);
}
if (i == 1)
{
cell.SetCellValue(d.deviceName);
}
if (i == 2)
{
cell.SetCellValue(d.value);
}
if (i == 3)
{
cell.SetCellValue(d.timestamp.ToString("yyyy-MM-dd HH:mm") + ":00");//
}
cell.CellStyle = style12;
}
}
}
#endregion
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message;
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
throw exception;
}
var ms = new NpoiMemoryStream
{
AllowClose = false
};
workbook.Write(ms);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
return File(ms, "application/vnd.ms-excel", fileName);
}
/// <summary>
/// 匯出excel
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/ExportHistoryExcel")]
public IActionResult ExportHistoryExcel([FromBody] PostHistoryDataFilter post)
{
ApiResult<string> apiResult = new ApiResult<string>();
var fileDateName = post.Type == 1 ? $@"{post.Start_date}T{post.Start_time}~{post.End_date}T{post.End_time}" : $@"{post.Start_date}~{post.End_date}&T{post.Start_time}~T{post.End_time}";
var fileName = "歷史資料_" + fileDateName + ".xlsx";
XSSFWorkbook workbook = new XSSFWorkbook();
try
{
#region obix
EDFunction ed = new EDFunction();
var obixApiConfig = new ObixApiConfig();
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
var variableObix = backendRepository.GetAllAsync<KeyValue>(sqlObix).Result;
obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
obixApiConfig.UserName = ed.AESDecrypt(variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
obixApiConfig.Password = ed.AESDecrypt(variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
#endregion obix
#region get device and device_item(point)
var device = backendRepository.GetAllAsync<Device>($"select * from device where deleted = 0 and is_link = 1 and device_number in @Device_list", new { Device_list = post.Device_list }).Result;
var devicePoint = backendRepository.GetAllAsync<Device_item>($"select * from device_item where deleted = 0 and is_link = 1 and is_show_history = 1 and device_building_tag in @building_tag", new { building_tag = post.Building_tag_list }).Result;
#endregion
var building = backendRepository.GetAllAsync<BuildList>("select * from building where deleted = 0").Result;
List<DeviceNumberPoint> listDevicePoint = new List<DeviceNumberPoint>();
List<HistoryExport> he = new List<HistoryExport>();
List<JsonDevice> jd = new List<JsonDevice>();
#region combine device and point
// 因傳進來point不是比照前端順序故這邊又排序了一次
var Sql = $@"select c.full_name building_name,b.device_number,b.full_name device_name,a.full_name item_name,a.points,a.unit
from device_item a
join device b on a.device_system_tag = b.device_system_tag
and a.device_building_tag COLLATE utf8mb4_unicode_ci = b.device_building_tag
and a.device_name_tag COLLATE utf8mb4_unicode_ci = b.device_name_tag
join building c on c.building_tag = b.device_building_tag
join variable v1 on v1.system_value = b.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
join variable v2 on v2.system_value = b.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
where a.deleted = 0 and b.deleted = 0 and b.is_link = 1 and v2.deleted = 0 and v1.deleted = 0 and is_show_history = 1 and a.is_link = 1
and b.device_number = 'NTPC_G6_EE_E4_B1F_EMP_WHT_N1'
GROUP BY points
order by c.priority,b.priority,a.is_bool;";
var pointData = backendRepository.GetAllAsync<History_PostItem>(Sql).Result;
List<string> points = pointData.Select(x => x.points).ToList();
List<string> inputParams = post.Points;
inputParams.Sort((a, b) => points.IndexOf(a).CompareTo(points.IndexOf(b)));
foreach (var Device in post.Device_list)
{
foreach (var point in inputParams)
{
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
deviceNumberPoint.DeviceNumber = Device;
deviceNumberPoint.Point = point;
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", Device, point);
listDevicePoint.Add(deviceNumberPoint);
}
}
#endregion
#region get data from niagara
if (post.Type == 1)
{
#region Niagara抓資料依據日期
//轉換日期格式
var start = string.Format("{0}T{1}:00.000+08:00", post.Start_date, post.Start_time);
var end = string.Format("{0}T{1}:10.000+08:00", post.End_date, post.End_time);
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name = 'start' val = '{start}' />
<abstime name = 'end' val = '{end}' />
</obj>";
XmlDocument xmlDocument = new XmlDocument();
List<string> errorPoints = new List<string>(); //錯誤的設備點位
if (listDevicePoint.Count > 0)
{
foreach (var d in listDevicePoint)
{
var station = backendRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history where device_building_tag = '{d.FullDeviceNumberPoint.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{d.FullDeviceNumberPoint.Split("_")[2]}' and device_name_tag = '{d.FullDeviceNumberPoint.Split("_")[3]}'
and device_floor_tag = '{d.FullDeviceNumberPoint.Split("_")[4]}' and device_master_tag = '{d.FullDeviceNumberPoint.Split("_")[5]}'
and device_last_name_tag = '{d.FullDeviceNumberPoint.Split("_")[6]}' and device_serial_tag = '{d.FullDeviceNumberPoint.Split("_")[7]}'
and device_point_name = '{d.FullDeviceNumberPoint.Split("_")[8]}'").Result;
if (!string.IsNullOrEmpty(station))
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{d.FullDeviceNumberPoint}/~historyQuery/");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
xmlDocument.LoadXml(responseContent);
string responseContentJson = JsonConvert.SerializeXmlNode(xmlDocument);
JObject responseContentJsonResult = (JObject)JsonConvert.DeserializeObject(responseContentJson);
if (responseContentJsonResult.ContainsKey("err")) //抓取錯誤
{
errorPoints.Add(d.DeviceNumber);
continue;
}
if (responseContentJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var countObj = responseContentJsonResult["obj"]["int"];
if (countObj != null && countObj["@name"].ToString() == "count")
{ //判斷是否有資料筆數
if (Convert.ToInt32(countObj["@val"].ToString()) > 0)
{
var dataList = responseContentJsonResult["obj"]["list"];
if (dataList != null && dataList["obj"].HasValues)
{
//判斷單筆資料還是多筆
if (Convert.ToInt32(countObj["@val"].ToString()) == 1)
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
string buildingTag = d.DeviceNumber.Split("_")[1];
//取得時間
var abstime = dataList["obj"]["abstime"]["@val"].ToString();
var val = dataList["obj"]["real"] != null ?
dataList["obj"]["real"]["@val"].ToString() : dataList["obj"]["bool"]["@val"].ToString();
HistoryExport hed = new HistoryExport();
hed.device_number = device_number;
hed.type = devicePoint.Where(x => x.device_building_tag == buildingTag && x.points == point).Select(x => x.full_name).FirstOrDefault();
hed.deviceName = device.Where(x => x.device_number == device_number).Select(x => x.full_name).FirstOrDefault();
hed.value = val;
hed.timestamp = Convert.ToDateTime(abstime);
hed.building_tag = buildingTag;
he.Add(hed);
}
else
{
//讀取資料
foreach (var obj in dataList["obj"])
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
string buildingTag = d.DeviceNumber.Split("_")[1];
//取得時間
var abstime = obj["abstime"]["@val"].ToString();
var val = obj["real"] != null ?
obj["real"]["@val"].ToString() : obj["bool"]["@val"].ToString();
HistoryExport hed = new HistoryExport();
hed.device_number = device_number;
hed.type = devicePoint.Where(x => x.device_building_tag == buildingTag && x.points == point).Select(x => x.full_name).FirstOrDefault();
hed.deviceName = device.Where(x => x.device_number == device_number).Select(x => x.full_name).FirstOrDefault();
hed.value = val;
hed.timestamp = Convert.ToDateTime(abstime);
hed.building_tag = buildingTag;
he.Add(hed);
}
}
}
}
}
}
}
else
{
Logger.LogError("【Device GetWay Error】, device_number: " + d.FullDeviceNumberPoint);
}
}
}
if (errorPoints.Count() > 0)
{
Logger.LogError("【Device GetWay Error】, device_number: " + errorPoints);
}
#endregion
}
if (post.Type == 2)
{
#region Niagara抓資料依據時間段
DateTime startday = DateTime.Parse(post.Start_date);
DateTime endtday = DateTime.Parse(post.End_date);
List<DateTime> dateRange = Enumerable.Range(0, (endtday - startday).Days + 1)
.Select(a => startday.AddDays(a))
.ToList();
foreach (var day in dateRange)
{
//轉換日期格式
var start = string.Format("{0}T{1}:00.000+08:00", day.ToString("yyyy-MM-dd"), post.Start_time);
var end = string.Format("{0}T{1}:10.000+08:00", day.ToString("yyyy-MM-dd"), post.End_time);
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name = 'start' val = '{start}' />
<abstime name = 'end' val = '{end}' />
</obj>";
XmlDocument xmlDocument = new XmlDocument();
List<string> errorPoints = new List<string>(); //錯誤的設備點位
if (listDevicePoint.Count > 0)
{
foreach (var d in listDevicePoint)
{
var station = backendRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history where device_building_tag = '{d.FullDeviceNumberPoint.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{d.FullDeviceNumberPoint.Split("_")[2]}' and device_name_tag = '{d.FullDeviceNumberPoint.Split("_")[3]}'
and device_floor_tag = '{d.FullDeviceNumberPoint.Split("_")[4]}' and device_master_tag = '{d.FullDeviceNumberPoint.Split("_")[5]}'
and device_last_name_tag = '{d.FullDeviceNumberPoint.Split("_")[6]}' and device_serial_tag = '{d.FullDeviceNumberPoint.Split("_")[7]}'
and device_point_name = '{d.FullDeviceNumberPoint.Split("_")[8]}'").Result;
if (!string.IsNullOrEmpty(station))
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{d.FullDeviceNumberPoint}/~historyQuery/");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
xmlDocument.LoadXml(responseContent);
string responseContentJson = JsonConvert.SerializeXmlNode(xmlDocument);
JObject responseContentJsonResult = (JObject)JsonConvert.DeserializeObject(responseContentJson);
if (responseContentJsonResult.ContainsKey("err")) //抓取錯誤
{
errorPoints.Add(d.DeviceNumber);
continue;
}
if (responseContentJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var countObj = responseContentJsonResult["obj"]["int"];
if (countObj != null && countObj["@name"].ToString() == "count")
{ //判斷是否有資料筆數
if (Convert.ToInt32(countObj["@val"].ToString()) > 0)
{
var dataList = responseContentJsonResult["obj"]["list"];
if (dataList != null && dataList["obj"].HasValues)
{
//判斷單筆資料還是多筆
if (Convert.ToInt32(countObj["@val"].ToString()) == 1)
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
string buildingTag = d.DeviceNumber.Split("_")[1];
//取得時間
var abstime = dataList["obj"]["abstime"]["@val"].ToString();
var val = dataList["obj"]["real"] != null ?
dataList["obj"]["real"]["@val"].ToString() : dataList["obj"]["bool"]["@val"].ToString();
HistoryExport hed = new HistoryExport();
hed.device_number = device_number;
hed.type = devicePoint.Where(x => x.device_building_tag == buildingTag && x.points == point).Select(x => x.full_name).FirstOrDefault();
hed.deviceName = device.Where(x => x.device_number == device_number).Select(x => x.full_name).FirstOrDefault();
hed.value = val;
hed.timestamp = Convert.ToDateTime(abstime);
hed.building_tag = buildingTag;
he.Add(hed);
}
else
{
//讀取資料
foreach (var obj in dataList["obj"])
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
string buildingTag = d.DeviceNumber.Split("_")[1];
//取得時間
var abstime = obj["abstime"]["@val"].ToString();
var val = obj["real"] != null ?
obj["real"]["@val"].ToString() : obj["bool"]["@val"].ToString();
HistoryExport hed = new HistoryExport();
hed.device_number = device_number;
hed.type = devicePoint.Where(x => x.device_building_tag == buildingTag && x.points == point).Select(x => x.full_name).FirstOrDefault();
hed.deviceName = device.Where(x => x.device_number == device_number).Select(x => x.full_name).FirstOrDefault();
hed.value = val;
hed.timestamp = Convert.ToDateTime(abstime);
hed.building_tag = buildingTag;
he.Add(hed);
}
}
}
}
}
}
}
else
{
Logger.LogError("【Device GetWay Error】, device_number: " + d.FullDeviceNumberPoint);
}
}
}
if (errorPoints.Count() > 0)
{
Logger.LogError("【Device GetWay Error】, device_number: " + errorPoints);
}
}
#endregion
}
#endregion
#region export file progress
#region excel設定
IFont font12 = workbook.CreateFont();
font12.FontName = "新細明體";
font12.FontHeightInPoints = 12;
ICellStyle style12 = workbook.CreateCellStyle();
style12.SetFont(font12);
style12.Alignment = HorizontalAlignment.Center;
style12.VerticalAlignment = VerticalAlignment.Center;
IFont font12Times = workbook.CreateFont();
font12Times.FontName = "Times New Roman";
font12Times.FontHeightInPoints = 12;
IFont font18 = workbook.CreateFont();
font18.FontName = "新細明體";
font18.FontHeightInPoints = 18;
font18.IsBold = true;
ICellStyle styleTitle18 = workbook.CreateCellStyle();
styleTitle18.SetFont(font18);
styleTitle18.Alignment = HorizontalAlignment.Center;
styleTitle18.VerticalAlignment = VerticalAlignment.Center;
ICellStyle styleLeft12 = workbook.CreateCellStyle();
styleLeft12.SetFont(font12);
styleLeft12.Alignment = HorizontalAlignment.Left;
styleLeft12.VerticalAlignment = VerticalAlignment.Center;
ICellStyle styleLine12 = workbook.CreateCellStyle();
styleLine12.SetFont(font12);
styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
styleLine12.VerticalAlignment = VerticalAlignment.Center;
styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
ICellStyle stylein12 = workbook.CreateCellStyle();
stylein12.SetFont(font12Times);
stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;
stylein12.VerticalAlignment = VerticalAlignment.Center;
stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
stylein12.WrapText = true;
#endregion
var data = he.GroupBy(x => new { x.deviceName, x.type })
.SelectMany(g => g.OrderByDescending(x => x.timestamp))
.ToList(); ;
if (data.Count > 0)
{
string lastDeviceItem = string.Empty;
string lastDevice = string.Empty;
int RowPosition = 0;
IRow row;
ISheet sheet;
#region set cell
//sheet = workbook.CreateSheet($"{building.Where(x => x.building_tag == data[0].device_number.Split("_")[1]).Select(x => x.full_name).FirstOrDefault()}{"_" + data[0].deviceName + "_" + data[0].type}");
sheet = workbook.CreateSheet($"歷史資料");
row = sheet.CreateRow(RowPosition);
sheet.SetColumnWidth(0, 4 * 160 * 12);
sheet.SetColumnWidth(1, 4 * 160 * 12);
sheet.SetColumnWidth(2, 4 * 160 * 12);
sheet.SetColumnWidth(3, 4 * 160 * 12);
sheet.SetColumnWidth(4, 4 * 160 * 12);
ICell cell = row.CreateCell(0);
cell.SetCellValue("棟別");
cell.CellStyle = styleLine12;
cell = row.CreateCell(1);
cell.SetCellValue("設備名稱");
cell.CellStyle = styleLine12;
cell = row.CreateCell(2);
cell.SetCellValue("類型");
cell.CellStyle = styleLine12;
cell = row.CreateCell(3);
cell.SetCellValue("數值");
cell.CellStyle = styleLine12;
cell = row.CreateCell(4);
cell.SetCellValue("記錄時間");
cell.CellStyle = styleLine12;
#endregion
foreach (var d in data)
{
//if (RowPosition == 0 && lastDeviceItem == "" && lastDevice == "")
//{
// lastDeviceItem = d.type; //第一次不用建立 sheet;
// lastDevice = d.deviceName;
//}
//if (d.type != lastDeviceItem || d.deviceName != lastDevice)
//{
// RowPosition = 0;
// lastDeviceItem = d.type;
// lastDevice = d.deviceName;
// sheet = workbook.CreateSheet($"{building.Where(x => x.building_tag == d.device_number.Split("_")[1]).Select(x => x.full_name).FirstOrDefault()}{"_" + d.deviceName + "_" + d.type}");
// //sheet = workbook.CreateSheet($"{d.deviceName}{"_" + d.type}");
// #region set cell
// row = sheet.CreateRow(RowPosition);
// sheet.SetColumnWidth(0, 4 * 160 * 12);
// sheet.SetColumnWidth(1, 4 * 160 * 12);
// sheet.SetColumnWidth(2, 4 * 160 * 12);
// sheet.SetColumnWidth(3, 4 * 160 * 12);
// cell = row.CreateCell(0);
// cell.SetCellValue("類型");
// cell.CellStyle = styleLine12;
// cell = row.CreateCell(1);
// cell.SetCellValue("設備名稱");
// cell.CellStyle = styleLine12;
// cell = row.CreateCell(2);
// cell.SetCellValue("數值");
// cell.CellStyle = styleLine12;
// cell = row.CreateCell(3);
// cell.SetCellValue("記錄時間");
// cell.CellStyle = styleLine12;
// #endregion
// RowPosition = 1;
//}
//else
//{
// RowPosition += 1;
//}
RowPosition += 1;
row = sheet.CreateRow(RowPosition);
for (var i = 0; i < 5; i++)
{
cell = row.CreateCell(i);
if (i == 0)
{
cell.SetCellValue(building.Where(x => x.building_tag == d.device_number.Split("_")[1]).Select(x => x.full_name).FirstOrDefault());
}
if (i == 1)
{
cell.SetCellValue(d.deviceName);
}
if (i == 2)
{
cell.SetCellValue(d.type);
}
if (i == 3)
{
cell.SetCellValue(d.value);
}
if (i == 4)
{
cell.SetCellValue(d.timestamp.ToString("yyyy-MM-dd HH:mm:ss"));
}
cell.CellStyle = style12;
}
}
}
else
{
apiResult.Code = "0001";
apiResult.Msg = "選擇的區間沒有資料,無法匯出。";
return Json(apiResult);
}
#endregion
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message;
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Json(apiResult);
}
var ms = new NpoiMemoryStream
{
AllowClose = false
};
workbook.Write(ms);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
return File(ms, "application/vnd.ms-excel", fileName);
}
/// <summary>
/// 即時趨勢條件過濾條件面板
/// </summary>
/// <param name="account"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetMainSub")]
public async Task<ActionResult<ApiResult<History_MainSubBuildFloor>>> GetMainSub([FromBody] HistoryFind hf)
{
ApiResult<History_MainSubBuildFloor> apiResult = new ApiResult<History_MainSubBuildFloor>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
else if (string.IsNullOrEmpty(hf.building_tag))
{
apiResult.Code = "0002";
apiResult.Msg = "必須選擇東別";
return apiResult;
}
try
{
var dbsub = await frontendRepository.GetAllAsync<HistoryDBMainSub>(
@$"select distinct v1.system_key main_name, v1.system_value main_system_tag, v2.system_key sub_name, v2.system_value sub_system_tag, v1.system_priority, v2.system_priority,
d.device_number, d.full_name as device_full_name, d.device_serial_tag ,di.is_show_history device_item_is_show_hsitory
from role_auth a
join auth_page b on a.AuthCode = b.AuthCode
join userinfo c on c.role_guid = a.role_guid
join variable v2 on b.ShowView = v2.id and v2.system_type = @sub_system_type
join variable v1 on v1.id = v2.system_parent_id and v1.system_type = @main_system_type
join device d on v1.system_value = d.device_system_tag and v2.system_value = d.device_name_tag and d.deleted = 0 and d.visible = 1 and d.is_link = 1 and d.device_building_tag = @building_tag
join device_item di on d.device_system_tag=di.device_system_tag and d.device_name_tag=di.device_name_tag
and di.is_link = 1 and di.is_show_history = 1
where c.account = @account
order by v1.system_priority, v2.system_priority", new { @account = myUser.account, @sub_system_type = sub_system_type, @main_system_type = main_system_type, building_tag = hf.building_tag });
var dbbuilding = await frontendRepository.GetAllAsync<History_Build>(
@$"select distinct d.building_tag,d.full_name,d.priority from role_auth a
join auth_page b on a.AuthCode = b.AuthCode
join userinfo c on c.role_guid = a.role_guid
join building d on d.building_tag = b.building_tag
where c.account = @account and d.building_tag = @building_tag
order by d.priority
", new { @account = myUser.account, @building_tag = hf.building_tag });
var mains = dbsub.GroupBy(a => a.main_system_tag).ToList();
apiResult.Data = new History_MainSubBuildFloor();
apiResult.Data.history_Main_Systems = new List<History_Main_system>();
foreach (var main in mains)
{
History_Main_system history_Main_System = new History_Main_system();
history_Main_System.main_system_tag = main.Select(a => a.main_system_tag).FirstOrDefault();
history_Main_System.full_name = main.Select(a => a.main_name).FirstOrDefault();
var subs = dbsub.Where(x => x.main_system_tag == main.Select(m => m.main_system_tag).FirstOrDefault()).GroupBy(x => x.sub_system_tag).ToList();
history_Main_System.History_Sub_systems = subs.Count > 0 ? new List<History_Sub_system>() : null;
foreach (var sub in subs)
{
History_Sub_system history_Sub_System = new History_Sub_system();
if (main.Select(x => x.main_system_tag).FirstOrDefault() != "S")
{
history_Sub_System.full_name = sub.Select(x => x.sub_name).FirstOrDefault();
history_Sub_System.sub_system_tag = sub.Select(x => x.sub_system_tag).FirstOrDefault();
history_Sub_System.is_show_history = sub.Select(x => x.device_item_is_show_hsitory).FirstOrDefault();
}
else
{
string name = sub.Select(x => x.sub_name).FirstOrDefault();
bool check = true;
if (name == "人流計數")
check = sub.Any(x => x.sub_system_tag.StartsWith(hf.building_tag));
if (check)
{
history_Sub_System.full_name = sub.Select(x => x.sub_name).FirstOrDefault();
history_Sub_System.sub_system_tag = sub.Select(x => x.sub_system_tag).FirstOrDefault();
history_Sub_System.is_show_history = sub.Select(x => x.device_item_is_show_hsitory).FirstOrDefault();
}
}
var devices = dbsub.Where(x => x.main_system_tag == main.Select(m => m.main_system_tag).FirstOrDefault() && x.sub_system_tag == sub.Select(x => x.sub_system_tag).FirstOrDefault() && x.device_number != null).OrderBy(x => x.device_full_name.Length).ThenBy(x => x.device_full_name).ToList();
history_Sub_System.device = devices.Count > 0 ? new List<Device>() : null;
foreach (var d in devices)
{
Device device = new Device();
device.device_number = d.device_number;
device.device_serial_tag = d.device_serial_tag;
device.full_name = d.device_full_name;
history_Sub_System.device.Add(device);
}
if (history_Sub_System.is_show_history == 1)
{
history_Main_System.History_Sub_systems.Add(history_Sub_System);
}
}
apiResult.Data.history_Main_Systems.Add(history_Main_System);
}
apiResult.Data.history_Builds = dbbuilding;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Ok(apiResult);
}
return Ok(apiResult);
}
/// <summary>
/// 即時趨勢條件過濾條件面板
/// </summary>
/// <param name="account"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetDevPoi")]
public async Task<ActionResult<ApiResult<List<DeviceItem>>>> GetDevPoi([FromBody] HistoryFind hf)
{
ApiResult<List<DeviceItem>> apiResult = new ApiResult<List<DeviceItem>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
else if (string.IsNullOrEmpty(hf.device_number))
{
apiResult.Code = "0002";
apiResult.Msg = "必須選擇設備";
return apiResult;
}
try
{
List<DeviceItem> deviceItems = new List<DeviceItem>();
var main_system_value = hf.device_number.Split('_')[2];
var sub_system_value = hf.device_number.Split('_')[3];
var building_tag = char.IsDigit(hf.device_number.Split('_')[1][0]) ? "$3" + hf.device_number.Split('_')[1] : hf.device_number.Split('_')[1];
var sqlString = $@"select * from device_item where deleted = 0 and device_system_tag = @main_system_value and device_name_tag = @sub_system_value and is_show_history = 1 and device_building_tag = @building_tag";
deviceItems = await frontendRepository.GetAllAsync<DeviceItem>(sqlString, new { @main_system_value = main_system_value, @sub_system_value = sub_system_value, building_tag = building_tag });
apiResult.Data = deviceItems;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Ok(apiResult);
}
return Ok(apiResult);
}
/// <summary>
/// 依據過濾條件取得設備列表
/// </summary>
/// <param name="postDevice"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetDevice")]
public async Task<ActionResult<ApiResult<List<History_GetDevice>>>> GetDevice(History_PostDevice postDevice)
{
ApiResult<List<History_GetDevice>> apiResult = new ApiResult<List<History_GetDevice>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
List<string> wheres = new List<string>();
wheres.Add("d.deleted = 0");
if (postDevice.SelectBuildings != null && postDevice.SelectBuildings.Count() > 0)
{
wheres.Add("d.device_building_tag in @builds");
}
if (postDevice.SelectFloors != null && postDevice.SelectFloors.Count() > 0)
{
wheres.Add("d.device_floor_tag in @floor_tag");
}
if (postDevice.SelectSub != null && postDevice.SelectSub.Count() > 0)
{
wheres.Add("d.device_name_tag in @syss");
}
if (!string.IsNullOrEmpty(postDevice.Device_name))
{
wheres.Add("d.full_name LIKE CONCAT('%', @device_name, '%')");
}
var wheres_str = string.Join(" AND ", wheres);
var sql = $@"SELECT
a.device_guid,
b.full_name building_name,
v1.system_key main_name,
v2.system_key sub_name,
a.full_name device_name,
a.device_number
from (SELECT *
FROM device d
WHERE {wheres_str}) a
join building b on b.building_tag = a.device_building_tag
join variable v1 on v1.system_value = a.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
join variable v2 on v2.system_value = a.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
order by b.priority,v1.system_priority,v2.system_priority,a.priority";
var dbDevice = await backendRepository.GetAllAsync<History_GetDevice>(sql, new { builds = postDevice.SelectBuildings, floor_tag = postDevice.SelectFloors, syss = postDevice.SelectSub, device_name = postDevice.Device_name });
apiResult.Data = dbDevice;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 依據小類過濾條件取得設備列表
/// </summary>
/// <param name="SelectSub"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetDeviceInfo")]
public async Task<ActionResult<ApiResult<List<HistoryBuildingDevice>>>> GetDeviceInfo([FromBody] History_Sub_system SelectSub)
{
ApiResult<List<HistoryBuildingDevice>> apiResult = new ApiResult<List<HistoryBuildingDevice>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
List<string> wheres = new List<string>();
wheres.Add("d.deleted = 0 and is_link = 1");
if (SelectSub.sub_system_tag != null)
{
wheres.Add("d.device_name_tag = @syss");
}
var wheres_str = string.Join(" AND ", wheres);
var Sql = $@"SELECT
b.full_name building_name,
b.building_tag,
a.device_guid,
a.full_name device_name,
a.device_number
from (SELECT *
FROM device d
WHERE {wheres_str}) a
join building b on b.building_tag = a.device_building_tag and b.deleted = 0
join variable v1 on v1.system_value = a.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
join variable v2 on v2.system_value = a.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
order by b.priority,v1.system_priority,v2.system_priority,a.priority,a.device_serial_tag";
var data = await backendRepository.GetAllAsync<GetHistoryBuildingDevice>(Sql, new { syss = SelectSub.sub_system_tag });
var groupedData = data.GroupBy(x => x.building_tag);
List<HistoryBuildingDevice> historyBuildingDevices = groupedData.Select(group =>
new HistoryBuildingDevice
{
building_tag = group.Key,
building_name = group.First().building_name,
device_list = group.Select(item => new HistoryDevice
{
device_guid = item.device_guid,
device_number = item.device_number,
device_name = item.device_name
}).ToList()
}).ToList();
apiResult.Data = historyBuildingDevices;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 依據選得的設備,查看所有設備點位
/// </summary>
/// <param name="postDevice"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetAllDevPoi")]
public async Task<ActionResult<ApiResult<List<History_PostItem>>>> GetAllDevPoi([FromBody] PostHistoryDataFilter postDevice)
{
ApiResult<List<History_PostItem>> apiResult = new ApiResult<List<History_PostItem>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var dbDevice = await backendRepository.GetAllAsync<History_PostItem>(
@$"select c.full_name building_name,b.device_number,b.full_name device_name,a.full_name item_name,a.points,a.unit
from device_item a
join device b on a.device_system_tag = b.device_system_tag
and a.device_building_tag COLLATE utf8mb4_unicode_ci = b.device_building_tag
and a.device_name_tag COLLATE utf8mb4_unicode_ci = b.device_name_tag
join building c on c.building_tag = b.device_building_tag
join variable v1 on v1.system_value = b.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
join variable v2 on v2.system_value = b.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
where a.deleted = 0 and b.deleted = 0 and b.is_link = 1 and v2.deleted = 0 and v1.deleted = 0 and is_show_history = 1 and a.is_link = 1
and b.device_number in @Device_number
GROUP BY points
order by c.priority,b.priority,a.is_bool;"
, new { Device_number = postDevice.Device_list }
);
apiResult.Data = dbDevice;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 取得歷史資料
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetHistoryData")]
public async Task<ActionResult<PageResultT<HistoryRawData>>> GetHistoryData([FromBody] PostHistoryDataFilter post)
{
ApiResult<PageResultT<HistoryRawData>> apiResult = new ApiResult<PageResultT<HistoryRawData>>(jwt_str);
//if (!jwtlife)
//{
// apiResult.Code = "5000";
// return BadRequest(apiResult);
//}
//else if (post.Device_list == null || !post.Device_list.Any() || post.Points == null || !post.Points.Any())
//{
// apiResult.Code = "0001";
// apiResult.Msg = "請選擇設備及點位。";
// return apiResult;
//}
try
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
#region obix
EDFunction ed = new EDFunction();
var obixApiConfig = new ObixApiConfig();
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
var variable = await frontendRepository.GetAllAsync<KeyValue>(sqlObix);
obixApiConfig.ApiBase = variable.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
obixApiConfig.UserName = ed.AESDecrypt(variable.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
obixApiConfig.Password = ed.AESDecrypt(variable.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
#endregion obix
List<DeviceNumberPoint> listDevicePoint = new List<DeviceNumberPoint>();
List<HistoryRawData> historyRawDatas = new List<HistoryRawData>();
int pageNumber = post.PageNumber;
int pageSize = 10;
int totalItems = 0;
#region combine device and point
// 因傳進來point不是比照前端順序故這邊又排序了一次
var Sql = $@"select c.full_name building_name,b.device_number,b.full_name device_name,a.full_name item_name,a.points,a.unit
from device_item a
join device b on a.device_system_tag = b.device_system_tag
and a.device_building_tag COLLATE utf8mb4_unicode_ci = b.device_building_tag
and a.device_name_tag COLLATE utf8mb4_unicode_ci = b.device_name_tag
join building c on c.building_tag = b.device_building_tag
join variable v1 on v1.system_value = b.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
join variable v2 on v2.system_value = b.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
where a.deleted = 0 and b.deleted = 0 and b.is_link = 1 and v2.deleted = 0 and v1.deleted = 0 and is_show_history = 1 and a.is_link = 1
and b.device_number = 'NTPC_G6_EE_E4_B1F_EMP_WHT_N1'
GROUP BY points
order by c.priority,b.priority,a.is_bool;";
var pointData = backendRepository.GetAllAsync<History_PostItem>(Sql).Result;
List<string> points = pointData.Select(x => x.points).ToList();
List<string> inputParams = post.Points;
inputParams.Sort((a, b) => points.IndexOf(a).CompareTo(points.IndexOf(b)));
foreach (var Device in post.Device_list)
{
foreach (var point in inputParams)
{
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
deviceNumberPoint.DeviceNumber = Device;
deviceNumberPoint.Point = point;
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", Device, point);
listDevicePoint.Add(deviceNumberPoint);
}
}
#endregion
//依據被選擇的設備找出相對應資料
var sqlDeviceItemInfo = $@"select
b.full_name as building_name,
v1.system_key as Main_system_name,
v2.system_key as Sub_system_name,
temp.device_number,
temp.device_name,
temp.full_name as item_name,
temp.points,
temp.device_building_tag,
temp.unit
from (
select
di.*,
d.device_number,
d.full_name as device_name,
d.priority
from device_item di
inner join device d on di.device_building_tag COLLATE utf8mb4_unicode_ci = d.device_building_tag
and di.device_system_tag COLLATE utf8mb4_unicode_ci = d.device_system_tag
and di.device_name_tag COLLATE utf8mb4_unicode_ci = d.device_name_tag
and d.deleted = 0
where di.deleted = 0
and di.points in @points
and d.device_number IN @Device_number
) temp
inner join building b on temp.device_building_tag COLLATE utf8mb4_unicode_ci = b.building_tag and b.deleted = 0
inner join variable v1 on temp.device_system_tag COLLATE utf8mb4_unicode_ci = v1.system_value and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
inner join variable v2 on temp.device_name_tag COLLATE utf8mb4_unicode_ci = v2.system_value and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
order by b.priority, v1.system_priority, v2.system_priority, temp.priority;";
var device_item_infos = await frontendRepository.GetAllAsync<DeviceItemInfo>(sqlDeviceItemInfo, new { Device_number = post.Device_list, points = post.Points });
if (post.Type == 1)
{
#region Niagara抓資料依據日期
//轉換日期格式
var start = string.Format("{0}T{1}:00.000+08:00", post.Start_date, post.Start_time);
var end = string.Format("{0}T{1}:10.000+08:00", post.End_date, post.End_time);
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name = 'start' val = '{start}' />
<abstime name = 'end' val = '{end}' />
</obj>";
XmlDocument xmlDocument = new XmlDocument();
List<string> errorPoints = new List<string>(); //錯誤的設備點位
if (listDevicePoint.Count > 0)
{
foreach (var d in listDevicePoint)
{
var station = backendRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history where device_building_tag = '{d.FullDeviceNumberPoint.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{d.FullDeviceNumberPoint.Split("_")[2]}' and device_name_tag = '{d.FullDeviceNumberPoint.Split("_")[3]}'
and device_floor_tag = '{d.FullDeviceNumberPoint.Split("_")[4]}' and device_master_tag = '{d.FullDeviceNumberPoint.Split("_")[5]}'
and device_last_name_tag = '{d.FullDeviceNumberPoint.Split("_")[6]}' and device_serial_tag = '{d.FullDeviceNumberPoint.Split("_")[7]}'
and device_point_name = '{d.FullDeviceNumberPoint.Split("_")[8]}'").Result;
if (!string.IsNullOrEmpty(station))
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{d.FullDeviceNumberPoint}/~historyQuery/");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
xmlDocument.LoadXml(responseContent);
string responseContentJson = JsonConvert.SerializeXmlNode(xmlDocument);
JObject responseContentJsonResult = (JObject)JsonConvert.DeserializeObject(responseContentJson);
if (responseContentJsonResult.ContainsKey("err")) //抓取錯誤
{
errorPoints.Add(d.DeviceNumber);
continue;
}
if (responseContentJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var countObj = responseContentJsonResult["obj"]["int"];
totalItems += Convert.ToInt32(countObj["@val"].ToString());
if (countObj != null && countObj["@name"].ToString() == "count")
{ //判斷是否有資料筆數
if (Convert.ToInt32(countObj["@val"].ToString()) > 0)
{
var dataList = responseContentJsonResult["obj"]["list"];
if (dataList != null && dataList["obj"].HasValues)
{
//判斷單筆資料還是多筆
if (Convert.ToInt32(countObj["@val"].ToString()) == 1)
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
//取得時間
var abstime = dataList["obj"]["abstime"]["@val"].ToString();
historyRawData.Timestamp = Convert.ToDateTime(abstime).ToString("yyyy-MM-dd HH:mm:ss");
//取得資料
historyRawData.Value = dataList["obj"]["real"] != null ?
dataList["obj"]["real"]["@val"].ToString() : dataList["obj"]["bool"]["@val"].ToString();
historyRawData.Device_number = device_item_info.Device_number;
historyRawData.Building_name = device_item_info.Building_name;
historyRawData.Device_name = device_item_info.Device_name;
historyRawData.Points = device_item_info.Points;
historyRawDatas.Add(historyRawData);
}
else
{
//讀取資料
foreach (var obj in dataList["obj"])
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
//取得時間
var abstime = obj["abstime"]["@val"].ToString();
historyRawData.Timestamp = Convert.ToDateTime(abstime).ToString("yyyy-MM-dd HH:mm:ss");
//取得資料
historyRawData.Value = obj["real"] != null ?
obj["real"]["@val"].ToString() : obj["bool"]["@val"].ToString();
historyRawData.Device_number = device_item_info.Device_number;
historyRawData.Building_name = device_item_info.Building_name;
historyRawData.Device_name = device_item_info.Device_name;
historyRawData.Points = device_item_info.Points;
historyRawDatas.Add(historyRawData);
}
}
}
}
}
}
}
else
{
Logger.LogError("【Device GetWay Error】, device_number: " + d.FullDeviceNumberPoint);
}
}
}
if (errorPoints.Count() > 0)
{
Logger.LogError("【Device GetWay Error】, device_number: " + errorPoints);
}
#endregion
}
if (post.Type == 2)
{
#region Niagara抓資料依據時間段
DateTime startday = DateTime.Parse(post.Start_date);
DateTime endtday = DateTime.Parse(post.End_date);
List<DateTime> dateRange = Enumerable.Range(0, (endtday - startday).Days + 1)
.Select(a => startday.AddDays(a))
.ToList();
foreach (var day in dateRange)
{
//轉換日期格式
var start = string.Format("{0}T{1}:00.000+08:00", day.ToString("yyyy-MM-dd"), post.Start_time);
var end = string.Format("{0}T{1}:10.000+08:00", day.ToString("yyyy-MM-dd"), post.End_time);
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name = 'start' val = '{start}' />
<abstime name = 'end' val = '{end}' />
</obj>";
XmlDocument xmlDocument = new XmlDocument();
List<string> errorPoints = new List<string>(); //錯誤的設備點位
if (listDevicePoint.Count > 0)
{
foreach (var d in listDevicePoint)
{
var station = backendRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history where device_building_tag = '{d.FullDeviceNumberPoint.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{d.FullDeviceNumberPoint.Split("_")[2]}' and device_name_tag = '{d.FullDeviceNumberPoint.Split("_")[3]}'
and device_floor_tag = '{d.FullDeviceNumberPoint.Split("_")[4]}' and device_master_tag = '{d.FullDeviceNumberPoint.Split("_")[5]}'
and device_last_name_tag = '{d.FullDeviceNumberPoint.Split("_")[6]}' and device_serial_tag = '{d.FullDeviceNumberPoint.Split("_")[7]}'
and device_point_name = '{d.FullDeviceNumberPoint.Split("_")[8]}'").Result;
if (!string.IsNullOrEmpty(station))
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{d.FullDeviceNumberPoint}/~historyQuery/");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
xmlDocument.LoadXml(responseContent);
string responseContentJson = JsonConvert.SerializeXmlNode(xmlDocument);
JObject responseContentJsonResult = (JObject)JsonConvert.DeserializeObject(responseContentJson);
if (responseContentJsonResult.ContainsKey("err")) //抓取錯誤
{
errorPoints.Add(d.DeviceNumber);
continue;
}
if (responseContentJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var countObj = responseContentJsonResult["obj"]["int"];
totalItems += Convert.ToInt32(countObj["@val"].ToString());
if (countObj != null && countObj["@name"].ToString() == "count")
{ //判斷是否有資料筆數
if (Convert.ToInt32(countObj["@val"].ToString()) > 0)
{
var dataList = responseContentJsonResult["obj"]["list"];
if (dataList != null && dataList["obj"].HasValues)
{
//判斷單筆資料還是多筆
if (Convert.ToInt32(countObj["@val"].ToString()) == 1)
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
//取得時間
var abstime = dataList["obj"]["abstime"]["@val"].ToString();
historyRawData.Timestamp = Convert.ToDateTime(abstime).ToString("yyyy-MM-dd HH:mm:ss");
//取得資料
historyRawData.Value = dataList["obj"]["real"] != null ?
dataList["obj"]["real"]["@val"].ToString() : dataList["obj"]["bool"]["@val"].ToString();
historyRawData.Device_number = device_item_info.Device_number;
historyRawData.Building_name = device_item_info.Building_name;
historyRawData.Device_name = device_item_info.Device_name;
historyRawData.Points = device_item_info.Points;
historyRawDatas.Add(historyRawData);
}
else
{
//讀取資料
foreach (var obj in dataList["obj"])
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var device_number = d.DeviceNumber;
var point = d.Point;
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
//取得時間
var abstime = obj["abstime"]["@val"].ToString();
historyRawData.Timestamp = Convert.ToDateTime(abstime).ToString("yyyy-MM-dd HH:mm:ss");
//取得資料
historyRawData.Value = obj["real"] != null ?
obj["real"]["@val"].ToString() : obj["bool"]["@val"].ToString();
historyRawData.Device_number = device_item_info.Device_number;
historyRawData.Building_name = device_item_info.Building_name;
historyRawData.Device_name = device_item_info.Device_name;
historyRawData.Points = device_item_info.Points;
historyRawDatas.Add(historyRawData);
}
}
}
}
}
}
}
else
{
Logger.LogError("【Device GetWay Error】, device_number: " + d.FullDeviceNumberPoint);
}
}
}
if (errorPoints.Count() > 0)
{
Logger.LogError("【Device GetWay Error】, device_number: " + errorPoints);
}
}
#endregion
}
var data = historyRawDatas.GroupBy(x => new { x.Device_number, x.Points })
.SelectMany(g => g.OrderByDescending(x => x.Timestamp))
.ToList();
var pagedDevices = data.Skip((pageNumber - 1) * pageSize).Take(pageSize);
stopwatch.Stop();
double elapsedTime = stopwatch.Elapsed.TotalSeconds;
var result = new PageResultT<HistoryRawData>
{
Items = data,
PageNumber = pageNumber,
PageSize = pageSize,
TotalItems = totalItems,
ElapsedTime = elapsedTime,
};
apiResult.Code = "0000";
apiResult.Data = result;
return Ok(apiResult);
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.ToString());
return Ok(apiResult);
}
}
/// <summary>
/// 取得歷史資料常用組合
/// </summary>
/// <param></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetHistoryFavorite")]
public async Task<ActionResult<ApiResult<List<HistoryFavorite>>>> GetHistoryFavorite()
{
ApiResult<List<HistoryFavorite>> apiResult = new ApiResult<List<HistoryFavorite>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var sql = $@"SELECT * from history_favorite WHERE userinfo_guid = @userinfo_guid and deleted = 0";
var rawDatas = await frontendRepository.GetAllAsync<HistoryFavorite>(sql, new { userinfo_guid = myUser.userinfo_guid });
foreach (var item in rawDatas)
{
var detailSql = $@"SELECT * from history_favorite_detail WHERE favorite_guid = @favorite_guid";
var detailDatas = await frontendRepository.GetAllAsync<HistoryFavoriteDetail>(detailSql, new { favorite_guid = item.favorite_guid });
foreach (var detailData in detailDatas)
{
if (detailData.key == "device")
{
item.device_list.Add(detailData.value);
}
else
{
item.Points.Add(detailData.value);
}
}
}
apiResult.Data = rawDatas;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 儲存歷史資料常用組合
/// </summary>
/// <param></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/SaveHistoryFavorite")]
public async Task<ActionResult<ApiResult<List<HistoryFavorite>>>> SaveHistoryFavorite([FromBody] HistoryFavorite post)
{
ApiResult<List<HistoryFavorite>> apiResult = new ApiResult<List<HistoryFavorite>>(jwt_str);
var favorite = await frontendRepository.GetOneAsync<HistoryFavorite>("history_favorite", "favorite_name = @favorite_name and deleted = 0", new { favorite_name = post.favorite_name });
if (favorite != null)
{
apiResult.Code = "5000";
apiResult.Msg = "已有該組合名稱";
return Ok(apiResult);
}
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
//產生一組GUID
var guid = Guid.NewGuid(); //常用組合GUID
Dictionary<string, object> combination = new Dictionary<string, object>();
combination = new Dictionary<string, object>()
{
{ "@favorite_guid", guid},
{ "@favorite_name", post.favorite_name},
{ "@userinfo_guid", myUser.userinfo_guid},
{ "@device_name_tag", post.device_name_tag},
{ "@type", post.type},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
};
await frontendRepository.AddOneByCustomTable(combination, "history_favorite");
List<Dictionary<string, object>> detailDics = new List<Dictionary<string, object>>();
foreach (var device in post.device_list)
{
Dictionary<string, object> detailDic = new Dictionary<string, object>()
{
{ "@favorite_guid", guid},
{ "@key", "device"},
{ "@value", device}
};
detailDics.Add(detailDic);
}
foreach (var point in post.Points)
{
Dictionary<string, object> detailDic = new Dictionary<string, object>()
{
{ "@favorite_guid", guid},
{ "@key", "point"},
{ "@value", point}
};
detailDics.Add(detailDic);
}
await frontendRepository.AddMutiByCustomTable(detailDics, "history_favorite_detail");
apiResult.Msg = "儲存成功";
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 修改歷史資料常用組合名稱
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/EditHistoryFavorite")]
public async Task<ActionResult<ApiResult<string>>> EditHistoryFavoriten([FromBody] HistoryFavorite post)
{
ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var sWhere = $@"deleted = 0 AND favorite_guid = @favorite_guid";
var Combination = await frontendRepository.GetOneAsync<HistoryFavorite>("history_favorite", sWhere, new { favorite_guid = post.favorite_guid });
if (Combination == null)
{
apiResult.Code = "9998";
apiResult.Msg = "查無該組合";
return Ok(apiResult);
}
else
{
Dictionary<string, object> CombinationDic = new Dictionary<string, object>()
{
{ "@favorite_name", post.favorite_name },
{ "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
};
await frontendRepository.UpdateOneByCustomTable(CombinationDic, "history_favorite", $@"favorite_guid = '{post.favorite_guid}'");
}
apiResult.Msg = "修改成功。";
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 刪除歷史資料常用組合名稱
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/DeleteHistoryFavorite")]
public async Task<ActionResult<ApiResult<string>>> DeleteHistoryFavorite([FromBody] HistoryFavorite post)
{
ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var sWhere = $@"deleted = 0 AND favorite_guid = @favorite_guid";
var Combination = await frontendRepository.GetOneAsync<RealTimeCombination>("history_favorite", sWhere, new { favorite_guid = post.favorite_guid });
if (Combination == null)
{
apiResult.Code = "9998";
apiResult.Msg = "查無該組合";
return Ok(apiResult);
}
else
{
await frontendRepository.DeleteOne(post.favorite_guid, "history_favorite", "favorite_guid");
}
apiResult.Msg = "刪除成功。";
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 歷史資料依據選得的設備,查看所有設備點位
/// </summary>
/// <param name="postDevice"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/LookRealTime")]
public async Task<ActionResult<ApiResult<List<History_PostItem>>>> LookRealTime(itemlist postDevice)
{
ApiResult<List<History_PostItem>> apiResult = new ApiResult<List<History_PostItem>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var dbDevice = await backendRepository.GetAllAsync<History_PostItem>(
@$"select c.full_name building_name,b.device_number,b.full_name device_name,a.full_name item_name,a.points,a.unit
from device_item a
join device b on a.device_system_tag = b.device_system_tag
and a.device_building_tag COLLATE utf8mb4_unicode_ci = b.device_building_tag
and a.device_name_tag COLLATE utf8mb4_unicode_ci = b.device_name_tag
join building c on c.building_tag = b.device_building_tag
join variable v1 on v1.system_value = b.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
join variable v2 on v2.system_value = b.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
where a.deleted = 0 and b.deleted = 0 and v2.deleted = 0 and v1.deleted = 0
and a.unit is not null and b.device_number in @Device_number
order by c.priority,b.priority;"
, new { Device_number = postDevice.select_data.Select(a => a.device_number).ToList() }
);
apiResult.Data = dbDevice;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 取得即時趨勢常用組合
/// </summary>
/// <param name="postDevice"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/RealTimeCombination")]
public async Task<ActionResult<ApiResult<List<RealTimeCombination>>>> GetRealTimeCombination(PostRealTimeCombination post)
{
ApiResult<List<RealTimeCombination>> apiResult = new ApiResult<List<RealTimeCombination>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var sql = $@"
SELECT
rc.combination_guid,
rc.full_name AS combination_full_name,
rcd.device_guid,
d.device_number,
d.full_name AS Device_full_name,
b.full_name AS Building_full_name,
v1.system_key AS Main_system_full_name,
v2.system_key AS Sub_system_full_name
FROM realtime_combination_detail rcd
LEFT JOIN
(SELECT
rc.*
FROM realtime_combination rc
WHERE building_tag = @building_tag
AND userinfo_guid = @userinfo_guid
) rc ON rcd.combination_guid = rc.combination_guid
JOIN device d ON d.deleted = 0 AND d.device_guid = rcd.device_guid
JOIN building b ON b.deleted = 0 AND b.building_tag = d.device_building_tag
JOIN variable v1 ON v1.deleted = 0 AND v1.system_value = d.device_system_tag and v1.system_type = 'device_system_category_layer2'
JOIN variable v2 ON v2.deleted = 0 AND v2.system_value = d.device_name_tag and v2.system_type = 'device_system_category_layer3'
WHERE rc.deleted = 0";
var rawDatas = await frontendRepository.GetAllAsync<RealTimeCombinationRawData>(sql, new { building_tag = post.building_tag, userinfo_guid = myUser.userinfo_guid });
var rawDatas_groups = rawDatas.GroupBy(x => x.Combination_guid).ToList();
List<RealTimeCombination> realTimeCombinations = new List<RealTimeCombination>();
foreach (var rawDatas_group in rawDatas_groups)
{
RealTimeCombination realTimeCombination = new RealTimeCombination();
realTimeCombination.Combination_guid = rawDatas_group.Key;
realTimeCombination.Combination_full_name = rawDatas_group.First().Combination_full_name;
realTimeCombination.Details = new List<RealTimeCombinationDetail>();
foreach (var rawData in rawDatas_group)
{
RealTimeCombinationDetail realTimeCombinationDetail = new RealTimeCombinationDetail();
realTimeCombinationDetail.Combination_guid = rawData.Combination_guid;
realTimeCombinationDetail.Device_guid = rawData.Device_guid;
realTimeCombinationDetail.Device_number = rawData.Device_number;
realTimeCombinationDetail.Device_full_name = rawData.Device_full_name;
realTimeCombinationDetail.Building_full_name = rawData.Building_full_name;
realTimeCombinationDetail.Main_system_full_name = rawData.Main_system_full_name;
realTimeCombinationDetail.Sub_system_full_name = rawData.Sub_system_full_name;
realTimeCombination.Details.Add(realTimeCombinationDetail);
}
realTimeCombinations.Add(realTimeCombination);
}
apiResult.Data = realTimeCombinations;
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 新增常用組合(包含覆蓋、另存新檔)
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/SaveRealTimeCombination")]
public async Task<ActionResult<ApiResult<string>>> SaveRealTimeCombination(PostSaveRealTimeCombination post)
{
ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
if (post.Save_type == 1)
{ //另存新檔
//產生一組GUID
var guid = Guid.NewGuid(); //常用組合GUID
Dictionary<string, object> combination = new Dictionary<string, object>();
combination = new Dictionary<string, object>()
{
{ "@combination_guid", guid},
{ "@building_tag", post.Building_tag},
{ "@userinfo_guid", myUser.userinfo_guid},
{ "@full_name", post.Full_name},
{ "@created_by", myUser.userinfo_guid}
};
await frontendRepository.AddOneByCustomTable(combination, "realtime_combination");
List<Dictionary<string, object>> detailDics = new List<Dictionary<string, object>>();
foreach (var detail in post.Details)
{
Dictionary<string, object> detailDic = new Dictionary<string, object>()
{
{ "@combination_guid", guid},
{ "@device_guid", detail.Device_guid},
{ "@created_by", myUser.userinfo_guid}
};
detailDics.Add(detailDic);
}
await frontendRepository.AddMutiByCustomTable(detailDics, "realtime_combination_detail");
}
else
{ //覆蓋
var sWhere = $@"deleted = 0 AND combination_guid = @combination_guid";
var realTimeCombination = await frontendRepository.GetOneAsync<RealTimeCombination>("realtime_combination", sWhere, new { combination_guid = post.Combination_guid });
if (realTimeCombination == null)
{
apiResult.Code = "9996";
apiResult.Msg = "查無該常用組合";
return Ok(apiResult);
}
else
{
//刪除該組合的所有設備
await frontendRepository.PurgeOneAsync(realTimeCombination.Combination_guid, "realtime_combination_detail", "combination_guid");
//重新新增
List<Dictionary<string, object>> detailDics = new List<Dictionary<string, object>>();
foreach (var detail in post.Details)
{
Dictionary<string, object> detailDic = new Dictionary<string, object>()
{
{ "@combination_guid", realTimeCombination.Combination_guid},
{ "@device_guid", detail.Device_guid},
{ "@created_by", myUser.userinfo_guid}
};
detailDics.Add(detailDic);
}
await frontendRepository.AddMutiByCustomTable(detailDics, "realtime_combination_detail");
}
}
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 修改常用組合名稱
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/EditRealTimeCombination")]
public async Task<ActionResult<ApiResult<string>>> EditRealTimeCombination(PostEditRealTimeCombination post)
{
ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var sWhere = $@"deleted = 0 AND combination_guid = @combination_guid";
var realTimeCombination = await frontendRepository.GetOneAsync<RealTimeCombination>("realtime_combination", sWhere, new { combination_guid = post.Combination_guid });
if (realTimeCombination == null)
{
apiResult.Code = "9996";
}
else
{
Dictionary<string, object> realTimeCombinationDic = new Dictionary<string, object>()
{
{ "@full_name", post.Full_name },
{ "@updated_by", myUser.userinfo_guid},
{ "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
};
await frontendRepository.UpdateOneByCustomTable(realTimeCombinationDic, "realtime_combination", "combination_guid = '" + post.Combination_guid + "'");
}
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
/// <summary>
/// 刪除常用組合名稱
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/DeleteRealTimeCombination")]
public async Task<ActionResult<ApiResult<string>>> DeleteRealTimeCombination(string guid)
{
ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
var sWhere = $@"deleted = 0 AND combination_guid = @combination_guid";
var realTimeCombination = await frontendRepository.GetOneAsync<RealTimeCombination>("realtime_combination", sWhere, new { combination_guid = guid });
if (realTimeCombination == null)
{
apiResult.Code = "9996";
}
else
{
await frontendRepository.DeleteOne(guid, "realtime_combination", "combination_guid");
}
apiResult.Code = "0000";
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
}
return Ok(apiResult);
}
//[HttpPost]
//[Route("api/History/GetHistoryMenu")]
//public async Task<ActionResult<ApiResult<List<History_Main_system>>>> GetHistoryMenu(string account)
//{
// ApiResult<List<History_Main_system>> apiResult = new ApiResult<List<History_Main_system>>(jwt_str);
// if (!jwtlife)
// {
// apiResult.Code = "5000";
// return BadRequest(apiResult);
// }
// try
// {
// var dbitems = await backendRepository.GetAllAsync<HistoryClass>(
// @$"select c.main_system_guid ,c.full_name main_name,b.sub_system_guid,b.full_name sub_name,e.building_guid,e.full_name building_name,a.device_item_guid,a.full_name item_name
// from device_item a
// join sub_system b on b.sub_system_guid = a.sub_system_guid
// join main_system c on c.main_system_guid = b.main_system_guid
// join auth_page d on d.ShowView = b.sub_system_guid
// join building e on e.building_guid = d.building_guid
// join role_auth f on f.AuthCode = d.AuthCode
// join userinfo g on g.role_guid = f.role_guid
// where g.account = '{account}' and a.deleted = 0");
// var dbdevice = await backendRepository.GetAllAsync<History_Sub_device>
// ("device", " deleted = 0");
// var main_systems = dbitems.GroupBy(a => a.main_system_guid).ToList();
// List<History_Main_system> History_Main_system = new List<History_Main_system>();
// foreach (var main_system in main_systems)
// {
// History_Main_system history_Main_System = new History_Main_system()
// {
// History_Sub_systems = new List<History_Sub_system>(),
// main_system_guid = main_system.Select(a => a.main_system_guid).FirstOrDefault(),
// full_name = main_system.Select(a => a.main_name).FirstOrDefault()
// };
// var sub_systems = main_system.GroupBy(a => a.sub_system_guid).ToList();
// foreach (var sub_system in sub_systems)
// {
// History_Sub_system history_Sub_System = new History_Sub_system()
// {
// sub_system_guid = sub_system.Select(a => a.sub_system_guid).FirstOrDefault(),
// full_name = sub_system.Select(a => a.sub_name).FirstOrDefault(),
// History_Builds = new List<History_Build>()
// };
// var builds = sub_system.GroupBy(a => a.building_guid).ToList();
// foreach (var build in builds)
// {
// History_Build history_Build = new History_Build()
// {
// building_guid = build.Select(a => a.building_guid).First(),
// full_name = build.Select(a => a.building_name).FirstOrDefault(),
// History_Devices = new List<History_Device>()
// };
// var devices = dbdevice.Where(a => a.building_guid == history_Build.building_guid & a.sub_system_guid == history_Sub_System.sub_system_guid).ToList();
// foreach (var device in devices)
// {
// History_Device history_Device = new History_Device()
// {
// device_guid = device.device_guid,
// full_name = device.full_name,
// History_Deviceitems = new List<History_Deviceitem>()
// };
// var items = build.GroupBy(a => a.device_item_guid).ToList();
// foreach (var item in items)
// {
// History_Deviceitem history_Deviceitem = new History_Deviceitem()
// {
// device_item_guid = item.Select(a => a.device_item_guid).FirstOrDefault(),
// full_name = item.Select(a => a.item_name).FirstOrDefault()
// };
// history_Device.History_Deviceitems.Add(history_Deviceitem);
// }
// history_Build.History_Devices.Add(history_Device);
// }
// history_Sub_System.History_Builds.Add(history_Build);
// }
// history_Main_System.History_Sub_systems.Add(history_Sub_System);
// }
// History_Main_system.Add(history_Main_System);
// }
// apiResult.Code = "0000";
// apiResult.Data = History_Main_system;
// }
// catch (Exception exception)
// {
// apiResult.Code = "9999";
// Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
// return Ok(apiResult);
// }
// return Ok(apiResult);
//}
/// <summary>
/// 歷史資料查詢過濾條件面板
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetHistoryFilterPanel")]
public async Task<ActionResult<ApiResult<History_MainSubBuildFloor>>> GetHistoryFilterPanel(PostHistoryFilterPanel post)
{
ApiResult<History_MainSubBuildFloor> apiResult = new ApiResult<History_MainSubBuildFloor>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
#region
var sqlBuildingFloor = $@"SELECT
b.building_tag,
b.full_name AS building_name,
b.priority,
f.floor_guid,
f.full_name AS floor_name,
f.priority
FROM building b
JOIN floor f ON f.deleted = 0 AND f.building_tag = b.building_tag
WHERE b.building_tag IN (
SELECT
ap.building_tag
FROM role_auth ra
JOIN auth_page ap ON ra.AuthCode = ap.AuthCode
JOIN userinfo u ON u.role_guid = ra.role_guid WHERE u.account = @Account
)
ORDER BY b.priority, f.priority";
var buildingFloorRawDatas = await frontendRepository.GetAllAsync<BuildingFloorRawData>(sqlBuildingFloor, post);
var buildingFloorRawDatas_GroupBy_building_guid = buildingFloorRawDatas.GroupBy(x => x.building_tag).ToList();
List<History_Build> history_Builds = new List<History_Build>();
foreach (var buildingFloorRawData in buildingFloorRawDatas_GroupBy_building_guid)
{
List<History_Floor> history_Floors = new List<History_Floor>();
foreach (var floorRawData in buildingFloorRawData)
{
History_Floor history_Floor = new History_Floor()
{
floor_guid = floorRawData.floor_guid,
full_name = floorRawData.floor_name,
};
history_Floors.Add(history_Floor);
}
History_Build history_Build = new History_Build()
{
building_tag = buildingFloorRawData.Key,
full_name = buildingFloorRawData.First().building_name,
history_Floors = history_Floors
};
history_Builds.Add(history_Build);
}
#endregion
#region
var sqlMainSubSystem = $@"select
v1.system_value as main_system_tag, v1.system_key as main_name, v2.system_value as sub_system_tag, v2.system_key as sub_name
from variable v2
inner join variable v1 on v2.system_parent_id = v1.id
where v2.deleted = 0 and
v2.id in (
select ap.ShowView
from role_auth ra
inner join auth_page ap on ra.AuthCode = ap.AuthCode
inner join userinfo ui on ra.role_guid = ui.role_guid
where ui.account = @Account
)
order by v1.system_priority, v2.system_priority;";
var mainSubSystemRawDatas = await frontendRepository.GetAllAsync<HistoryDBMainSub>(sqlMainSubSystem, post);
var mainSubSystemRawDatas_GroupBy_main_system_guid = mainSubSystemRawDatas.GroupBy(x => x.main_system_tag).ToList();
List<History_Main_system> history_Main_Systems = new List<History_Main_system>();
foreach (var mainSubSystemRawData in mainSubSystemRawDatas_GroupBy_main_system_guid)
{
List<History_Sub_system> history_Sub_Systems = new List<History_Sub_system>();
foreach (var SubSystemRawData in mainSubSystemRawData)
{
History_Sub_system history_Sub_System = new History_Sub_system()
{
sub_system_tag = SubSystemRawData.sub_system_tag,
full_name = SubSystemRawData.sub_name,
};
history_Sub_Systems.Add(history_Sub_System);
}
History_Main_system history_Main_System = new History_Main_system()
{
main_system_tag = mainSubSystemRawData.Key,
full_name = mainSubSystemRawData.First().main_name,
History_Sub_systems = history_Sub_Systems
};
history_Main_Systems.Add(history_Main_System);
}
#endregion
History_MainSubBuildFloor history_MainSubBuildFloor = new History_MainSubBuildFloor()
{
history_Builds = history_Builds,
history_Main_Systems = history_Main_Systems
};
apiResult.Code = "0000";
apiResult.Data = history_MainSubBuildFloor;
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Ok(apiResult);
}
return Ok(apiResult);
}
/// <summary>
/// 取得歷史資料
/// </summary>
/// <param name="post"></param>
/// <returns></returns>
[HttpPost]
[Route("api/History/GetHistoryRawData")]
public async Task<ActionResult<ApiResult<List<HistoryRawData>>>> GetHistoryRawData(PostHistoryRawDataFilter post)
{
ApiResult<List<HistoryRawData>> apiResult = new ApiResult<List<HistoryRawData>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
try
{
EDFunction ed = new EDFunction();
var obixApiConfig = new ObixApiConfig();
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
var variable = await frontendRepository.GetAllAsync<KeyValue>(sqlObix);
obixApiConfig.ApiBase = variable.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
obixApiConfig.UserName = ed.AESDecrypt(variable.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
obixApiConfig.Password = ed.AESDecrypt(variable.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
//找出被選擇的設備編號
var device_numbers = post.HistoryItems.Select(x => x.Device_number_point.Split(":")[0]).Distinct().ToList();
//依據被選擇的設備找出相對應資料
var sqlDeviceItemInfo = $@"select
b.full_name as building_name,
v1.system_key as Main_system_name,
v2.system_key as Sub_system_name,
temp.device_number,
temp.device_name,
temp.full_name as item_name,
temp.points,
temp.unit
from (
select
di.*,
d.device_number,
d.full_name as device_name,
d.priority
from device_item di
inner join device d on di.device_building_tag COLLATE utf8mb4_unicode_ci = d.device_building_tag
and di.device_system_tag COLLATE utf8mb4_unicode_ci = d.device_system_tag
and di.device_name_tag COLLATE utf8mb4_unicode_ci = d.device_name_tag
and d.deleted = 0
where di.deleted = 0 and di.unit is not null and d.device_number IN @Device_number
) temp
inner join building b on temp.device_building_tag COLLATE utf8mb4_unicode_ci = b.building_tag and b.deleted = 0
inner join variable v1 on temp.device_system_tag COLLATE utf8mb4_unicode_ci = v1.system_value and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
inner join variable v2 on temp.device_name_tag COLLATE utf8mb4_unicode_ci = v2.system_value and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
order by b.priority, v1.system_priority, v2.system_priority, temp.priority;";
var device_item_infos = await frontendRepository.GetAllAsync<DeviceItemInfo>(sqlDeviceItemInfo, new { Device_number = device_numbers });
//轉換日期格式
var start = string.Format("{0}T00:00:00.000+08:00", post.Start_timestamp);
var end = string.Format("{0}T23:59:59.000+08:00", post.End_timestamp);
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name = 'start' val = '{start}' />
<abstime name = 'end' val = '{end}' />
</obj>";
XmlDocument xmlDocument = new XmlDocument();
List<HistoryRawData> historyRawDatas = new List<HistoryRawData>();
List<string> errorPoints = new List<string>(); //錯誤的設備點位
foreach (var historyItem in post.HistoryItems)
{
var device_number_point = historyItem.Device_number_point.Replace(":", "_");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{device_number_point}/~historyQuery/");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
xmlDocument.LoadXml(responseContent);
string responseContentJson = JsonConvert.SerializeXmlNode(xmlDocument);
JObject responseContentJsonResult = (JObject)JsonConvert.DeserializeObject(responseContentJson);
if (responseContentJsonResult.ContainsKey("err")) //抓取錯誤
{
errorPoints.Add(device_number_point);
continue;
}
if (responseContentJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var countObj = responseContentJsonResult["obj"]["int"];
if (countObj != null && countObj["@name"].ToString() == "count")
{ //判斷是否有資料筆數
if (Convert.ToInt32(countObj["@val"].ToString()) > 0)
{
var dataList = responseContentJsonResult["obj"]["list"];
if (dataList != null && dataList["obj"].HasValues)
{
//讀取資料
foreach (var obj in dataList["obj"])
{
HistoryRawData historyRawData = new HistoryRawData();
//取得設備基本資訊
var tempSplit = historyItem.Device_number_point.Split(":");
var device_number = tempSplit[0];
var point = tempSplit[1];
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
historyRawData.Building_name = device_item_info.Building_name;
historyRawData.Main_system_name = device_item_info.Main_system_name;
historyRawData.Sub_system_name = device_item_info.Sub_system_name;
historyRawData.Device_number = device_item_info.Device_number;
historyRawData.Device_name = device_item_info.Device_name;
historyRawData.Item_name = device_item_info.Item_name;
historyRawData.Points = device_item_info.Points;
historyRawData.Unit = device_item_info.Unit;
//取得時間
var abstime = obj["abstime"]["@val"].ToString();
historyRawData.Timestamp = Convert.ToDateTime(abstime).ToString("yyyy-MM-dd HH:mm:ss");
//取得資料
historyRawData.Value = obj["real"]["@val"].ToString();
historyRawDatas.Add(historyRawData);
}
}
}
}
}
}
if (errorPoints.Count() > 0)
{
apiResult.Code = "9998";
apiResult.Msg = String.Join(",", errorPoints);
return Ok(apiResult);
}
apiResult.Code = "0000";
apiResult.Data = historyRawDatas;
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.ToString());
return Ok(apiResult);
}
return Ok(apiResult);
}
/// <summary>
/// 即使歷史資料(前7天)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
[Route("api/HistoryRealTime")]
public async Task<ActionResult<ApiResult<List<HistoryRawData>>>> GetHistoryRealTime(PostHistoryRawDataFilter input)
{
ApiResult<List<HistoryRawData>> apiResult = new ApiResult<List<HistoryRawData>>(jwt_str);
apiResult.Data = new List<HistoryRawData>();
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
if (input.HistoryItems.Count == 0)
{
apiResult.Code = "9998";
apiResult.Msg = "沒有設備被選擇";
return BadRequest(apiResult);
}
try
{
//依據被選擇的設備找出相對應資料
var sqlDeviceItemInfo = $@"select
b.full_name as building_name,
v1.system_key as Main_system_name,
v2.system_key as Sub_system_name,
temp.device_number,
temp.device_name,
temp.full_name as item_name,
temp.points,
temp.unit
from (
select
di.*,
d.device_number,
d.full_name as device_name,
d.priority
from device_item di
inner join device d on di.device_building_tag COLLATE utf8mb4_unicode_ci = d.device_building_tag
and di.device_system_tag COLLATE utf8mb4_unicode_ci = d.device_system_tag
and di.device_name_tag COLLATE utf8mb4_unicode_ci = d.device_name_tag
and d.deleted = 0
where di.deleted = 0 and di.unit is not null and d.device_number = @Device_number
) temp
inner join building b on temp.device_building_tag COLLATE utf8mb4_unicode_ci = b.building_tag and b.deleted = 0
inner join variable v1 on temp.device_system_tag COLLATE utf8mb4_unicode_ci = v1.system_value and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2'
inner join variable v2 on temp.device_name_tag COLLATE utf8mb4_unicode_ci = v2.system_value and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3'
order by b.priority, v1.system_priority, v2.system_priority, temp.priority;";
foreach (var hi in input.HistoryItems)
{
var device_number = hi.Device_number_point.Split(":")[0];
var point = hi.Device_number_point.Split(":")[1];
var tableName = await backgroundServiceMsSqlRepository.GetOneAsync<string>($"select table_name from INFORMATION_SCHEMA.TABLES where table_name like '%{device_number}_{point}%'");
if (!string.IsNullOrEmpty(tableName))
{
var device_item_infos = await frontendRepository.GetAllAsync<DeviceItemInfo>(sqlDeviceItemInfo, new { Device_number = device_number });
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
var sql = $@"select '{device_item_info.Building_name}' as Building_name, '{device_item_info.Main_system_name}' as Main_system_name,
'{device_item_info.Sub_system_name}' as Sub_system_name, '{device_item_info.Device_number}' as Device_number,
'{device_item_info.Device_name}' as Device_name, '{device_item_info.Item_name}' as Item_name, '{device_item_info.Points}' as Points,
'{device_item_info.Unit}' as Unit, timestamp as Timestamp, round(value, 2) as Value
from FIC_CENTER_{device_number}_{point}
where replace(convert(varchar, [timestamp], 111), '/', '-') >= @startTime
and replace(convert(varchar, [timestamp], 111), '/', '-') <= @endTime order by timestamp";
apiResult.Data.AddRange(
await backgroundServiceMsSqlRepository.GetAllAsync<HistoryRawData>(sql, new { startTime = input.Start_timestamp, endTime = input.End_timestamp })
);
}
//foreach (var tn in tableName)
//{
//}
}
apiResult.Code = "0000";
apiResult.Data = apiResult.Data.OrderBy(x => x.Device_number).ThenBy(x => x.Timestamp).ToList();
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Ok(apiResult);
}
return Ok(apiResult);
}
private List<Dictionary<string, object>> ArrangeRawData(DeviceNumberPoint deviceNumberPoint, JObject jsonResult)
{
List<Dictionary<string, object>> arrangeRawDatas = new List<Dictionary<string, object>>();
var histories = jsonResult["obj"]["list"]["obj"];
var rawdateCount = Convert.ToInt32(jsonResult["obj"]["int"]["@val"].ToString());
if (rawdateCount == 0)
{
return null;
}
if (histories != null && histories.HasValues)
{
if (rawdateCount > 1)
{ //多筆資料
foreach (var history in histories)
{
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
arrangeRawData.Add("@point", deviceNumberPoint.Point);
//時間
if (history["abstime"] != null && history["abstime"].HasValues)
{
foreach (var abstime in history["abstime"])
{
var name = abstime["@name"].ToString();
switch (name)
{
case "start":
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (history["int"] != null && history["int"].HasValues)
{
var count = Convert.ToInt32(history["int"]["@val"].ToString());
arrangeRawData.Add("@count_rawdata", count);
}
//整合數值(最大、最小、平均、總和)
if (history["real"] != null && history["real"].HasValues)
{
foreach (var real in history["real"])
{
var name = real["@name"].ToString();
switch (name)
{
case "min":
var min = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@min_rawdata", min);
break;
case "max":
var max = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@sum_rawdata", sum);
break;
}
}
}
arrangeRawData.Add("@is_complete", 1);
arrangeRawData.Add("@repeat_times", 0);
arrangeRawData.Add("@fail_reason", null);
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
arrangeRawDatas.Add(arrangeRawData);
}
}
else
{ //單筆資料
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
arrangeRawData.Add("@point", deviceNumberPoint.Point);
//時間
if (histories["obj"]["abstime"] != null && histories["obj"]["abstime"].HasValues)
{
foreach (var abstime in histories["obj"]["abstime"])
{
var name = abstime["@name"].ToString();
switch (name)
{
case "start":
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (histories["obj"]["int"] != null && histories["obj"]["int"].HasValues)
{
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
arrangeRawData.Add("@count_rawdata", count);
}
//整合數值(最大、最小、平均、總和)
if (histories["obj"]["real"] != null && histories["obj"]["real"].HasValues)
{
foreach (var real in histories["obj"]["real"])
{
var name = real["@name"].ToString();
switch (name)
{
case "min":
var min = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@min_rawdata", min);
break;
case "max":
var max = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = real["@val"].ToString() == "NaN" ? -1 : Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@sum_rawdata", sum);
break;
}
}
}
arrangeRawData.Add("@is_complete", 1);
arrangeRawData.Add("@repeat_times", 0);
arrangeRawData.Add("@fail_reason", null);
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
arrangeRawDatas.Add(arrangeRawData);
}
}
return arrangeRawDatas;
}
}
}