調整同步流程

This commit is contained in:
dev02 2025-06-09 12:07:40 +08:00
commit 130ecba50f
14 changed files with 1569 additions and 887 deletions

View File

@ -266,7 +266,119 @@ namespace Backend.Models
#endregion
#region weather api
public class Root3
{
public string Success { get; set; }
public Records3 Records { get; set; }
}
public class Records3
{
public string DatasetDescription { get; set; }
public string LocationsName { get; set; }
public string Dataid { get; set; }
public List<Locations3> Locations { get; set; }
}
public class Locations3
{
public List<Location3> Location { get; set; }
}
public class Location3
{
public string LocationName { get; set; }
public string Geocode { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
public List<WeatherElement3> WeatherElement { get; set; }
}
public class WeatherElement3
{
public string ElementName { get; set; }
public List<Time> Time { get; set; }
}
public class Time
{
public string DataTime { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public List<ElementValue> ElementValue { get; set; }
}
public class ElementValue
{
/// <summary>
/// 溫度
/// </summary>
public string Temperature { get; set; }
/// <summary>
/// 露點溫度
/// </summary>
public string DewPoint { get; set; }
/// <summary>
/// 相對溼度
/// </summary>
public string RelativeHumidity { get; set; }
/// <summary>
/// 體感溫度
/// </summary>
public string ApparentTemperature { get; set; }
/// <summary>
/// 舒適度指數
/// </summary>
public string ComfortIndex { get; set; }
/// <summary>
/// 舒適度指數描述
/// </summary>
public string ComfortIndexDescription { get; set; }
/// <summary>
/// 風速
/// </summary>
public string WindSpeed { get; set; }
/// <summary>
/// 蒲福氏風級
/// </summary>
public string BeaufortScale { get; set; }
/// <summary>
/// 風向
/// </summary>
public string WindDirection { get; set; }
/// <summary>
/// 降雨機率
/// </summary>
public string ProbabilityOfPrecipitation { get; set; }
/// <summary>
/// 天氣現象
/// </summary>
public string Weather { get; set; }
/// <summary>
/// 天氣現象代號
/// </summary>
public string WeatherCode { get; set; }
/// <summary>
/// 天氣預報綜合描述
/// </summary>
public string WeatherDescription { get; set; }
}
public enum ElementName
{
,
,
,
,
,
,
,
,
,
}
#endregion

View File

@ -121,7 +121,7 @@ namespace BackendWorkerService
//);
//#endregion
#region ( 5 )
#region ( 5 )()
services.AddSingleton<ParkingJob>();
services.AddSingleton(
new JobSchedule(jobType: typeof(ParkingJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:ParkingJob"))
@ -142,7 +142,7 @@ namespace BackendWorkerService
);
#endregion
#region API
#region API()
services.AddSingleton<Quartz.Jobs.WeatherAPIJob>();
services.AddSingleton(
new JobSchedule(jobType: typeof(Quartz.Jobs.WeatherAPIJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:WeatherAPIJob"))

View File

@ -355,8 +355,8 @@ namespace BackendWorkerService.Quartz.Jobs
row.TryGetValue("@start_timestamp", out var yyyymmData);
dbDateName = System.DateTime.Parse(yyyymmData.ToString()).ToString("yyyyMM");
var sql = $@"CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_day_{dbDateName}` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`device_number` varchar(50) NOT NULL,
`point` varchar(20) NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
@ -367,11 +367,11 @@ namespace BackendWorkerService.Quartz.Jobs
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '0: 1:',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '',
`fail_reason` varchar(4000) NULL DEFAULT NULL COMMENT '',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
UPDATE archive_electric_water_meter_day_{dbDateName} SET
@ -524,8 +524,8 @@ namespace BackendWorkerService.Quartz.Jobs
dbDateName = System.DateTime.Parse(yyyymmData.ToString()).ToString("yyyyMM");
var sql = $@"
CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_day_{dbDateName}` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`device_number` varchar(50) NOT NULL,
`point` varchar(20) NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
@ -536,11 +536,11 @@ namespace BackendWorkerService.Quartz.Jobs
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '0: 1:',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '',
`fail_reason` varchar(4000) NULL DEFAULT NULL COMMENT '',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC;
UPDATE archive_electric_water_meter_day_{dbDateName} SET
count_rawdata = @count_rawdata,
@ -1357,8 +1357,8 @@ namespace BackendWorkerService.Quartz.Jobs
{
var sql = $@"
CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_month` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`device_number` varchar(50) NOT NULL,
`point` varchar(20) NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
@ -1369,11 +1369,11 @@ namespace BackendWorkerService.Quartz.Jobs
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '0: 1:',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '',
`fail_reason` varchar(4000) NULL DEFAULT NULL COMMENT '',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
UPDATE archive_electric_water_meter_month SET
@ -1523,8 +1523,8 @@ namespace BackendWorkerService.Quartz.Jobs
{
var sql = $@"
CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_month` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`device_number` varchar(50) NOT NULL,
`point` varchar(20) NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
@ -1535,11 +1535,11 @@ namespace BackendWorkerService.Quartz.Jobs
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '0: 1:',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '',
`fail_reason` varchar(4000) NULL DEFAULT NULL COMMENT '',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
UPDATE archive_electric_water_meter_month SET

View File

@ -38,14 +38,13 @@ namespace BackendWorkerService.Quartz.Jobs
private readonly IBackendRepository backendRepository;
private readonly ILogger<Task_Detail> loggers;
public LightScheduleJob(ILogger<LightScheduleJob> logger,
IBackgroundServiceRepository backgroundServiceRepository, IBackendRepository backendRepository, ILogger<Task_Detail> loggers)
IBackgroundServiceRepository backgroundServiceRepository, IBackendRepository backendRepository, ILogger<Task_Detail> loggers)
{
this.logger = logger;
this.backgroundServiceRepository = backgroundServiceRepository;
this.backendRepository = backendRepository;
this.loggers = loggers;
}
public async Task Execute(IJobExecutionContext context)
{
Task_Detail task_Detail = new Task_Detail(loggers, backendRepository);
@ -58,33 +57,13 @@ namespace BackendWorkerService.Quartz.Jobs
await task_Detail.InsertWorkTime("LightScheduleJob", "light_schedule");
var TimeNow = DateTime.Now.ToString("dddd HH:mm");
var schedule = await backendRepository.GetAllAsync<Schedule>("light_schedule","deleted = 0 and status = 1");
var schedule = await backendRepository.GetAllAsync<Schedule>("light_schedule", "deleted = 0 and status = 1");
string date = DateTime.Now.ToString("yyyy-MM-dd");
foreach (var oneSchedule in schedule)
{
// 檢查執行log
string light_schedule_guid = oneSchedule.light_schedule_guid;
string sWhere = @$"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'";
var schedule_log = await backendRepository.GetOneAsync<ScheduleLog>("light_schedule_log", sWhere);
string start_time = null;
string end_time = null;
if (schedule_log != null)
{
start_time = schedule_log.start_time;
end_time = schedule_log.end_time;
}
if (schedule_log == null)
{
Dictionary<string, object> log = new Dictionary<string, object>()
{
{ "@light_schedule_guid", light_schedule_guid},
{ "@date", date},
};
await backendRepository.AddOneByCustomTable(log, "light_schedule_log");
}
// 如果log有紀錄
// 先檢查今日否需執行
var weeklistN = oneSchedule.week.Split(',');
List<string> weeklist = new List<string>();
foreach (var weekN in weeklistN)
@ -102,35 +81,53 @@ namespace BackendWorkerService.Quartz.Jobs
};
weeklist.Add(week);
}
var Time = TimeNow.Split(" ");
string check = string.Empty;
// 檢查起始執行
if (start_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.start_time))
{
check = "<real val='true' />";
UpdatedNiagara(oneSchedule, check);
Dictionary<string, object> log = new Dictionary<string, object>()
{
{ "@start_time", Time[1]},
};
await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'");
logger.LogInformation($"【LightScheduleJob】【燈控排程開啟成功】排程名稱 :{oneSchedule.full_name}");
if (!weeklist.Contains(Time[0])) { continue; }
// 檢查執行log
string light_schedule_guid = oneSchedule.light_schedule_guid;
string sWhere = @$"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'";
var schedule_log = await backendRepository.GetOneAsync<ScheduleLog>("light_schedule_log", sWhere);
string start_time = null;
string end_time = null;
if (schedule_log != null)
{
start_time = schedule_log.start_time;
end_time = schedule_log.end_time;
}
if (schedule_log == null)
{
Dictionary<string, object> log = new Dictionary<string, object>()
{
{ "@light_schedule_guid", light_schedule_guid },
{ "@date", date },
};
await backendRepository.AddOneByCustomTable(log, "light_schedule_log");
}
string check = string.Empty;
// 檢查起始執行
if (start_time == null && end_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.start_time))
{
check = "true"; // 開啟
}
// 檢查結束執行
if (end_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.end_time))
{
check = "<real val='false' />";
UpdatedNiagara(oneSchedule, check);
Dictionary<string, object> log = new Dictionary<string, object>()
{
{ "@end_time", Time[1]},
};
await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'");
logger.LogInformation($"【LightScheduleJob】【燈控排程關閉成功】排程名稱 :{oneSchedule.full_name}");
check = "false"; // 關閉
}
if (!string.IsNullOrEmpty(check))
{
bool requestSuccess = await UpdatedNiagara(oneSchedule, check);
}
}
await task_Detail.InsertWorkTime_End("LightScheduleJob", "light_schedule");
}
catch (Exception ex)
@ -146,52 +143,279 @@ namespace BackendWorkerService.Quartz.Jobs
logger.LogError("【LightScheduleJob】【任務失敗】[Exception]{0}", exception.ToString());
}
}
public async void UpdatedNiagara(Schedule oneSchedule, string check)
public async Task<bool> UpdatedNiagara(Schedule oneSchedule, string check)
{
try
{
var deviceNumList = await backendRepository.GetAllAsync<string>(@$"select d.device_number from schedule_device sd join device d on sd.device_guid = d.device_guid
where light_schedule_guid = '{oneSchedule.light_schedule_guid}' and is_link = 1");
// 取得排程所對應的設備號碼列表
var deviceNumList = await backendRepository.GetAllAsync<string>(@$"SELECT d.device_number
FROM schedule_device sd
JOIN device d ON sd.device_guid = d.device_guid
WHERE light_schedule_guid = '{oneSchedule.light_schedule_guid}' AND is_link = 1");
// 取得obix配置
var variableObix = await backendRepository.GetAllAsync<Backend.Models.KeyValue>(@$"SELECT system_value as Value, system_key as Name
FROM variable
WHERE deleted = 0 AND system_type = 'obixConfig'");
// 取得obix相關配置參數
string url = variableObix.FirstOrDefault(x => x.Name == "ApiBase")?.Value;
string account = variableObix.FirstOrDefault(x => x.Name == "UserName")?.Value;
string pass = variableObix.FirstOrDefault(x => x.Name == "Password")?.Value;
// 檢查是否有配置缺失
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(account) || string.IsNullOrEmpty(pass))
{
logger.LogWarning("【LightScheduleJob】【obix配置缺失】請檢查obix配置");
return false;
}
// 準備HTTP請求的基本資訊
string authInfo = Convert.ToBase64String(Encoding.Default.GetBytes($"{account}:{pass}"));
// 構建每個設備的請求
List<string> batchRequests = new List<string>();
TagChangeFunction tagChange = new TagChangeFunction();
var variableObix = await backendRepository.GetAllAsync<Backend.Models.KeyValue>("SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'");
string url = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
string account = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault();
string pass = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault();
foreach (var deviceNum in deviceNumList)
{
TagChangeFunction tagChange = new TagChangeFunction();
// 處理設備號碼分解到URL中
var d = tagChange.AddStringIfStartsWithDigit(deviceNum, "$3");
var html = $"{url}obix/config/Arena/" + $"{d[0]}/{d[1]}/{d[2]}/{d[3]}/{deviceNum}/SSC/set";
string authInfo = account + ":" + pass;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(html);
request.Method = "POST";
request.Accept = "application/json; charset=utf-8";
request.Headers["Authorization"] = "Basic " + authInfo;
byte[] byteArray = Encoding.UTF8.GetBytes(check);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
var response = (HttpWebResponse)request.GetResponse();
string strResponse = "";
var uri = $"{url}obix/config/Arena/{d[0]}/{d[1]}/{d[2]}/{d[3]}/{deviceNum}/SSC/set";
using (var sr = new StreamReader(response.GetResponseStream()))
{
strResponse = sr.ReadToEnd();
}
// 只取err會取到override
if (strResponse.Contains("<err"))
{
logger.LogWarning($"【LightScheduleJob 】【set niagara light value fail】[排程 名稱]{oneSchedule.full_name},[設備 名稱]{deviceNum}");
}
// 構建要發送的實體資料
string realData = $"<real name='in' val='{check}' />";
// 建立批次請求
batchRequests.Add($"<uri is='obix:Invoke' val='{uri}'>" + realData + "</uri>");
}
// 構建整體批次請求
var batchRequestData = $@"<list is='obix:BatchIn'>
{string.Join("", batchRequests)}
</list>";
// 發送批次請求
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "obix/batch");
request.Method = "POST";
request.Accept = "application/json; charset=utf-8";
request.Headers["Authorization"] = "Basic " + authInfo;
// 將所有設備的請求內容合併成一個批次請求
byte[] byteArray = Encoding.UTF8.GetBytes(batchRequestData);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
// 發送請求並處理回應
var response = (HttpWebResponse)request.GetResponse();
string responseContent = string.Empty;
using (var sr = new StreamReader(response.GetResponseStream()))
{
responseContent = sr.ReadToEnd();
}
// 檢查回應中是否有錯誤
if (responseContent.Contains("<err"))
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
// 找到所有的 err 節點
XmlNodeList errNodes = xmlDocument.GetElementsByTagName("err");
// 如果有錯誤節點,進行處理
foreach (XmlNode errNode in errNodes)
{
logger.LogWarning($"【LightScheduleJob】【Niagara燈控設置失敗】排程名稱 :{oneSchedule.full_name} 顯示錯誤: {errNode}");
}
return false; // 如果有錯誤,返回 false
}
// 成功後記錄並更新結束時間
Dictionary<string, object> log = new Dictionary<string, object>();
string time = DateTime.Now.ToString("HH:mm");
if (check == "true")
{
log.Add("@start_time", time);
}
else
{
log.Add("@end_time", time);
}
await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{oneSchedule.light_schedule_guid}' and date = '{DateTime.Now:yyyy-MM-dd}'");
logger.LogInformation($"【LightScheduleJob】【Niagara燈控設置成功】排程名稱 :{oneSchedule.full_name}");
return true;
}
catch (Exception ex)
{
logger.LogError("【LightScheduleJob】" + "UpdatedNiagaraFail:" + ex.ToString());
throw ex;
logger.LogError("【LightScheduleJob】批次請求發送失敗:" + ex.ToString());
return false;
}
}
//public async Task Execute(IJobExecutionContext context)
//{
// Task_Detail task_Detail = new Task_Detail(loggers, backendRepository);
// try
// {
// if (await task_Detail.GetNeedWorkTask("LightScheduleJob", "light_schedule"))
// {
// try
// {
// await task_Detail.InsertWorkTime("LightScheduleJob", "light_schedule");
// var TimeNow = DateTime.Now.ToString("dddd HH:mm");
// var schedule = await backendRepository.GetAllAsync<Schedule>("light_schedule","deleted = 0 and status = 1");
// string date = DateTime.Now.ToString("yyyy-MM-dd");
// foreach (var oneSchedule in schedule)
// {
// // 檢查執行log
// string light_schedule_guid = oneSchedule.light_schedule_guid;
// string sWhere = @$"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'";
// var schedule_log = await backendRepository.GetOneAsync<ScheduleLog>("light_schedule_log", sWhere);
// string start_time = null;
// string end_time = null;
// if (schedule_log != null)
// {
// start_time = schedule_log.start_time;
// end_time = schedule_log.end_time;
// }
// if (schedule_log == null)
// {
// Dictionary<string, object> log = new Dictionary<string, object>()
// {
// { "@light_schedule_guid", light_schedule_guid},
// { "@date", date},
// };
// await backendRepository.AddOneByCustomTable(log, "light_schedule_log");
// }
// // 如果log有紀錄
// var weeklistN = oneSchedule.week.Split(',');
// List<string> weeklist = new List<string>();
// foreach (var weekN in weeklistN)
// {
// var week = weekN switch
// {
// "0" => "星期日",
// "1" => "星期一",
// "2" => "星期二",
// "3" => "星期三",
// "4" => "星期四",
// "5" => "星期五",
// "6" => "星期六",
// _ => ""
// };
// weeklist.Add(week);
// }
// var Time = TimeNow.Split(" ");
// string check = string.Empty;
// // 檢查起始執行
// if (start_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.start_time))
// {
// check = "<real val='true' />";
// UpdatedNiagara(oneSchedule, check);
// Dictionary<string, object> log = new Dictionary<string, object>()
// {
// { "@start_time", Time[1]},
// };
// await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'");
// logger.LogInformation($"【LightScheduleJob】【燈控排程開啟成功】排程名稱 :{oneSchedule.full_name}");
// }
// // 檢查結束執行
// if (end_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.end_time))
// {
// check = "<real val='false' />";
// UpdatedNiagara(oneSchedule, check);
// Dictionary<string, object> log = new Dictionary<string, object>()
// {
// { "@end_time", Time[1]},
// };
// await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'");
// logger.LogInformation($"【LightScheduleJob】【燈控排程關閉成功】排程名稱 :{oneSchedule.full_name}");
// }
// }
// await task_Detail.InsertWorkTime_End("LightScheduleJob", "light_schedule");
// }
// catch (Exception ex)
// {
// logger.LogInformation($"LightScheduleJob fail");
// await task_Detail.WorkFail("LightScheduleJob", "light_schedule", ex.Message.ToString());
// }
// }
// }
// catch (Exception exception)
// {
// logger.LogError("【LightScheduleJob】【任務失敗】");
// logger.LogError("【LightScheduleJob】【任務失敗】[Exception]{0}", exception.ToString());
// }
//}
//public async void UpdatedNiagara(Schedule oneSchedule, string check)
//{
// try
// {
// var deviceNumList = await backendRepository.GetAllAsync<string>(@$"select d.device_number from schedule_device sd join device d on sd.device_guid = d.device_guid
// where light_schedule_guid = '{oneSchedule.light_schedule_guid}' and is_link = 1");
// var variableObix = await backendRepository.GetAllAsync<Backend.Models.KeyValue>("SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'");
// string url = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
// string account = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault();
// string pass = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault();
// foreach (var deviceNum in deviceNumList)
// {
// TagChangeFunction tagChange = new TagChangeFunction();
// var d = tagChange.AddStringIfStartsWithDigit(deviceNum, "$3");
// var html = $"{url}obix/config/Arena/" + $"{d[0]}/{d[1]}/{d[2]}/{d[3]}/{deviceNum}/SSC/set";
// string authInfo = account + ":" + pass;
// authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
// HttpWebRequest request = (HttpWebRequest)WebRequest.Create(html);
// request.Method = "POST";
// request.Accept = "application/json; charset=utf-8";
// request.Headers["Authorization"] = "Basic " + authInfo;
// byte[] byteArray = Encoding.UTF8.GetBytes(check);
// using (Stream reqStream = request.GetRequestStream())
// {
// reqStream.Write(byteArray, 0, byteArray.Length);
// }
// var response = (HttpWebResponse)request.GetResponse();
// string strResponse = "";
// using (var sr = new StreamReader(response.GetResponseStream()))
// {
// strResponse = sr.ReadToEnd();
// }
// // 只取err會取到override
// if (strResponse.Contains("<err"))
// {
// logger.LogWarning($"【LightScheduleJob 】【set niagara light value fail】[排程 名稱]{oneSchedule.full_name},[設備 名稱]{deviceNum}");
// }
// }
// }
// catch (Exception ex)
// {
// logger.LogError("【LightScheduleJob】" + "UpdatedNiagaraFail:" + ex.ToString());
// throw ex;
// }
//}
}
}

View File

@ -95,79 +95,33 @@ namespace BackendWorkerService.Quartz.Jobs
if (spaceResponseResult != null && spaceResponseResult.Code == "20000")
{
List<string> batchRequests = new List<string>(); // 用來存儲批次請求的列表
foreach (var area in spaceResponseResult.Payload.Areas)
{
//找出對定的設備代碼
var selectedMapping = parkingSapceMapping.Where(x => x.System_key == area.Name).FirstOrDefault();
// 找出對應的設備代碼
var selectedMapping = parkingSapceMapping.FirstOrDefault(x => x.System_key == area.Name);
if (selectedMapping != null)
{
item = area.Name;
var name = area.Name; // 保存設備名稱
var tagName = selectedMapping.system_value;
var apiFormat = @"{0}obix/config/Arena/{1}/{2}/{3}/{4}/{5}/CV/set";
var tagNameSplit = tagName.Split("_");
var parames = new List<object>();
parames.Add(parkingConfig.ApiBase);
for (var i = 0; i < tagNameSplit.Length; i++)
{
if (i != tagNameSplit.Length - 1)
{
parames.Add(tagNameSplit[i]); // tag 前 4段
}
else
{
parames.Add(tagName); // 第五段 完整 tag
}
}
//logger.LogError(@$"【ParkingJob】【停車場剩餘車位】{apiFormat}");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(apiFormat, parames.ToArray()));
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
request.Timeout = System.Threading.Timeout.Infinite;
var parames = new List<object> { parkingConfig.ApiBase };
parames.AddRange(tagNameSplit.Take(tagNameSplit.Length - 1)); // tag 前 4段
parames.Add(tagName); // 最後一段 完整 tag
string requestUri = string.Format(apiFormat, parames.ToArray());
// 構建要發送的實體資料
var real = $@"<real val='{area.Remain}' />";
byte[] realByteArray = Encoding.UTF8.GetBytes(real);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(realByteArray, 0, realByteArray.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
batchRequests.Add($"<uri is='obix:Invoke' val='{requestUri}'>" +
$"<real name='in' val='{area.Remain}' />" +
$"</uri>");
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
string json = JsonConvert.SerializeXmlNode(xmlDocument);
JObject jsonResult = (JObject)JsonConvert.DeserializeObject(json);
if (jsonResult.ContainsKey("err")) //抓取錯誤
{
logger.LogError("【ParkingJob】【停車場剩餘車位資訊】");
logger.LogError("【ParkingJob】【停車場剩餘車位資訊】[錯誤內容]{0}", json);
}
else
{
if (jsonResult.ContainsKey("real")) //表示可以讀取到內容
{
List<Dictionary<string, object>> ontimeRawDatas = new List<Dictionary<string, object>>();
var realList = jsonResult["real"];
var display = realList["@display"];
if (display != null)
{
var tempStrSplit = display.ToString().Split(" ");
if (tempStrSplit[0] != area.Remain.ToString())
{
logger.LogError("【ParkingJob】【停車場剩餘車位資訊】[修改失敗]{0}", display.ToString());
}
else
{
logger.LogInformation("【ParkingJob】【停車場剩餘車位資訊】[修改成功]{0}", display.ToString());
logger.LogInformation("【ParkingJob】【停車場剩餘車位資訊】[停車場資訊]{0}", item);
}
}
}
}
// 進行日誌記錄
logger.LogInformation("【ParkingJob】【停車場剩餘車位】準備更新設備{0},剩餘車位數:{1}", name, area.Remain);
}
else
{
@ -175,11 +129,59 @@ namespace BackendWorkerService.Quartz.Jobs
}
}
if (batchRequests.Any())
{
// 建立批次請求 XML
var batchRequestXml = $@"<list is='obix:BatchIn'>
{string.Join("", batchRequests)}
</list>";
// 發送批次請求
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(parkingConfig.ApiBase + "obix/batch");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
request.Timeout = System.Threading.Timeout.Infinite;
byte[] requestData = Encoding.UTF8.GetBytes(batchRequestXml);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(requestData, 0, requestData.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
// 檢查回應中是否有錯誤
if (responseContent.Contains("<err"))
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
// 找到所有的 err 節點
XmlNodeList errNodes = xmlDocument.GetElementsByTagName("err");
// 如果有錯誤節點,進行處理
foreach (XmlNode errNode in errNodes)
{
logger.LogWarning($"【ParkingJob】【停車場剩餘車位資訊】[錯誤內容]{errNode}");
}
}
else
{
logger.LogInformation("【ParkingJob】【停車場剩餘車位資訊】[批次請求成功]");
}
}
else
{
logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】[沒有需要發送的請求]");
}
}
else
{
logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】 - [查無資料]");
}
await task_Detail.InsertWorkTime_End("ParkingJob", "Parking", "執行成功停車場剩餘車位Job");
//logger.LogInformation("【ParkingJob】【執行成功停車場剩餘車位Job】");
}
@ -233,91 +235,92 @@ namespace BackendWorkerService.Quartz.Jobs
if (equipmentResponseResult != null && equipmentResponseResult.Code == "20000")
{
List<string> batchRequests = new List<string>(); // 用來存儲批次請求的列表
foreach (var equipment in equipmentResponseResult.Payload)
{
//找出對定的設備代碼
var selectedMapping = parkingEquipmentMapping.Where(x => x.System_key == equipment.Id).FirstOrDefault();
// 找出對應的設備代碼
var selectedMapping = parkingEquipmentMapping.FirstOrDefault(x => x.System_key == equipment.Id);
if (selectedMapping != null)
{
item = equipment.Id;
var name = equipment.Id; // 保存設備ID
var tagName = selectedMapping.system_value;
var apiFormat = @"{0}obix/config/Arena/{1}/{2}/{3}/{4}/{5}/ST/set";
var tagNameSplit = tagName.Split("_");
var parames = new List<object>();
parames.Add(parkingConfig.ApiBase);
for (var i = 0; i < tagNameSplit.Length; i++)
{
if (i != tagNameSplit.Length - 1)
{
parames.Add(tagNameSplit[i]);
}
else
{
parames.Add(tagName);
}
}
var parames = new List<object> { parkingConfig.ApiBase };
parames.AddRange(tagNameSplit.Take(tagNameSplit.Length - 1)); // tag 前 4段
parames.Add(tagName); // 最後一段 完整 tag
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(apiFormat, parames.ToArray()));
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
string requestUri = string.Format(apiFormat, parames.ToArray());
// 構建要發送的實體資料
var real = $@"<real val='{equipment.Alive.ToString().ToLower()}' />";
byte[] realByteArray = Encoding.UTF8.GetBytes(real);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(realByteArray, 0, realByteArray.Length);
}
batchRequests.Add($"<uri is='obix:Invoke' val='{requestUri}'>" +
$"<real name='in' val='{equipment.Alive.ToString().ToLower()}' />" +
$"</uri>");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
string json = JsonConvert.SerializeXmlNode(xmlDocument);
JObject jsonResult = (JObject)JsonConvert.DeserializeObject(json);
if (jsonResult.ContainsKey("err")) //抓取錯誤
{
logger.LogError("【ParkingJob】【設備資訊】");
logger.LogError("【ParkingJob】【設備資訊】[錯誤內容]{0}", json);
}
else
{
if (jsonResult.ContainsKey("bool")) //表示可以讀取到內容
{
List<Dictionary<string, object>> ontimeRawDatas = new List<Dictionary<string, object>>();
var realList = jsonResult["bool"];
var val = realList["@val"];
if (val != null)
{
var tempStrSplit = val.ToString();
if (tempStrSplit != equipment.Alive.ToString().ToLower())
{
logger.LogError("【ParkingJob】【設備資訊】[修改失敗]{0}", val.ToString());
}
else
{
logger.LogInformation("【ParkingJob】【設備資訊】[修改成功]{0}", val.ToString());
logger.LogInformation("【ParkingJob】【設備資訊】[設備資訊]{0}", item);
}
}
}
}
// 進行日誌記錄
logger.LogInformation("【ParkingJob】【設備資訊】準備更新設備{0},設備狀態:{1}", name, equipment.Alive);
}
else
{
logger.LogWarning("【ParkingJob】【設備資訊】[查無該名稱對應表]{0}", equipment.Id);
}
}
if (batchRequests.Any())
{
// 建立批次請求 XML
var batchRequestXml = $@"<list is='obix:BatchIn'>
{string.Join("", batchRequests)}
</list>";
// 發送批次請求
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(parkingConfig.ApiBase + "obix/batch");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
byte[] requestData = Encoding.UTF8.GetBytes(batchRequestXml);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(requestData, 0, requestData.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
// 檢查回應中是否有錯誤
if (responseContent.Contains("<err"))
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
// 找到所有的 err 節點
XmlNodeList errNodes = xmlDocument.GetElementsByTagName("err");
// 如果有錯誤節點,進行處理
foreach (XmlNode errNode in errNodes)
{
logger.LogWarning($"【ParkingJob】【設備資訊】[錯誤內容]{errNode}");
}
}
else
{
logger.LogInformation("【ParkingJob】【設備資訊】[批次請求成功]");
}
}
else
{
logger.LogWarning("【ParkingJob】【設備資訊】[沒有需要發送的請求]");
}
}
else
{
logger.LogWarning("【ParkingJob】【設備資訊】 - [查無資料]");
}
await task_Detail.InsertWorkTime_End("ParkingJob", "Device", "執行成功設備資訊Job");
//logger.LogInformation("【ParkingJob】【執行成功設備資訊Job】");
}

View File

@ -20,6 +20,7 @@ using BackendWorkerService.Services.Implement;
using RainApi;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace BackendWorkerService.Quartz.Jobs
{
@ -128,7 +129,8 @@ namespace BackendWorkerService.Quartz.Jobs
HttpResponseMessage response = client.GetAsync(UVUri).Result;
String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString();
var observation = JsonConvert.DeserializeObject<Root>(jsonUVs);
var observation = JsonConvert.DeserializeObject<Root3>(jsonUVs); // Use Root3 here
logger.LogInformation("【WeatherAPIJob】【取得成功氣象預報】");
if (observation.Success != "true")
@ -139,67 +141,35 @@ namespace BackendWorkerService.Quartz.Jobs
{
logger.LogInformation("【WeatherAPIJob】【開始存入氣象預報到資料庫】");
List<Dictionary<string, object>> WeatherAPIdbS = new List<Dictionary<string, object>>();
var Type_ALL = observation.Records.Locations[0].Location[0].WeatherElement;
var Type_ALL = observation.Records.Locations[0].Location[1].WeatherElement; // Location[1]是信義區
foreach (var a in Type_ALL)
{
foreach (var b in a.Time)
{
if (a.ElementName == "PoP12h" || a.ElementName == "Wx")
{
if (Convert.ToDateTime(b.StartTime) > DateTime.Now.AddDays(1))
{
break;
}
}
else
{
if (Convert.ToDateTime(b.DataTime) > DateTime.Now.AddDays(1))
{
break;
}
}
Dictionary<string, object> WeatherAPIdb = new Dictionary<string, object>()
{
{ "@weather_type", a.ElementName},
{ "@data_no", DataNO},
{ "@get_value", b.ElementValue[0].Value},
{ "@measures", b.ElementValue[0].Measures},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
};
if (a.ElementName == "PoP12h" || a.ElementName == "Wx")
{
WeatherAPIdb.Add("@start_time", b.StartTime);
WeatherAPIdb.Add("@end_time", b.EndTime);
}
else
{
WeatherAPIdb.Add("@start_time", b.DataTime);
WeatherAPIdb.Add("@end_time", null);
}
WeatherAPIdbS.Add(WeatherAPIdb);
if (a.ElementName == "Wx")
{
Dictionary<string, object> TWeatherAPIdb = new Dictionary<string, object>()
{
{ "@weather_type", "WxV"},
{ "@weather_type", a.ElementName},
{ "@data_no", DataNO},
{ "@get_value", b.ElementValue[1].Value},
{ "@measures", b.ElementValue[1].Measures},
{ "@start_time", b.StartTime},
{ "@end_time", b.EndTime},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
};
WeatherAPIdbS.Add(TWeatherAPIdb);
}
ProcessElementValue(a, b, WeatherAPIdb, WeatherAPIdbS);
}
}
await backendRepository.AddMutiByCustomTable(WeatherAPIdbS, "api_weateher");
string sql = @"
INSERT INTO api_weateher (weather_type, data_no, get_value, get_value2, created_by, created_at, start_time, end_time)
VALUES (@weather_type, @data_no, @get_value, @get_value2, @created_by, @created_at, @start_time, @end_time)
ON DUPLICATE KEY UPDATE
get_value = VALUES(get_value),
get_value2 = VALUES(get_value2);";
foreach (var item in WeatherAPIdbS)
{
await backendRepository.ExecuteSql(sql, item);
}
}
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_weateher");
@ -245,16 +215,16 @@ namespace BackendWorkerService.Quartz.Jobs
.FirstOrDefault();
Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
{
{ "@msgType", observation.Alert.MsgType},
{ "@headline", taipeiInfo.Headline},
{ "@severity_level", severity_level },
{ "@areaDesc", area},
{ "@onset", taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@expires", taipeiInfo.Expires.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
};
{
{ "@msgType", observation.Alert.MsgType},
{ "@headline", taipeiInfo.Headline},
{ "@severity_level", severity_level },
{ "@areaDesc", area},
{ "@onset", taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@expires", taipeiInfo.Expires.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
};
var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain");
var val = RainValue(severity_level, taipeiInfo.Headline);
@ -387,17 +357,17 @@ namespace BackendWorkerService.Quartz.Jobs
var area = taipeiInfo.Area.Where(a => a.AreaDesc == "臺北市").Select(x => x.AreaDesc).FirstOrDefault();
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
{
{ "@msgType", observation.Alert.MsgType},
{ "@headline", taipeiInfo.Headline},
{ "@areaDesc", area},
{ "@urgency",taipeiInfo.Urgency},
{ "@severity",taipeiInfo.Severity},
{ "@onset", taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@expires", taipeiInfo.Expires.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
};
{
{ "@msgType", observation.Alert.MsgType},
{ "@headline", taipeiInfo.Headline},
{ "@areaDesc", area},
{ "@urgency",taipeiInfo.Urgency},
{ "@severity",taipeiInfo.Severity},
{ "@onset", taipeiInfo.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@expires", taipeiInfo.Expires.ToString("yyyy-MM-dd HH:mm:ss")},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
};
var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon");
if (taipeiInfo.Urgency != null && taipeiInfo.Urgency != "Expected")
{
@ -531,16 +501,16 @@ namespace BackendWorkerService.Quartz.Jobs
if (NeedCallApi == 0)
{
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
{
{ "@earthquakeNo", eq.EarthquakeNo},
{ "@newEarthquake", 1},
{ "@originTime", DateTime.Parse(eq.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)},
{ "@magnitudeValue", eq.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue},
{ "@areaName", exist.CountyName},
{ "@areaIntensity", exist.AreaIntensity},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
};
{
{ "@earthquakeNo", eq.EarthquakeNo},
{ "@newEarthquake", 1},
{ "@originTime", DateTime.Parse(eq.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)},
{ "@magnitudeValue", eq.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue},
{ "@areaName", exist.CountyName},
{ "@areaIntensity", exist.AreaIntensity},
{ "@created_by", "system"},
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
};
var Nag = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/ALMLEVL_LMI/set", Regex.Match(exist.AreaIntensity, @"\d+").ToString());
@ -660,44 +630,142 @@ namespace BackendWorkerService.Quartz.Jobs
await task_Detail.WorkFail("WeatherAPI", "api_earthquake", ex.Message.ToString());
}
}
// Niagara批次寫法
if (await task_Detail.GetNeedWorkTask("WeatherAPI", "set_weather"))
{
try
{
await task_Detail.InsertWorkTime("WeatherAPI", "set_weather");
var sql = @$"SELECT
id,
weather_type,
get_value
FROM api_weateher
where id in (select MAX(id) from api_weateher where start_time < NOW() group by weather_type)
order by start_time desc";
id,
weather_type,
get_value
FROM api_weateher
WHERE id IN (
SELECT MAX(id)
FROM api_weateher
WHERE start_time < NOW()
GROUP BY weather_type
)
ORDER BY start_time DESC";
var types = await backendRepository.GetAllAsync<ShowWeather>(sql);
var T = types.Where(a => a.weather_type == "T").FirstOrDefault();
var RbT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set", T.get_value);
UpdatedNiagara("api_weateher", RbT, T.id);
var urlMapping = new Dictionary<string, string>
{
{ "溫度", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set" },
{ "相對濕度", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set" },
{ "3小時降雨機率", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set" },
{ "天氣現象", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set" }
};
var RH = types.Where(a => a.weather_type == "RH").FirstOrDefault();
var RHT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set", RH.get_value);
UpdatedNiagara("api_weateher", RHT, RH.id);
// 建立批次請求
var batchRequests = types
.Where(t => urlMapping.ContainsKey(t.weather_type))
.Select(t => (
url: obixApiConfig.ApiBase + urlMapping[t.weather_type],
value: t.get_value
))
.ToList();
// 呼叫批次請求
var batchResponse = await ProcessBatchRequestAsync(obixApiConfig, batchRequests);
// 解析回應 XML
var batchResponseXml = XDocument.Parse(batchResponse);
var listElement = batchResponseXml.Descendants().FirstOrDefault(e => e.Name.LocalName == "list");
if (listElement == null)
{
throw new Exception("Batch response XML does not contain a 'list' element.");
}
var childElements = listElement.Elements().ToList();
// 使用 urlMapping 的值反向找對應的 weather_type
for (int i = 0; i < childElements.Count; i++)
{
var tag = childElements[i].Name.LocalName;
var responseStr = childElements[i].ToString();
var currentRequest = batchRequests[i];
// 找到當前 URL 在 urlMapping 中的 key (weather_type)
var weatherTypeKey = urlMapping.FirstOrDefault(x => currentRequest.url.Contains(x.Value)).Key;
if (weatherTypeKey != null)
{
var weatherType = types.FirstOrDefault(t => t.weather_type == weatherTypeKey);
if (weatherType != null)
{
if (tag == "err")
{
UpdatedNiagara("api_weateher", responseStr, weatherType.id);
}
else
{
UpdatedNiagara("api_weateher", "success", weatherType.id);
}
}
else
{
logger.LogWarning($"No matching weather type found for key: {weatherTypeKey}");
}
}
else
{
logger.LogWarning($"No matching URL found for request: {currentRequest.url}");
}
}
var PoP12h = types.Where(a => a.weather_type == "PoP12h").FirstOrDefault();
var PoP12hT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set", PoP12h.get_value);
UpdatedNiagara("api_weateher", PoP12hT, PoP12h.id);
var Wx = types.Where(a => a.weather_type == "Wx").FirstOrDefault();
var WxT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set", Wx.get_value);
UpdatedNiagara("api_weateher", WxT, Wx.id);
await task_Detail.InsertWorkTime_End("WeatherAPI", "set_weather");
logger.LogInformation($"set niagara weather value success");
logger.LogInformation($"Set Niagara weather value success");
}
catch (Exception ex)
{
logger.LogInformation($"set niagara weather value fail");
await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message.ToString());
logger.LogError($"Set Niagara weather value fail: {ex.Message}");
await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message);
}
}
// Niagara單次寫法
//if (await task_Detail.GetNeedWorkTask("WeatherAPI", "set_weather"))
//{
// try
// {
// await task_Detail.InsertWorkTime("WeatherAPI", "set_weather");
// var sql = @$"SELECT
// id,
// weather_type,
// get_value
// FROM api_weateher
// where id in (select MAX(id) from api_weateher where start_time < NOW() group by weather_type)
// order by start_time desc";
// var types = await backendRepository.GetAllAsync<ShowWeather>(sql);
// var T = types.Where(a => a.weather_type == "T").FirstOrDefault();
// var RbT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set", T.get_value);
// UpdatedNiagara("api_weateher", RbT, T.id);
// var RH = types.Where(a => a.weather_type == "RH").FirstOrDefault();
// var RHT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set", RH.get_value);
// UpdatedNiagara("api_weateher", RHT, RH.id);
// var PoP12h = types.Where(a => a.weather_type == "PoP12h").FirstOrDefault();
// var PoP12hT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set", PoP12h.get_value);
// UpdatedNiagara("api_weateher", PoP12hT, PoP12h.id);
// var Wx = types.Where(a => a.weather_type == "Wx").FirstOrDefault();
// var WxT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set", Wx.get_value);
// UpdatedNiagara("api_weateher", WxT, Wx.id);
// await task_Detail.InsertWorkTime_End("WeatherAPI", "set_weather");
// logger.LogInformation($"set niagara weather value success");
// }
// catch (Exception ex)
// {
// logger.LogInformation($"set niagara weather value fail");
// await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message.ToString());
// }
//}
}
catch (Exception exception)
{
@ -737,6 +805,125 @@ namespace BackendWorkerService.Quartz.Jobs
return rint;
}
public async Task<string> ProcessBatchRequestAsync(ObixApiConfig obixApiConfig, List<(string url, string value)> batchRequests)
{
try
{
var batchRequestData = new StringBuilder();
string authInfo = Convert.ToBase64String(Encoding.Default.GetBytes($"{obixApiConfig.UserName}:{obixApiConfig.Password}"));
// 組合批次請求的資料
foreach (var request in batchRequests)
{
var jsonData = $"<real name='in' val=\"{request.value}\" />";
batchRequestData.AppendLine($"<uri is='obix:Invoke' val='{request.url}'>" + jsonData + "</uri>");
}
// 最終的批次請求資料
var batchRequestXml = $@"<list is='obix:BatchIn'>{batchRequestData}</list>";
// 建立 HTTP 請求
var requestBacth = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/batch");
requestBacth.Method = "POST";
requestBacth.Headers.Add("Authorization", "Basic " + authInfo);
// 寫入請求資料
using (var streamWriter = new StreamWriter(requestBacth.GetRequestStream()))
{
streamWriter.Write(batchRequestXml);
}
// 獲取回應
using (var response = (HttpWebResponse)await requestBacth.GetResponseAsync())
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
return await streamReader.ReadToEndAsync();
}
}
catch (Exception)
{
return "BatchRequestg失敗";
}
}
//Helper Method to process Element Values
private void ProcessElementValue(WeatherElement3 a, Time b, Dictionary<string, object> WeatherAPIdb, List<Dictionary<string, object>> WeatherAPIdbS)
{
//Common parameters for element value
if (a.ElementName.Contains(ElementName..ToString()) || a.ElementName.Contains(ElementName..ToString()) || a.ElementName.Contains(ElementName..ToString()))
{
if (Convert.ToDateTime(b.StartTime) > DateTime.Now.AddDays(1))
{
return; // Skip to next element
}
WeatherAPIdb.Add("@start_time", Convert.ToDateTime(b.StartTime).ToString("yyyy-MM-dd HH:mm:ss"));
WeatherAPIdb.Add("@end_time", Convert.ToDateTime(b.EndTime).ToString("yyyy-MM-dd HH:mm:ss"));
}
else
{
if (Convert.ToDateTime(b.DataTime) > DateTime.Now.AddDays(1))
{
return; // Skip to next element
}
WeatherAPIdb.Add("@start_time", Convert.ToDateTime(b.DataTime).ToString("yyyy-MM-dd HH:mm:ss"));
WeatherAPIdb.Add("@end_time", null);
}
//Switch statement to handle different element names and their values
switch (a.ElementName)
{
case "溫度":
WeatherAPIdb.Add("@get_value", b.ElementValue[0].Temperature);
WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
break;
//case "露點溫度":
// WeatherAPIdb.Add("@get_value", b.ElementValue[0].DewPoint);
// WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
// break;
case "相對濕度":
WeatherAPIdb.Add("@get_value", b.ElementValue[0].RelativeHumidity);
WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
break;
//case "體感溫度":
// WeatherAPIdb.Add("@get_value", b.ElementValue[0].ApparentTemperature);
// WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
// break;
//case "舒適度指數":
// WeatherAPIdb.Add("@get_value", b.ElementValue[0].ComfortIndex);
// WeatherAPIdb.Add("@get_value2", b.ElementValue[0].ComfortIndexDescription);
// WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
// break;
//case "風速":
// WeatherAPIdb.Add("@get_value", b.ElementValue[0].WindSpeed);
// WeatherAPIdb.Add("@get_value2", b.ElementValue[0].BeaufortScale);
// WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
// break;
//case "風向":
// WeatherAPIdb.Add("@get_value", b.ElementValue[0].WindDirection);
// WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
// break;
case "3小時降雨機率":
WeatherAPIdb.Add("@get_value", b.ElementValue[0].ProbabilityOfPrecipitation);
WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
break;
case "天氣現象":
WeatherAPIdb.Add("@get_value", b.ElementValue[0].Weather);
WeatherAPIdb.Add("@get_value2", b.ElementValue[0].WeatherCode);
WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
break;
//case "天氣預報綜合描述":
// WeatherAPIdb.Add("@get_value", b.ElementValue[0].WeatherDescription);
// WeatherAPIdbS.Add(new Dictionary<string, object>(WeatherAPIdb));
// break;
}
}
public async void UpdatedNiagara(string DBTableName, string ResponseStr, int CheckNumId)
{
try

View File

@ -47,27 +47,27 @@ namespace FrontendWebApi.ApiControllers
(
SELECT w.get_value
FROM api_weateher w
WHERE w.weather_type = 'Wx' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC, w.id desc
WHERE w.weather_type = '' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC, w.id desc
limit 1
) AS WxText,
(
SELECT wd.WeatherKey
FROM api_weateher w
LEFT JOIN weather_description wd ON w.get_value = wd.WeatherValue
WHERE w.weather_type = 'WxV' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC, w.id desc
LEFT JOIN weather_description wd ON w.get_value2 = wd.WeatherValue
WHERE w.weather_type = '' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC, w.id desc
limit 1
) AS Wx,
(
SELECT w.get_value
FROM api_weateher w
WHERE w.weather_type = 'T' AND @DateNow >= w.start_time
WHERE w.weather_type = '' AND @DateNow BETWEEN w.start_time AND DATE_ADD(w.start_time, INTERVAL 1 HOUR)
order by created_at desc, id desc
limit 1
) AS Temp,
(
SELECT w.get_value
FROM api_weateher w
WHERE w.weather_type = 'RH' AND @DateNow >= w.start_time
WHERE w.weather_type = '' AND @DateNow BETWEEN w.start_time AND DATE_ADD(w.start_time, INTERVAL 1 HOUR)
order by created_at desc, id desc
limit 1
) AS RH

View File

@ -637,7 +637,7 @@ namespace FrontendWebApi.ApiControllers
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 import_niagara_item_history h on b.device_number = h.device_number and a.points = h.device_point_name
-- join import_niagara_item_history h on b.device_number = h.device_number and a.points = h.device_point_name
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

View File

@ -24,6 +24,8 @@ using System.Threading.Tasks;
using Image = System.Drawing.Image;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using NPOI.POIFS.Crypt.Dsig;
using System.Text;
namespace FrontendWebApi.ApiControllers
{
@ -32,230 +34,386 @@ namespace FrontendWebApi.ApiControllers
public class OperationLogController : MyBaseApiController<OperationLogController>
{
private readonly IBackendRepository backendRepository;
private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository;
private string operationFileSaveAsPath = "";
public OperationLogController(IBackendRepository backendRepository)
public OperationLogController(IBackendRepository backendRepository, IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository)
{
this.backendRepository = backendRepository;
operationFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "operation");
this.backgroundServiceMsSqlRepository = backgroundServiceMsSqlRepository;
}
/// <summary>
/// 巨蛋操作紀錄api 1:系統紀錄;2:登入紀錄;3:燈控排程紀錄
/// </summary>
/// <param name="pageResult"></param>
/// <returns></returns>
[HttpPost]
[Route("api/OperationLog/GetList")]
public async Task<ActionResult<ApiResult<List<OperationLogOutput>>>> GetList([FromBody] PageResult<OperationLogInput> pageResult)
[Route("api/OperationLog/GetLogList")]
public async Task<ApiResult<PageResult<List<OperationLogOutput>>>> GetLogList([FromBody] PageResult<OperationLogInput> pageResult)
{
ApiResult<List<OperationLogOutput>> apiResult = new ApiResult<List<OperationLogOutput>>(jwt_str);
if (!jwtlife)
{
apiResult.Code = "5000";
return BadRequest(apiResult);
}
ApiResult<PageResult<List<OperationLogOutput>>> apiResult = new ApiResult<PageResult<List<OperationLogOutput>>>();
List<OperationLogOutput> logList = new List<OperationLogOutput>();
int total = 0;
string start_time = DateTime.Parse(pageResult.data?.start_time).ToString("yyyy-MM-dd");
string end_time = DateTime.Parse(pageResult.data?.end_time).ToString("yyyy-MM-dd"); ;
string mark = pageResult.isEnable ? ";" : "\n";
try
{
string pageQuery = pageResult.isEnable ? " LIMIT @pageSize OFFSET @skip" : "";
// 取得資料
var logList = await backendRepository.GetAllAsync<OperationLogOutput>($@"
select ui.full_name as 'user_name' ,ol.* from operation_log ol
LEFT JOIN userinfo ui on ui.userinfo_guid COLLATE utf8mb4_unicode_ci = ol.user_guid
WHERE ol.operation_type = @operation_type AND ol.building_tag = @building_tag AND
ol.created_at >= @start_time AND ol.created_at <= @end_time
{pageQuery}",
new {
pageSize = pageResult.pageSize ,
skip = (pageResult.currentPage - 1) * pageResult.pageSize,
operation_type = pageResult.data?.operation_type,
building_tag = pageResult.data?.building_tag,
start_time = pageResult.data?.start_time,
end_time = pageResult.data?.end_time,
});
if (pageResult.data.type == 1 || pageResult.data.type == 2)
{
string building_tag = pageResult.data?.building_tag;
string tableName = (building_tag == "D2" || building_tag == "D3") ? "D2_Pri" : $"{building_tag}";
string sWhere = pageResult.data.type == 1 ? "OPERATION ='Invoked'" : "(OPERATION = 'Login' or OPERATION = 'Logout (Timeout)')";
string sWhere2 = pageResult.data.type == 1 ? ((building_tag == "D2" || building_tag == "D3") ?
"and (TARGET like '/Arena/D2%' or target like '/Arena/D3%')" : $"and TARGET like '/Arena/{building_tag}%'") : "";
string pageQuery = pageResult.isEnable ? "" : @"ORDER BY [TIMESTAMP] DESC -- 必須提供 ORDER BY 子句
OFFSET @skip ROWS
FETCH NEXT @pageSize ROWS ONLY;";
// 設定呈現紀錄內容
foreach (var log in logList) {
if (log.parameter == null) {
continue;
}
switch (log.operation_type) {
case 1:
var chaName = JsonConvert.DeserializeObject<ChangeName>(log.parameter);
if (chaName == null) continue;
log.content = chaName.TagName + "" + chaName.ChangeN;
break;
case 2:
var schedule = JsonConvert.DeserializeObject<SaveSchedule>(log.parameter);
if (schedule == null) continue;
var contentArr = new List<string>() {
string sql = $@"SELECT DISTINCT
[TIMESTAMP] created_at
,[OPERATION] action_name
,[TARGET] parameter
,[SLOTNAME]
,[OLDVALUE]
,[VALUE]
,[USERNAME] user_name
FROM [taipei_dome].[dbo].[ARENA_{tableName}_AUDITHISTORY]
WHERE {sWhere}
AND TIMESTAMP >= @start_time AND TIMESTAMP < DATEADD(day, 1, @end_time)
{sWhere2}
{pageQuery}";
// 取得資料
logList = await backgroundServiceMsSqlRepository.GetAllAsync<OperationLogOutput>(sql,
new
{
pageSize = pageResult.pageSize,
skip = (pageResult.currentPage - 1) * pageResult.pageSize,
operation_type = pageResult.data?.operation_type,
start_time = start_time,
end_time = end_time,
});
sql = @$"SELECT COUNT(*) AS TotalCount
FROM (
SELECT DISTINCT
[TIMESTAMP] created_at,
[OPERATION] action_name,
[TARGET] parameter,
[SLOTNAME],
[OLDVALUE],
[VALUE],
[USERNAME] user_name
FROM [taipei_dome].[dbo].[ARENA_{tableName}_AUDITHISTORY]
WHERE {sWhere}
AND TIMESTAMP >= @start_time AND TIMESTAMP < DATEADD(day, 1, @end_time)
{sWhere2}
) AS subquery;";
total = await backgroundServiceMsSqlRepository.GetOneAsync<int>(sql,
new
{
start_time = start_time,
end_time = end_time,
});
logList.ForEach(log => log.content = $"Target{log.parameter}{mark}Value{log.value}");
}
else if (pageResult.data.type == 3)
{
string pageQuery = pageResult.isEnable ? "" : "LIMIT @pageSize OFFSET @skip";
var sql = $@"SELECT ui.full_name AS user_name, ol.*
FROM operation_log ol
LEFT JOIN userinfo ui ON ui.userinfo_guid COLLATE utf8mb4_unicode_ci = ol.user_guid
WHERE ol.operation_type = @operation_type
AND ol.building_tag = @building_tag
AND ol.created_at >= @start_time
AND ol.created_at <= @end_time
{pageQuery}";
// 取得資料
logList = await backendRepository.GetAllAsync<OperationLogOutput>(sql,
new
{
pageSize = pageResult.pageSize,
skip = (pageResult.currentPage - 1) * pageResult.pageSize,
operation_type = pageResult.data?.operation_type,
building_tag = pageResult.data?.building_tag,
start_time = start_time,
end_time = end_time,
});
sql = $@"SELECT COUNT(*) AS total_count
FROM (
SELECT ui.full_name AS user_name, ol.*
FROM operation_log ol
LEFT JOIN userinfo ui ON ui.userinfo_guid COLLATE utf8mb4_unicode_ci = ol.user_guid
WHERE ol.operation_type = @operation_type
AND ol.building_tag = @building_tag
AND ol.created_at >= @start_time
AND ol.created_at <= @end_time
) AS subquery;";
total = await backendRepository.GetOneAsync<int>(sql,
new
{
operation_type = pageResult.data?.operation_type,
building_tag = pageResult.data?.building_tag,
start_time = start_time,
end_time = end_time,
});
// 設定呈現紀錄內容
foreach (var log in logList)
{
if (log.parameter == null)
{
continue;
}
switch (log.operation_type)
{
case 1:
var chaName = JsonConvert.DeserializeObject<ChangeName>(log.parameter);
if (chaName == null) continue;
log.content = chaName.TagName + "" + chaName.ChangeN;
break;
case 2:
var schedule = JsonConvert.DeserializeObject<SaveSchedule>(log.parameter);
if (schedule == null) continue;
var contentArr = new List<string>() {
"編號:" + schedule.light_schedule_guid,
"名稱:" + schedule.full_name,
};
if (log.action_name == "修改") {
contentArr.Add("修改內容:" + string.Join("、", schedule.changeNames));
}
log.content = string.Join("\n",contentArr);
break;
if (log.action_name == "修改")
{
contentArr.Add("修改內容:" + string.Join("、", schedule.changeNames));
}
log.content = string.Join(mark, contentArr);
break;
}
}
}
else
{
apiResult.Code = "5000";
apiResult.Msg = "無效參數";
return apiResult;
}
var result = new PageResult<List<OperationLogOutput>>
{
pageSize = pageResult.pageSize,
totalItem = total,
currentPage = pageResult.currentPage,
data = logList.OrderByDescending(log => log.created_at).ToList()
};
apiResult.Code = "0000";
apiResult.Data = logList;
apiResult.Data = result;
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
return Ok(apiResult);
return apiResult;
}
return Ok(apiResult);
return apiResult;
}
[HttpPost]
[Route("api/OperationLog/ExportList")]
public async Task<FileResult> ExportList([FromBody] OperationLogExportInput input)
public async Task<IActionResult> ExportList([FromBody] OperationLogExportInput input)
{
List<OperationLogOutput> result = new List<OperationLogOutput>();
if (input.isNiagara)
//if (input.isNiagara)
//{
// result = input.exportList;
//}
//else
//{
// PageResult<OperationLogInput> pageResult = input.listInput;
// pageResult.isEnable = false;
// result = ((ApiResult<List<OperationLogOutput>>)((OkObjectResult)(await this.GetList(pageResult)).Result).Value).Data.ToList();
//}
input.listInput.isEnable = true;
result = GetLogList(input.listInput).Result.Data.data;
var FileName = $"{input.exportOpeTypeName}_{DateTime.Now}.csv";
// 生成CSV文件
string Csv;
string formatted_created_at = null;
if (result.Count > 0)
{
result = input.exportList;
StringBuilder csv = new StringBuilder();
// 添加CSV標題行
csv.AppendLine("操作人,動作,內容,紀錄時間");
// 添加數據行
foreach (var item in result)
{
if (item.created_at.HasValue)
{
formatted_created_at = item.created_at.Value.ToString("yyyy/MM/dd HH:mm:ss");
}
csv.AppendLine($"{item.user_name},{item.action_name},{item.content},{formatted_created_at}");
}
Csv = csv.ToString();
using (var fileMemoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(fileMemoryStream, Encoding.UTF8))
{
streamWriter.Write(Csv);
}
return File(fileMemoryStream.ToArray(), "text/csv", FileName);
}
}
else
{
PageResult<OperationLogInput> pageResult = input.listInput;
pageResult.isEnable = false;
result = ((ApiResult<List<OperationLogOutput>>)((OkObjectResult)(await this.GetList(pageResult)).Result).Value).Data.ToList();
var msg = new { Code = "0003", Msg = "無資料可匯出。" };
return StatusCode(400, msg);
}
var workbook = new XSSFWorkbook();
#region excel寫法 1,048,576
#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;
//var workbook = new XSSFWorkbook();
//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 sheet = workbook.CreateSheet(input.exportOpeTypeName);
int RowPosition = 0;
if (result.Count > 0)
{
#region set cell
int ri = 0;
IRow row = sheet.CreateRow(RowPosition);
if (!input.isNiagara) {
sheet.SetColumnWidth(ri++, 1 * 160 * 12);
}
sheet.SetColumnWidth(ri++, 2 * 160 * 12);
sheet.SetColumnWidth(ri++, 2 * 160 * 12);
sheet.SetColumnWidth(ri++, 8 * 160 * 12);
sheet.SetColumnWidth(ri++, 4 * 160 * 12);
//var sheet = workbook.CreateSheet(input.exportOpeTypeName);
//int RowPosition = 0;
//if (result.Count > 0)
//{
// #region set cell
// int ri = 0;
// IRow row = sheet.CreateRow(RowPosition);
// //if (!input.isNiagara)
// //{
// // sheet.SetColumnWidth(ri++, 1 * 160 * 12);
// //}
// sheet.SetColumnWidth(ri++, 2 * 160 * 12);
// sheet.SetColumnWidth(ri++, 2 * 160 * 12);
// sheet.SetColumnWidth(ri++, 8 * 160 * 12);
// sheet.SetColumnWidth(ri++, 4 * 160 * 12);
int i = 0;
// int i = 0;
ICell cell = row.CreateCell(i++);
if (!input.isNiagara)
{
cell.SetCellValue("編號");
cell.CellStyle = styleLine12;
cell = row.CreateCell(i++);
}
cell.SetCellValue("操作人");
cell.CellStyle = styleLine12;
cell = row.CreateCell(i++);
cell.SetCellValue("動作");
cell.CellStyle = styleLine12;
// ICell cell = row.CreateCell(i++);
// //if (!input.isNiagara)
// //{
// // cell.SetCellValue("編號");
// // cell.CellStyle = styleLine12;
// // cell = row.CreateCell(i++);
// //}
// cell.SetCellValue("操作人");
// cell.CellStyle = styleLine12;
// cell = row.CreateCell(i++);
// cell.SetCellValue("動作");
// cell.CellStyle = styleLine12;
cell = row.CreateCell(i++);
cell.SetCellValue("內容");
cell.CellStyle = styleLine12;
cell = row.CreateCell(i++);
cell.SetCellValue("紀錄時間");
cell.CellStyle = styleLine12;
#endregion
// cell = row.CreateCell(i++);
// cell.SetCellValue("內容");
// cell.CellStyle = styleLine12;
// cell = row.CreateCell(i++);
// cell.SetCellValue("紀錄時間");
// cell.CellStyle = styleLine12;
// #endregion
foreach (var r in result)
{
RowPosition += 1;
int k = 3;
row = sheet.CreateRow(RowPosition);
for (int j = 0; j <= i; j++)
{
int s = 0;
cell = row.CreateCell(j);
if (!input.isNiagara && j == s++)
{
cell.SetCellValue(r.id);
}
if (j == s++)
{
cell.SetCellValue(r.user_name);
}
if (j == s++)
{
cell.SetCellValue(r.action_name);
}
// foreach (var r in result)
// {
// RowPosition += 1;
// int k = 3;
// row = sheet.CreateRow(RowPosition);
// for (int j = 0; j <= i; j++)
// {
// int s = 0;
// cell = row.CreateCell(j);
// //if (!input.isNiagara && j == s++)
// //{
// // cell.SetCellValue(r.id);
// //}
// if (j == s++)
// {
// cell.SetCellValue(r.user_name);
// }
// if (j == s++)
// {
// cell.SetCellValue(r.action_name);
// }
if (j == s++)
{
cell.SetCellValue(r.content);
}
if (j == s++)
{
cell.SetCellValue(r.created_at != null ? ((DateTime)r.created_at).ToString("yyyy-MM-dd HH:mm:ss") : null);
}
// if (j == s++)
// {
// cell.SetCellValue(r.content);
// }
cell.CellStyle = style12;
}
}
}
// if (j == s++)
// {
// cell.SetCellValue(r.created_at != null ? ((DateTime)r.created_at).ToString("yyyy-MM-dd HH:mm:ss") : null);
// }
var ms = new NpoiMemoryStream
{
AllowClose = false
};
workbook.Write(ms);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
// cell.CellStyle = style12;
// }
// }
//}
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
//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", $"操作紀錄_{input.exportOpeTypeName}.xlsx");
#endregion
return File(ms, "application/vnd.ms-excel", $"操作紀錄_{input.exportOpeTypeName}.xlsx");
}
}
}

View File

@ -751,7 +751,6 @@ namespace FrontendWebApi.ApiControllers
var fileDateName = DateTime.Now.ToString("yyyy-MM-ddTHH-mm-ss");
var waterMeterFileName = $"水電報表_水錶_{fileDateName}.csv";
var electricMeterFileName = $"水電報表_電錶_{fileDateName}.csv";
var zipFileName = $"水電報表_{fileDateName}.zip";
try
{
@ -790,7 +789,7 @@ namespace FrontendWebApi.ApiControllers
// 判斷是否有資料
if (existMonth.Count == 0)
{
var msg = new { Code = "0001", Msg = "還沒有選擇用戶,無法匯出檔案。" };
var msg = new { Code = "0001", Msg = "時間段無資料或無設置用戶。" };
return StatusCode(400, msg);
}
else
@ -862,12 +861,6 @@ namespace FrontendWebApi.ApiControllers
var waterMeterData = outputBillExcel.Where(x => x.device_name_tag == "W1" && x.building_tag == tb.building_tag).ToList();
var electricMeterData = outputBillExcel.Where(x => x.device_name_tag == "E4" && x.building_tag == tb.building_tag).ToList();
// 檢查是否有水錶或電錶數據
//if (waterMeterData.Count == 0 && electricMeterData.Count == 0)
//{
// var msg = new { Code = "0002", Msg = "該棟沒有可匯出的水錶或電錶數據。" };
// return StatusCode(400, msg);
//}
if (tb.tableType == "elec" && electricMeterData.Count == 0)
{
@ -885,11 +878,11 @@ namespace FrontendWebApi.ApiControllers
string electricMeterCsv = null;
if (waterMeterData.Count > 0)
{
waterMeterCsv = GenerateCsv(waterMeterData);
waterMeterCsv = GenerateCsv(waterMeterData, "water");
}
if (electricMeterData.Count > 0)
{
electricMeterCsv = GenerateCsv(electricMeterData);
electricMeterCsv = GenerateCsv(electricMeterData, "elec");
}
// 返回CSV文件
@ -921,37 +914,6 @@ namespace FrontendWebApi.ApiControllers
return StatusCode(400, msg);
}
//// 創建ZIP檔案
//using (var zipMemoryStream = new MemoryStream())
//{
// using (var archive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Create, true))
// {
// if (waterMeterData.Count > 0)
// {
// var waterEntry = archive.CreateEntry(waterMeterFileName);
// using (var entryStream = waterEntry.Open())
// using (var streamWriter = new StreamWriter(entryStream, Encoding.UTF8))
// {
// streamWriter.Write(waterMeterCsv);
// }
// }
// if (electricMeterData.Count > 0)
// {
// var electricEntry = archive.CreateEntry(electricMeterFileName);
// using (var entryStream = electricEntry.Open())
// using (var streamWriter = new StreamWriter(entryStream, Encoding.UTF8))
// {
// streamWriter.Write(electricMeterCsv);
// }
// }
// }
// zipMemoryStream.Seek(0, SeekOrigin.Begin);
// return File(zipMemoryStream.ToArray(), "application/zip", zipFileName);
//}
}
catch (Exception exception)
{
@ -963,12 +925,19 @@ namespace FrontendWebApi.ApiControllers
}
private string GenerateCsv(List<OutputBillExcel> data)
private string GenerateCsv(List<OutputBillExcel> data, string type)
{
StringBuilder csv = new StringBuilder();
// 添加CSV標題行
csv.AppendLine("用戶,設備代碼,設備名稱,日期,用電單價(元/度),當日用電(kWh),電費(元),起訖時間");
if (type == "elec")
{
csv.AppendLine("用戶,設備代碼,設備名稱,日期,用電單價(元/度),當日用電(kWh),電費(元),起訖時間");
}
else if (type == "water")
{
csv.AppendLine("用戶,設備代碼,設備名稱,日期,用水單價(元/度),當日用水(m³),水費(元),起訖時間");
}
// 添加數據行
foreach (var item in data)

View File

@ -9,8 +9,8 @@ namespace FrontendWebApi.Models
{
public string WxText { get; set; }
public string Wx { get; set; }
public int Temp { get; set; }
public int RH { get; set; }
public int? Temp { get; set; }
public int? RH { get; set; }
}
public class DefaultBuilding

View File

@ -168,6 +168,7 @@ namespace FrontendWebApi.Models
public string end_time { get; set; }
public string building_tag{ get; set; }
public short operation_type { get; set; }
public int type { get; set; } = 1; // log選項 1:系統紀錄;2:登入紀錄;3:燈控排程紀錄
}
public class OperationLogExportInput {
public bool isNiagara { get; set; }

View File

@ -286,7 +286,7 @@ namespace FrontendWebApi.Models
public class BasePageResult {
public int? pageSize { get; set; } = 10;
public int? totalItem { get; set; } = 0;
public int? totalPage { get; set; } = 0;
public int? currentPage { get; set; } = 0;
}
@ -295,6 +295,6 @@ namespace FrontendWebApi.Models
{
public T data { get; set; }
public bool isEnable { get; set; }
public bool isEnable { get; set; }
}
}

View File

@ -67,7 +67,7 @@ namespace Repository.BackendRepository.Implement
`device_full_name` varchar(100) DEFAULT NULL,
`is_used` smallint(1) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;";
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;";
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sql);
@ -90,11 +90,11 @@ namespace Repository.BackendRepository.Implement
{
tag_name = x.Key.tag_name2,
displayName = x.Key.displayName2
});
});
// StringBuilder sb = new StringBuilder();
bool isDome = false; //是否為巨蛋案
int count = 0;
int count = 0;
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
foreach (var row in ds2)
@ -125,7 +125,7 @@ namespace Repository.BackendRepository.Implement
{
if (arrTag.Length == 5)
{
isDome= true;
isDome = true;
sb.Append($@" insert into import_niagara_tag(niagara_tags, device_area_tag, device_building_tag, device_system_tag,
device_name_tag, device_floor_tag, device_master_tag, device_last_name_tag, device_serial_tag, device_model_tag, device_full_name, atDateTime) values('" +
row.tag_name + "', '" + //niagara_tags
@ -209,7 +209,7 @@ namespace Repository.BackendRepository.Implement
}
}
}
/// <summary>
/// 獲取照明開關 是否在 device_node 層
/// </summary>
@ -220,9 +220,9 @@ namespace Repository.BackendRepository.Implement
stopwatch.Start();
using (IDbConnection conn = GetDbConnection())
{
conn.Open();
conn.Open();
var sql = "select system_value from variable where system_type = 'module_light_switch' ";
var module_light_switch = conn.QueryAsync<string>(sql).Result.FirstOrDefault();
var module_light_switch = conn.QueryAsync<string>(sql).Result.FirstOrDefault();
conn.Close();
stopwatch.Stop();
await KeepTimeLog("getLightSwitchLevel", stopwatch.ElapsedMilliseconds);
@ -250,7 +250,7 @@ namespace Repository.BackendRepository.Implement
{
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
foreach(var b in building)
foreach (var b in building)
{
string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
@ -263,7 +263,7 @@ namespace Repository.BackendRepository.Implement
`parent_path` varchar(50) DEFAULT NULL,
`full_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;";
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;";
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sql);
@ -281,7 +281,8 @@ namespace Repository.BackendRepository.Implement
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
ds = ds.GroupBy(x => new {
ds = ds.GroupBy(x => new
{
device_area_tag = x.device_area_tag,
device_building_tag = x.device_building_tag,
device_system_tag = x.device_system_tag,
@ -304,7 +305,7 @@ namespace Repository.BackendRepository.Implement
foreach (var row in ds)
{
sb.Append($@" insert import_niagara_item(device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_point_name, parent_path, full_name, is_history)
values('"+
values('" +
row.device_area_tag + "', '" +
row.device_building_tag + "', '" +
row.device_system_tag + "', '" +
@ -446,7 +447,7 @@ namespace Repository.BackendRepository.Implement
{
conn.Close();
}
}
}
@ -456,377 +457,404 @@ namespace Repository.BackendRepository.Implement
/// <returns></returns>
public async Task DeviceComparison(string LightSwitchLevel)
{
stopwatch = new Stopwatch();
stopwatch.Start();
Stopwatch stopwatch = Stopwatch.StartNew();
using (IDbConnection conn = GetDbConnection())
{
conn.Open();
try
{
List<NiagaraTags> result;
StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
sb.Append($@"SELECT m.*
FROM import_niagara_tag m
WHERE NOT EXISTS (
SELECT 1
FROM device d
WHERE m.niagara_tags = d.device_number
);");
result = (await conn.QueryAsync<NiagaraTags>(sb.ToString())).ToList<NiagaraTags>();
sb.Clear();
stopwatchSection.Stop();
await KeepTimeLog("filter device item from import_niagara_tag", stopwatchSection.ElapsedMilliseconds);
// 1. 取得需要新增的 NiagaraTags
Stopwatch sw1 = Stopwatch.StartNew();
string sqlGetNiagaraTags = @"
SELECT m.*
FROM import_niagara_tag m
WHERE NOT EXISTS (
SELECT 1
FROM device d
WHERE m.niagara_tags = d.device_number
);";
List<NiagaraTags> niagaraTagsToAdd = (await conn.QueryAsync<NiagaraTags>(sqlGetNiagaraTags)).ToList();
sw1.Stop();
await KeepTimeLog("filter device item from import_niagara_tag", sw1.ElapsedMilliseconds);
#region device, device_kind
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
int count = 0;
//新增至device, is_link = 1
if (result.Count > 0)
// 2. 新增 device 和 device_kind
if (niagaraTagsToAdd.Count > 0)
{
var result2 = result.GroupBy(x => new
// 2.1. 新增 device
Stopwatch sw2 = Stopwatch.StartNew();
List<string> sqlInsertDeviceList = new List<string>();
foreach (var data in niagaraTagsToAdd)
{
device_building_tag2 = x.device_building_tag,
device_system_tag2 = x.device_system_tag,
device_name_tag2 = x.device_name_tag
}).Select(x => new Device_item8
{
device_building_tag = x.Key.device_building_tag2,
device_system_tag = x.Key.device_system_tag2,
device_name_tag = x.Key.device_name_tag2
});
foreach (var data in result)
{
//開關控制在個別燈具(device_node層) and 小類為二線式照明系統 and tag第八段開頭不是 G
if (LightSwitchLevel == "node" && data.device_name_tag == "L1" && data.device_serial_tag.Substring(0, 1) != "G")
{
// 燈具新增 device_node
continue;
}
else {
sb.Append($@" insert device(device_guid, deleted, status, priority, is_link, device_area_tag,
device_building_tag, device_system_tag, device_name_tag, full_name, device_floor_tag, device_master,
device_last_name, device_serial_tag, device_model_tag, device_number, device_system_category_layer3, visible, created_at, updated_at)
select uuid(), 0, 1, 0, 1, '" +
data.device_area_tag + "', '" +
data.device_building_tag + "', '" +
data.device_system_tag + "', '" +
data.device_name_tag + "', '" +
data.device_full_name + "', '" +
data.device_floor_tag + "', '" +
data.device_master_tag + "', '" +
data.device_last_name_tag + "', '" +
data.device_serial_tag + "', '" +
data.device_model_tag + "', '" +
data.niagara_tags + "', '" +
data.device_system_tag + "', 1, now(), now() " +
$@"WHERE NOT EXISTS ( SELECT 1 FROM device WHERE device_number = '{data.niagara_tags}'); ");
count += 1;
if (count >= 100)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
count = 0;
}
}
string sqlInsertDevice = @"
INSERT INTO device (device_guid, deleted, status, priority, is_link, device_area_tag,
device_building_tag, device_system_tag, device_name_tag, full_name, device_floor_tag, device_master,
device_last_name, device_serial_tag, device_model_tag, device_number, device_system_category_layer3, visible, created_at, updated_at)
select uuid(), 0, 1, 0, 1, @device_area_tag, @device_building_tag, @device_system_tag, @device_name_tag,
@full_name, @device_floor_tag, @device_master_tag, @device_last_name_tag, @device_serial_tag,
@device_model_tag, @niagara_tags, @device_system_tag, 1, now(), now() WHERE NOT EXISTS (SELECT 1 FROM device WHERE device_number = @niagara_tags); ";
sqlInsertDeviceList.Add(sqlInsertDevice); // 先暫存SQL語法等等一次執行
}
if (sb.Length > 0)
// 2.1.1 分批執行新增 device
int batchSize = 100;
for (int i = 0; i < sqlInsertDeviceList.Count; i += batchSize)
{
//建立參數
var batch = niagaraTagsToAdd.Skip(i).Take(batchSize).ToList();
//建立參數化查詢要用的物件
List<object> parameters = new List<object>();
foreach (var data in batch)
{
parameters.Add(new
{
device_area_tag = data.device_area_tag,
device_building_tag = data.device_building_tag,
device_system_tag = data.device_system_tag,
device_name_tag = data.device_name_tag,
full_name = data.device_full_name,
device_floor_tag = data.device_floor_tag,
device_master_tag = data.device_master_tag,
device_last_name_tag = data.device_last_name_tag,
device_serial_tag = data.device_serial_tag,
device_model_tag = data.device_model_tag,
niagara_tags = data.niagara_tags
});
}
//建立多條Insert語法可以搭配Dapper的參數化查詢
string insertSql = string.Join(" ", sqlInsertDeviceList.Take(batchSize));
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
}
stopwatchSection.Stop();
await KeepTimeLog("insert into device", stopwatchSection.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
foreach (var data in result2)
{
var sqlString = new StringBuilder();
sqlString.Append("select * from device_kind where device_building_tag = '" + data.device_building_tag + "' and device_system_tag = '" + data.device_system_tag + "' and device_name_tag = '" + data.device_name_tag + "'");
var dk = (await conn.QueryAsync<device_kind>(sqlString.ToString())).ToList<device_kind>();
if (dk.Count == 0)
{
sb2.Append($@"INSERT device_kind (device_kind_guid, device_building_tag, device_system_tag, device_name_tag,
device_normal_flashing, device_close_flashing, device_error_flashing, device_error_independent,
created_by, created_at, is_link)
VALUES (uuid(), '" + data.device_building_tag + "', '" + data.device_system_tag + "', '" + data.device_name_tag +
"', 0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 1);");
count += 1;
if (count >= 100)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb2.ToString());
}
sb2.Clear();
count = 0;
}
await conn.ExecuteAsync(insertSql, parameters); // 使用參數化查詢
scope.Complete();
}
}
if (sb2.Length > 0)
sw2.Stop();
await KeepTimeLog("insert into device", sw2.ElapsedMilliseconds);
// 2.2. 新增 device_kind
Stopwatch sw3 = Stopwatch.StartNew();
// 建立 device_kind 時需要用到的資料結構
var deviceKindData = niagaraTagsToAdd.GroupBy(x => new
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb2.ToString());
}
sb2.Clear();
}
stopwatchSection.Stop();
await KeepTimeLog("insert into device_kind", stopwatchSection.ElapsedMilliseconds);
}
#endregion
#region device_kind process for cctv
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(@"SET SQL_SAFE_UPDATES = 0;
update device d join import_niagara_tag n on d.device_number = n.niagara_tags set d.device_model_tag = n.device_model_tag
where d.device_system_tag = 'S' and d.device_name_tag = 'C' and (d.device_model_tag is null or d.device_model_tag = '');");
}
stopwatchSection.Stop();
await KeepTimeLog("update cctv model is null or empty", stopwatchSection.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
var resultDeviceItem = await conn.QueryAsync<NiagaraTags>($@"select * from import_niagara_tag where device_system_tag = 'S' and device_name_tag = 'C';");
var result3 = resultDeviceItem.GroupBy(x => new
{
device_building_tag2 = x.device_building_tag,
device_system_tag2 = x.device_system_tag,
device_name_tag2 = x.device_name_tag,
device_model_tag2 = x.device_model_tag
}).Select(x => new Device_item8
{
device_building_tag = x.Key.device_building_tag2,
device_system_tag = x.Key.device_system_tag2,
device_name_tag = x.Key.device_name_tag2,
device_model_tag = x.Key.device_model_tag2
});
foreach (var data in result3)
{
var sqlString = new StringBuilder();
sqlString.Append("select * from device_kind where device_building_tag = '" + data.device_building_tag + "' and device_system_tag = '" + data.device_system_tag + "' and device_name_tag = '" + data.device_name_tag + "' and device_model_tag = '" + data.device_model_tag + "'");
var dk = (await conn.QueryAsync<device_kind>(sqlString.ToString())).ToList<device_kind>();
if (dk.Count == 0)
x.device_building_tag,
x.device_system_tag,
x.device_name_tag
}).Select(g => new
{
sb2.Append($@"INSERT device_kind (device_kind_guid, device_building_tag, device_system_tag, device_name_tag,
device_normal_flashing, device_close_flashing, device_error_flashing, device_error_independent,
created_by, created_at, device_model_tag, is_link)
VALUES (uuid(), '" + data.device_building_tag + "', '" + data.device_system_tag + "', '" + data.device_name_tag +
"', 0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), '" + data.device_model_tag + "', 1);");
count += 1;
if (count >= 100)
g.Key.device_building_tag,
g.Key.device_system_tag,
g.Key.device_name_tag
}).ToList();
foreach (var data in deviceKindData)
{
// 檢查 device_kind 是否已存在 (改成使用 EXISTS 子查詢)
string sqlCheckDeviceKind = @"
SELECT EXISTS (
SELECT 1
FROM device_kind
WHERE device_building_tag = @device_building_tag
AND device_system_tag = @device_system_tag
AND device_name_tag = @device_name_tag
);";
var parameters = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag };
bool deviceKindExists = await conn.ExecuteScalarAsync<bool>(sqlCheckDeviceKind, parameters); // 使用參數化查詢
if (!deviceKindExists)
{
// 新增 device_kind
string sqlInsertDeviceKind = @"
INSERT INTO device_kind (device_kind_guid, device_building_tag, device_system_tag, device_name_tag,
device_normal_flashing, device_close_flashing, device_error_flashing, device_error_independent,
created_by, created_at, is_link)
VALUES (uuid(), @device_building_tag, @device_system_tag, @device_name_tag,
0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 1);";
var parameters2 = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag };
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb2.ToString());
await conn.ExecuteAsync(sqlInsertDeviceKind, parameters2); // 使用參數化查詢
scope.Complete();
}
sb2.Clear();
count = 0;
}
}
sw3.Stop();
await KeepTimeLog("insert into device_kind", sw3.ElapsedMilliseconds);
}
// 3. device_kind process for cctv
Stopwatch sw4 = Stopwatch.StartNew();
// 3.1 更新 device 的 model tag
string sqlUpdateCCTVModel = @"
UPDATE device d
JOIN import_niagara_tag n ON d.device_number = n.niagara_tags
SET d.device_model_tag = n.device_model_tag
WHERE d.device_system_tag = 'S'
AND d.device_name_tag = 'C'
AND (d.device_model_tag IS NULL OR d.device_model_tag = '');";
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sqlUpdateCCTVModel); // 使用參數化查詢
scope.Complete();
}
sw4.Stop();
await KeepTimeLog("update cctv model is null or empty", sw4.ElapsedMilliseconds);
// 3.2 取得 CCTV 相關資料,並新增 device_kind (邏輯同 2.2,但需要額外考量 device_model_tag)
Stopwatch sw5 = Stopwatch.StartNew();
string sqlGetCCTVData = @"SELECT * FROM import_niagara_tag WHERE device_system_tag = 'S' AND device_name_tag = 'C';";
var cctvData = await conn.QueryAsync<NiagaraTags>(sqlGetCCTVData);
// 建立 device_kind 時需要用到的資料結構
var cctvKindData = cctvData.GroupBy(x => new
{
x.device_building_tag,
x.device_system_tag,
x.device_name_tag,
x.device_model_tag
}).Select(g => new
{
g.Key.device_building_tag,
g.Key.device_system_tag,
g.Key.device_name_tag,
g.Key.device_model_tag
}).ToList();
foreach (var data in cctvKindData)
{
// 檢查 device_kind 是否已存在 (改成使用 EXISTS 子查詢)
string sqlCheckDeviceKind = @"
SELECT EXISTS (
SELECT 1
FROM device_kind
WHERE device_building_tag = @device_building_tag
AND device_system_tag = @device_system_tag
AND device_name_tag = @device_name_tag
AND device_model_tag = @device_model_tag
);";
var parameters = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag, device_model_tag = data.device_model_tag };
bool deviceKindExists = await conn.ExecuteScalarAsync<bool>(sqlCheckDeviceKind, parameters);
if (!deviceKindExists)
{
// 新增 device_kind
string sqlInsertDeviceKind = @"
INSERT INTO device_kind (device_kind_guid, device_building_tag, device_system_tag, device_name_tag,
device_normal_flashing, device_close_flashing, device_error_flashing, device_error_independent,
created_by, created_at, device_model_tag, is_link)
VALUES (uuid(), @device_building_tag, @device_system_tag, @device_name_tag,
0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), @device_model_tag, 1);";
var parameters2 = new { device_building_tag = data.device_building_tag, device_system_tag = data.device_system_tag, device_name_tag = data.device_name_tag, device_model_tag = data.device_model_tag };
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sqlInsertDeviceKind, parameters2); // 使用參數化查詢
scope.Complete();
}
}
}
if (sb2.Length > 0)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb2.ToString());
}
sw5.Stop();
await KeepTimeLog("insert cctv device_kind", sw5.ElapsedMilliseconds);
sb2.Clear();
}
// 3.3 更新 device_kind 的 is_link (邏輯複雜需要仔細確認SQL語法)
Stopwatch sw6 = Stopwatch.StartNew();
// 先更新 device_kind 的 is_link 為 0
string sqlUpdateDeviceKindIsLinkToZero = @"
UPDATE device_kind
SET is_link = 0
WHERE device_system_tag = 'S'
AND device_name_tag = 'C'
AND NOT EXISTS (
SELECT 1
FROM import_niagara_tag
WHERE device_system_tag = device_kind.device_system_tag
AND device_name_tag = device_kind.device_name_tag
AND device_model_tag = device_kind.device_model_tag
);";
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync($@"SET SQL_SAFE_UPDATES = 0;
UPDATE device_kind dk
left JOIN (
SELECT device_system_tag, device_name_tag, device_model_tag
FROM import_niagara_tag
LIMIT 100000
) i ON dk.device_system_tag = i.device_system_tag
and dk.device_name_tag = i.device_name_tag
and dk.device_model_tag = i.device_model_tag
SET dk.is_link = 0
WHERE dk.is_link = 1 and dk.device_system_tag = 'S' and dk.device_name_tag = 'C' and i.device_system_tag is null;");
await conn.ExecuteAsync(sqlUpdateDeviceKindIsLinkToZero); // 使用參數化查詢
scope.Complete();
}
// 再更新 device_kind 的 is_link 為 1
string sqlUpdateDeviceKindIsLinkToOne = @"
UPDATE device_kind
SET is_link = 1
WHERE device_system_tag = 'S'
AND device_name_tag = 'C'
AND EXISTS (
SELECT 1
FROM import_niagara_tag
WHERE device_system_tag = device_kind.device_system_tag
AND device_name_tag = device_kind.device_name_tag
AND device_model_tag = device_kind.device_model_tag
);";
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync($@"SET SQL_SAFE_UPDATES = 0;
UPDATE device_kind dk
left JOIN (
SELECT device_system_tag, device_name_tag, device_model_tag
FROM import_niagara_tag
LIMIT 100000
) i ON dk.device_system_tag = i.device_system_tag
and dk.device_name_tag = i.device_name_tag
and dk.device_model_tag = i.device_model_tag
SET dk.is_link = 1
WHERE dk.is_link = 0 and dk.device_system_tag = 'S' and dk.device_name_tag = 'C' and i.device_system_tag is not null;");
await conn.ExecuteAsync(sqlUpdateDeviceKindIsLinkToOne); // 使用參數化查詢
scope.Complete();
}
stopwatchSection.Stop();
await KeepTimeLog("insert/update cctv model is_link", stopwatchSection.ElapsedMilliseconds);
#endregion
#region device_node
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
sb.Append($@" SELECT m.*
FROM import_niagara_tag m
WHERE NOT EXISTS (
SELECT 1
FROM device_node d
WHERE m.niagara_tags COLLATE utf8mb4_0900_ai_ci = d.device_number COLLATE utf8mb4_0900_ai_ci
);");
result = (await conn.QueryAsync<NiagaraTags>(sb.ToString())).ToList<NiagaraTags>();
sb.Clear();
sw6.Stop();
await KeepTimeLog("insert/update cctv model is_link", sw6.ElapsedMilliseconds);
if (result.Count > 0)
// 4. device_node 新增 (邏輯同 2.1,需要調整 SQL 語法和參數)
Stopwatch sw7 = Stopwatch.StartNew();
string sqlGetNiagaraTagsForNode = @"
SELECT m.*
FROM import_niagara_tag m
WHERE NOT EXISTS (
SELECT 1
FROM device_node d
WHERE m.niagara_tags = d.device_number
);";
List<NiagaraTags> niagaraTagsToAddForNode = (await conn.QueryAsync<NiagaraTags>(sqlGetNiagaraTagsForNode)).ToList();
if (niagaraTagsToAddForNode.Count > 0)
{
var result2 = result.GroupBy(x => new
// 4.1. 新增 device_node
List<string> sqlInsertDeviceNodeList = new List<string>();
foreach (var data in niagaraTagsToAddForNode)
{
device_building_tag2 = x.device_building_tag,
device_system_tag2 = x.device_system_tag,
device_name_tag2 = x.device_name_tag
}).Select(x => new Device_item8
{
device_building_tag = x.Key.device_building_tag2,
device_system_tag = x.Key.device_system_tag2,
device_name_tag = x.Key.device_name_tag2
});
count = 0;
foreach (var data in result)
{
//開關控制在個別燈具(device_node層) and 小類為二線式照明系統 and tag第八段開頭不是 G
if (LightSwitchLevel == "node" && data.device_name_tag == "L1" && data.device_serial_tag.Substring(0, 1) != "G")
{
// 燈具新增 device_node
sb.Append($@"INSERT INTO device_node(device_node_guid, deleted, device_guid, device_number, full_name, created_by, created_at, updated_at)
VALUES (uuid(), 0, '' " + //device_guid 父層需要 forge 那邊提供
",'" + data.niagara_tags + // device_number
"', '" + data.device_full_name + //full_name
"','B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), now());");
count += 1;
if (count >= 100)
{
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
count = 0;
}
string sqlInsertDeviceNode = @"
INSERT INTO device_node (device_node_guid, deleted, device_guid, device_number, full_name, created_by, created_at, updated_at)
VALUES (uuid(), 0, '', @device_number, @full_name, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), now());";
sqlInsertDeviceNodeList.Add(sqlInsertDeviceNode);
}
}
if (sb.Length > 0)
//4.1.1 分批執行新增device node
int batchSizeNode = 100;
for (int i = 0; i < sqlInsertDeviceNodeList.Count; i += batchSizeNode)
{
//建立參數
var batch = niagaraTagsToAddForNode.Skip(i).Take(batchSizeNode).ToList();
//建立參數化查詢要用的物件
List<object> parameters = new List<object>();
foreach (var data in batch)
{
parameters.Add(new
{
device_number = data.niagara_tags,
full_name = data.device_full_name,
});
}
//建立多條Insert語法可以搭配Dapper的參數化查詢
string insertSql = string.Join(" ", sqlInsertDeviceNodeList.Take(batchSizeNode));
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
await conn.ExecuteAsync(insertSql, parameters); // 使用參數化查詢
scope.Complete();
}
sb.Clear();
}
stopwatchSection.Stop();
await KeepTimeLog("insert into device_node", stopwatchSection.ElapsedMilliseconds);
}
#endregion
sw7.Stop();
await KeepTimeLog("insert into device_node", sw7.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
//device有niagara有is_link 更新成 1
sb.Append($@" SET SQL_SAFE_UPDATES = 0;
UPDATE device d
JOIN (
SELECT niagara_tags
FROM import_niagara_tag
LIMIT 100000
) i ON d.device_number = i.niagara_tags
SET d.is_link = 1, d.deleted = 0");
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
stopwatchSection.Stop();
await KeepTimeLog("update device is_link = 1, deleted = 0", stopwatchSection.ElapsedMilliseconds);
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
//device有niagara沒有is_link 更新成 0
sb.Append($@" SET SQL_SAFE_UPDATES = 0;
UPDATE device d
left JOIN (
SELECT niagara_tags
FROM import_niagara_tag
LIMIT 100000
) i ON d.device_number = i.niagara_tags
SET d.is_link = 0
WHERE d.is_link = 1 and i.niagara_tags is null;");
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
}
sb.Clear();
stopwatchSection.Stop();
await KeepTimeLog("update device is_link = 0", stopwatchSection.ElapsedMilliseconds);
// 5. 更新 device 的 is_link
Stopwatch sw8 = Stopwatch.StartNew();
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
// device_node 有, niagara沒有, is_link 更新成 0
sb.Append($@" SET SQL_SAFE_UPDATES = 0;
UPDATE device_node dn
left JOIN (
SELECT niagara_tags
FROM import_niagara_tag
LIMIT 100000
) i ON dn.device_number COLLATE utf8mb4_0900_ai_ci = i.niagara_tags COLLATE utf8mb4_0900_ai_ci
SET dn.is_link = 0
WHERE dn.is_link = 1 and i.niagara_tags is null;");
// 先更新 device 的 is_link 為 1 (邏輯簡單,直接使用 UPDATE JOIN)
string sqlUpdateDeviceIsLinkToOne = @"
UPDATE device d
JOIN import_niagara_tag i ON d.device_number = i.niagara_tags
SET d.is_link = 1, d.deleted = 0;";
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sb.ToString());
await conn.ExecuteAsync(sqlUpdateDeviceIsLinkToOne); // 使用參數化查詢
scope.Complete();
}
stopwatchSection.Stop();
await KeepTimeLog("update device_node is_link = 0", stopwatchSection.ElapsedMilliseconds);
sw8.Stop();
await KeepTimeLog("update device is_link = 1, deleted = 0", sw8.ElapsedMilliseconds);
// 再更新 device 的 is_link 為 0 (邏輯需要調整,使用 NOT EXISTS 子查詢)
Stopwatch sw9 = Stopwatch.StartNew();
string sqlUpdateDeviceIsLinkToZero = @"
UPDATE device
SET is_link = 0
WHERE is_link = 1
AND NOT EXISTS (
SELECT 1
FROM import_niagara_tag
WHERE device.device_number = import_niagara_tag.niagara_tags
);";
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sqlUpdateDeviceIsLinkToZero); // 使用參數化查詢
scope.Complete();
}
sw9.Stop();
await KeepTimeLog("update device is_link = 0", sw9.ElapsedMilliseconds);
// 6. 更新 device_node 的 is_link (邏輯同 5需要調整 SQL 語法和參數)
Stopwatch sw10 = Stopwatch.StartNew();
string sqlUpdateDeviceNodeIsLinkToZero = @"
UPDATE device_node
SET is_link = 0
WHERE is_link = 1
AND NOT EXISTS (
SELECT 1
FROM import_niagara_tag
WHERE device_node.device_number = import_niagara_tag.niagara_tags
);";
using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sqlUpdateDeviceNodeIsLinkToZero); // 使用參數化查詢
scope.Complete();
}
sw10.Stop();
await KeepTimeLog("update device_node is_link = 0", sw10.ElapsedMilliseconds);
//Main總時間
stopwatch.Stop();
await KeepTimeLog("DeviceComparison", stopwatch.ElapsedMilliseconds);
}
catch (Exception exception)
{
//throw exception;
throw;
throw; // 保留原始堆疊追蹤
}
finally
{
conn.Close();
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
}
}
@ -952,8 +980,7 @@ namespace Repository.BackendRepository.Implement
AND d.device_name_tag = subquery.device_name_tag
AND d.points = subquery.device_point_name
AND d.device_building_tag = subquery.device_building_tag
SET d.is_show_history = CASE WHEN subquery.device_point_name IS NULL THEN 0 ELSE 1 END
where date(d.created_at) = subquery.created_at;");
SET d.is_show_history = CASE WHEN subquery.device_point_name IS NULL THEN 0 ELSE 1 END");
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
@ -1337,7 +1364,7 @@ namespace Repository.BackendRepository.Implement
throw exception;
}
finally
{
{
conn.Close();
}
}
@ -1358,7 +1385,8 @@ namespace Repository.BackendRepository.Implement
try
{
StringBuilder sb = new StringBuilder();
sb.Append("update device set full_name=device_number where full_Name='';");
sb.Append(@"SET SQL_SAFE_UPDATES = 0;
update device set full_name=device_number where full_Name='';");
await conn.ExecuteAsync(sb.ToString());
}
catch (Exception exception)
@ -1426,13 +1454,13 @@ namespace Repository.BackendRepository.Implement
{
StringBuilder sb = new StringBuilder();
sb.Append(@"SET SQL_SAFE_UPDATES = 0;
UPDATE device d
JOIN (
SELECT niagara_tags, device_full_name
FROM import_niagara_tag
) m ON m.niagara_tags = d.device_number
SET d.full_name = m.device_full_name
WHERE d.full_name != m.device_full_name;");
UPDATE device AS d
JOIN import_niagara_tag AS i ON d.device_number = i.niagara_tags
SET d.full_name = i.device_full_name
WHERE d.full_name <> i.device_full_name;
SET SQL_SAFE_UPDATES = 1;");
await conn.ExecuteAsync(sb.ToString());
}
catch (Exception exception)
@ -1589,7 +1617,7 @@ namespace Repository.BackendRepository.Implement
conn.Close();
}
}
stopwatchSection = new Stopwatch();
stopwatchSection.Start();
// 過濾 dv 集合,只保留設備編號有效的項目
@ -1800,24 +1828,24 @@ SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `import_niagara_item_history`;
CREATE TABLE `import_niagara_item_history` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT ' TagName ',
`device_area_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_building_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_system_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_name_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_floor_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_master_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_last_name_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_serial_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_point_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`parent_path` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`device_number` varchar(50) NULL DEFAULT NULL COMMENT ' TagName ',
`device_area_tag` varchar(50) NULL DEFAULT NULL,
`device_building_tag` varchar(50) NULL DEFAULT NULL,
`device_system_tag` varchar(50) NULL DEFAULT NULL,
`device_name_tag` varchar(50) NULL DEFAULT NULL,
`device_floor_tag` varchar(50) NULL DEFAULT NULL,
`device_master_tag` varchar(50) NULL DEFAULT NULL,
`device_last_name_tag` varchar(50) NULL DEFAULT NULL,
`device_serial_tag` varchar(50) NULL DEFAULT NULL,
`device_point_name` varchar(50) NULL DEFAULT NULL,
`parent_path` varchar(50) NULL DEFAULT NULL,
`is_history` bit(1) NULL DEFAULT b'0',
`full_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`check_status` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`full_name` varchar(50) NULL DEFAULT NULL,
`check_status` varchar(50) NULL DEFAULT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_device_number` (`device_number`)
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;";
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
@ -1957,7 +1985,7 @@ SET FOREIGN_KEY_CHECKS = 1;";
/// </summary>
/// <param name="dcp"></param>
/// <returns></returns>
public async Task DeviceControlPoint (List<DeviceControlPoint> dcp)
public async Task DeviceControlPoint(List<DeviceControlPoint> dcp)
{
stopwatch = new Stopwatch();
stopwatch.Start();
@ -1979,7 +2007,7 @@ SET FOREIGN_KEY_CHECKS = 1;";
`device_number` varchar(50) DEFAULT NULL,
`device_point_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;";
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;";
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
await conn.ExecuteAsync(sql);