調整同步流程
This commit is contained in:
commit
130ecba50f
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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"))
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -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】");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user