Merge branch 'master' of https://gitea.mjm-staging.developers-homelab.net/BIMS/BIMS
This commit is contained in:
commit
73ca14abe9
@ -61,10 +61,10 @@ namespace Backend.ApiControllers
|
|||||||
{
|
{
|
||||||
{ "@user_guid", myUser.userinfo_guid },
|
{ "@user_guid", myUser.userinfo_guid },
|
||||||
{ "@operation_type", 1 }, //1:名稱修改
|
{ "@operation_type", 1 }, //1:名稱修改
|
||||||
{ "@building_guid", GetOne.Building_guid },
|
{ "@building_tag", GetOne.device_building_tag },
|
||||||
{ "@main_system_guid", GetOne.Main_system_guid },
|
{ "@main_system_tag", GetOne.device_system_tag },
|
||||||
{ "@sub_system_guid", GetOne.Sub_system_guid },
|
{ "@sub_system_tag", GetOne.device_name_tag },
|
||||||
{ "@floor_guid", GetOne.Floor_guid },
|
{ "@floor_tag", GetOne.device_floor_tag },
|
||||||
{ "@device_guid", GetOne.Device_guid },
|
{ "@device_guid", GetOne.Device_guid },
|
||||||
{ "@action_name", "修改名稱" },
|
{ "@action_name", "修改名稱" },
|
||||||
{ "@parameter", JsonConvert.SerializeObject(change) },
|
{ "@parameter", JsonConvert.SerializeObject(change) },
|
||||||
|
@ -23,8 +23,10 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.21" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.21" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.20" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.20" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.5" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.5" />
|
||||||
|
<PackageReference Include="ncrontab" Version="3.3.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="NPOI" Version="2.5.5" />
|
<PackageReference Include="NPOI" Version="2.5.5" />
|
||||||
|
<PackageReference Include="Quartz" Version="3.3.3" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="2.0.0" />
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="2.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1662,7 +1662,7 @@ namespace Backend.Controllers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string sWhere = "deleted = 0 AND device_name_tag = @Sub_system_tag and device_building_tag = @device_building_tag";
|
string sWhere = "deleted = 0 AND device_name_tag = @Sub_system_tag and device_building_tag = @device_building_tag and is_link = 1 and is_controll = 1";
|
||||||
|
|
||||||
object param = new { Sub_system_tag = input.sub_system_tag, device_building_tag = input.building_tag };
|
object param = new { Sub_system_tag = input.sub_system_tag, device_building_tag = input.building_tag };
|
||||||
|
|
||||||
|
@ -501,26 +501,37 @@ namespace Backend.Controllers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var main_tag = await backendRepository.GetOneAsync<string>($@"SELECT system_value FROM variable WHERE id = @id", new { id = device_Item.device_system_tag });
|
||||||
|
var sub_tag = await backendRepository.GetOneAsync<string>($@"SELECT system_value FROM variable WHERE id = @id", new { id = device_Item.device_name_tag });
|
||||||
//檢查是否有未刪除的區域選單
|
//檢查是否有未刪除的區域選單
|
||||||
if(device_Item.is_show_riserDiagram == 1)
|
if (device_Item.is_show_riserDiagram == 1)
|
||||||
{
|
{
|
||||||
var sql_show_riserDiagram = $@"SELECT * FROM device_item di
|
var sql_show_riserDiagram = $@"SELECT di.id FROM device_item di
|
||||||
WHERE di.id = @id AND di.deleted = 0 AND is_show_riserDiagram = 1";
|
WHERE di.id != @id AND di.deleted = 0 AND is_show_riserDiagram = 1 and device_system_tag = @device_system_tag
|
||||||
|
and device_name_tag = @device_name_tag";
|
||||||
|
|
||||||
var is_show_riserDiagram = await backendRepository.GetAllAsync<string>(sql_show_riserDiagram, new { id = device_Item.id });
|
var deviceItemId = await backendRepository.GetAllAsync<int>(sql_show_riserDiagram,
|
||||||
|
new { id = device_Item.id, device_system_tag = main_tag, device_name_tag = sub_tag });
|
||||||
|
|
||||||
if (is_show_riserDiagram.Count() > 0)
|
if (deviceItemId.Count() > 0)
|
||||||
{
|
{
|
||||||
apiResult.Code = "9998";
|
foreach (var id in deviceItemId)
|
||||||
apiResult.Msg = "請先取消已選擇顯示於昇位圖點位。";
|
{
|
||||||
return apiResult;
|
Dictionary<string, object> Device_itemDic = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@is_show_riserDiagram", false},
|
||||||
|
{ "@updated_by", myUserInfo.Userinfo_guid},
|
||||||
|
{ "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
|
};
|
||||||
|
|
||||||
|
await backendRepository.UpdateOneByCustomTable(Device_itemDic, "device_item", "id='" + id + "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_Item.id == 0)
|
if (device_Item.id == 0)
|
||||||
{
|
{
|
||||||
var main_tag = await backendRepository.GetOneAsync<string>($@"SELECT system_value FROM variable WHERE id = @id", new { id = device_Item.device_system_tag });
|
|
||||||
var sub_tag = await backendRepository.GetOneAsync<string>($@"SELECT system_value FROM variable WHERE id = @id", new { id = device_Item.device_name_tag });
|
|
||||||
//新增
|
//新增
|
||||||
Dictionary<string, object> Device_itemDic = new Dictionary<string, object>()
|
Dictionary<string, object> Device_itemDic = new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
@ -586,7 +597,7 @@ namespace Backend.Controllers
|
|||||||
FROM device_item di
|
FROM device_item di
|
||||||
JOIN variable sv ON di.device_name_tag = sv.system_value
|
JOIN variable sv ON di.device_name_tag = sv.system_value
|
||||||
JOIN variable mv ON sv.system_parent_id = mv.id AND di.device_system_tag = mv.system_value
|
JOIN variable mv ON sv.system_parent_id = mv.id AND di.device_system_tag = mv.system_value
|
||||||
WHERE sv.id = @id AND di.deleted = @Deleted and di.device_building_tag = @building_tag";
|
WHERE sv.id = @id AND di.deleted = @Deleted and di.device_building_tag = @building_tag and di.is_link = 1";
|
||||||
|
|
||||||
object param = new { Deleted = 0, id = id, building_tag = building_tag.Split("/")[1] };
|
object param = new { Deleted = 0, id = id, building_tag = building_tag.Split("/")[1] };
|
||||||
|
|
||||||
|
@ -54,13 +54,13 @@ namespace Backend.Models
|
|||||||
public string Device_guid { get; set; }
|
public string Device_guid { get; set; }
|
||||||
public byte Deleted { get; set; }
|
public byte Deleted { get; set; }
|
||||||
public byte Status { get; set; }
|
public byte Status { get; set; }
|
||||||
public string Building_guid { get; set; }
|
public string device_building_tag { get; set; }
|
||||||
public string Building_full_name { get; set; }
|
public string Building_full_name { get; set; }
|
||||||
public string Main_system_guid { get; set; }
|
public string Main_system_guid { get; set; }
|
||||||
public string Main_system_full_name { get; set; }
|
public string Main_system_full_name { get; set; }
|
||||||
public string Sub_system_guid { get; set; }
|
public string Sub_system_guid { get; set; }
|
||||||
public string Sub_system_full_name { get; set; }
|
public string Sub_system_full_name { get; set; }
|
||||||
public string Floor_guid { get; set; }
|
public string device_floor_tag { get; set; }
|
||||||
public string Floor_full_name { get; set; }
|
public string Floor_full_name { get; set; }
|
||||||
public string Device_coordinate { get; set; }
|
public string Device_coordinate { get; set; }
|
||||||
public string Device_full_name { get; set; }
|
public string Device_full_name { get; set; }
|
||||||
@ -76,7 +76,8 @@ namespace Backend.Models
|
|||||||
public string Device_flashing { get; set; }
|
public string Device_flashing { get; set; }
|
||||||
public string Device_ip { get; set; }
|
public string Device_ip { get; set; }
|
||||||
public string Device_port { get; set; }
|
public string Device_port { get; set; }
|
||||||
public string Device_name_tag { get; set; }
|
public string device_name_tag { get; set; }
|
||||||
|
public string device_system_tag { get; set; }
|
||||||
public List<DeviceDisaster> Device_disasters { get; set; } //防災類型
|
public List<DeviceDisaster> Device_disasters { get; set; } //防災類型
|
||||||
public List<DeviceNode> Device_nodes { get; set; } //設備子節點
|
public List<DeviceNode> Device_nodes { get; set; } //設備子節點
|
||||||
}
|
}
|
||||||
|
198
Backend/Quartz/JobSchedule.cs
Normal file
198
Backend/Quartz/JobSchedule.cs
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Repository.BackendRepository.Implement;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NCrontab;
|
||||||
|
using static NCrontab.CrontabSchedule;
|
||||||
|
|
||||||
|
namespace Backend.Quartz
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Job調度中間對象
|
||||||
|
/// </summary>
|
||||||
|
public class JobSchedule
|
||||||
|
{
|
||||||
|
public JobSchedule(Type jobType, string cronExpression)
|
||||||
|
{
|
||||||
|
this.JobType = jobType ?? throw new ArgumentNullException(nameof(jobType));
|
||||||
|
CronExpression = cronExpression ?? throw new ArgumentNullException(nameof(cronExpression));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Job類型
|
||||||
|
/// </summary>
|
||||||
|
public Type JobType { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Cron表達式
|
||||||
|
/// </summary>
|
||||||
|
public string CronExpression { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Job狀態
|
||||||
|
/// </summary>
|
||||||
|
public JobStatus JobStatu { get; set; } = JobStatus.Init;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Job運行狀態
|
||||||
|
/// </summary>
|
||||||
|
public enum JobStatus : byte
|
||||||
|
{
|
||||||
|
[Description("初始化")]
|
||||||
|
Init = 0,
|
||||||
|
[Description("運行中")]
|
||||||
|
Running = 1,
|
||||||
|
[Description("調度中")]
|
||||||
|
Scheduling = 2,
|
||||||
|
[Description("已停止")]
|
||||||
|
Stopped = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Task_Detail
|
||||||
|
{
|
||||||
|
private readonly IBackendRepository backendRepository;
|
||||||
|
private readonly ILogger<Task_Detail> logger;
|
||||||
|
public Task_Detail(ILogger<Task_Detail> logger, IBackendRepository backendRepository)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.backendRepository = backendRepository;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 取得時間規則
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task"></param>
|
||||||
|
/// <param name="task_item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<string> GetWorkRule(string task,string task_item)
|
||||||
|
{
|
||||||
|
string Times = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sql = $@"select b.system_value from task_detail a
|
||||||
|
join variable b on a.variable_id = b.id
|
||||||
|
where a.task = '{task}' and a.task_item = '{task_item}'";
|
||||||
|
Times = await backendRepository.GetOneAsync<string>(sql);
|
||||||
|
}
|
||||||
|
catch(Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【Task_Detail】【任務時間獲取失敗】");
|
||||||
|
logger.LogError("【Task_Detail】【任務時間獲取失敗】[Exception]:{0},Task:{1},task_item:{2}", exception.ToString(),task,task_item);
|
||||||
|
}
|
||||||
|
return Times;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 是否執行任務
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task"></param>
|
||||||
|
/// <param name="task_item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<bool> GetNeedWorkTask(string task, string task_item)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sql = $@"select a.lastwork_time from task_detail a
|
||||||
|
where a.task = '{task}' and a.task_item = '{task_item}'";
|
||||||
|
|
||||||
|
var lastworkTime = await backendRepository.GetOneAsync<string>(sql);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DateTime dateTime = lastworkTime != null ? Convert.ToDateTime(lastworkTime) : Convert.ToDateTime("1970-01-01 00:00:01");
|
||||||
|
|
||||||
|
var nextTime = CrontabSchedule.Parse(await GetWorkRule(task, task_item), new ParseOptions { IncludingSeconds = true } ).GetNextOccurrence(dateTime);
|
||||||
|
if (DateTime.Now >= nextTime)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【Task_Detail】【時間解析失敗】[Exception]:{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 紀錄任務開始執行時間
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task"></param>
|
||||||
|
/// <param name="task_item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task InsertWorkTime(string task, string task_item ,string LoggerWord = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> worktime = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@lastwork_time", DateTime.Now},
|
||||||
|
{ "@success", 2},
|
||||||
|
{ "@updated_at", DateTime.Now},
|
||||||
|
};
|
||||||
|
await backendRepository.UpdateOneByCustomTable(worktime, "task_detail", $" task = '{task}' and task_item = '{task_item}'");
|
||||||
|
|
||||||
|
if(LoggerWord == null)
|
||||||
|
{
|
||||||
|
logger.LogInformation($"【Task_Detail】【開始{task},{task_item}任務】");
|
||||||
|
}
|
||||||
|
logger.LogInformation($"【Task_Detail】【{LoggerWord}】");
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【Task_Detail】【任務輸入開始時間】[Exception]:{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 紀錄任務結束時間
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task"></param>
|
||||||
|
/// <param name="task_item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task InsertWorkTime_End(string task, string task_item,string LoggerWord = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> worktime = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@success", 0},
|
||||||
|
{ "@lastwork_end_time", DateTime.Now},
|
||||||
|
{ "@updated_at", DateTime.Now},
|
||||||
|
};
|
||||||
|
await backendRepository.UpdateOneByCustomTable(worktime, "task_detail", $" task = '{task}' and task_item = '{task_item}'");
|
||||||
|
if (LoggerWord == null)
|
||||||
|
{
|
||||||
|
logger.LogInformation($"【Task_Detail】【結束{task},{task_item}任務】");
|
||||||
|
}
|
||||||
|
logger.LogInformation($"【Task_Detail】【{LoggerWord}】");
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【Task_Detail】【任務輸入結束時間】[Exception]:{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 執行失敗紀錄
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task"></param>
|
||||||
|
/// <param name="task_item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task WorkFail(string task, string task_item,string reason = "")
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> worktime = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@success", 1},
|
||||||
|
{ "@updated_at", DateTime.Now},
|
||||||
|
};
|
||||||
|
await backendRepository.UpdateOneByCustomTable(worktime, "task_detail", $" task = '{task}' and task_item = '{task_item}'");
|
||||||
|
logger.LogError("【Task_Detail】【任務執行失敗】[Exception]:{0},Task:{1},task_item:{2}", reason, task, task_item);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【Task_Detail】【任務執行失敗】[Exception]:{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1461
Backend/Quartz/Jobs/ArchiveElectricMeterDayJob.cs
Normal file
1461
Backend/Quartz/Jobs/ArchiveElectricMeterDayJob.cs
Normal file
File diff suppressed because it is too large
Load Diff
335
Backend/Quartz/Jobs/ArchiveElectricMeterHourJob.cs
Normal file
335
Backend/Quartz/Jobs/ArchiveElectricMeterHourJob.cs
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Quartz;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Backend.Quartz.Jobs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 電錶歸檔,每小時執行,只執行小時歸檔
|
||||||
|
/// </summary>
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
class ArchiveElectricMeterHourJob : IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<ArchiveElectricMeterHourJob> logger;
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
private readonly ILogger<Task_Detail> loggers;
|
||||||
|
|
||||||
|
public ArchiveElectricMeterHourJob(
|
||||||
|
ILogger<ArchiveElectricMeterHourJob> logger,
|
||||||
|
IBackgroundServiceRepository backgroundServiceRepository, ILogger<Task_Detail> loggers)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
||||||
|
this.loggers = loggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
Task_Detail task_Detail = new Task_Detail(loggers, backgroundServiceRepository);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(await task_Detail.GetNeedWorkTask("ArchiveElectricMeterHourJob", "All"))
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("ArchiveElectricMeterHourJob", "All", "任務開始");
|
||||||
|
EDFunction ed = new EDFunction();
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
|
||||||
|
var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'";
|
||||||
|
|
||||||
|
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
|
||||||
|
var electricMeterGuid = variableArchive.Where(x => x.Name == "ElectricMeterGuid").Select(x => x.Value).FirstOrDefault();
|
||||||
|
|
||||||
|
#region 找出所有電錶設備
|
||||||
|
var sWhere = "deleted = 0 AND sub_system_guid = @sub_system_guid";
|
||||||
|
var electricMeters = await backgroundServiceRepository.GetAllAsync<Device>("device", sWhere, new { sub_system_guid = electricMeterGuid });
|
||||||
|
#endregion 找出所有電錶設備
|
||||||
|
|
||||||
|
#region 找出所有電錶系統的點位
|
||||||
|
var sPointWhere = "deleted = 0 AND sub_system_guid = @sub_system_guid";
|
||||||
|
var points = await backgroundServiceRepository.GetAllAsync<Device_item>("device_item", sPointWhere, new { sub_system_guid = electricMeterGuid });
|
||||||
|
#endregion 找出所有電錶系統的點位
|
||||||
|
|
||||||
|
#region 組合出所有電錶設備點位
|
||||||
|
List<DeviceNumberPoint> deviceNumberPoints = new List<DeviceNumberPoint>();
|
||||||
|
foreach (var electricMeter in electricMeters)
|
||||||
|
{
|
||||||
|
foreach (var point in points)
|
||||||
|
{
|
||||||
|
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
deviceNumberPoint.DeviceNumber = electricMeter.Device_number;
|
||||||
|
deviceNumberPoint.Point = point.points;
|
||||||
|
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", electricMeter.Device_number, point.points);
|
||||||
|
|
||||||
|
deviceNumberPoints.Add(deviceNumberPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion 組合出所有電錶設備點位
|
||||||
|
|
||||||
|
#region 取得obix 設定
|
||||||
|
var obixApiConfig = new ObixApiConfig();
|
||||||
|
|
||||||
|
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
|
||||||
|
|
||||||
|
var variableObix = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlObix);
|
||||||
|
obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
|
||||||
|
obixApiConfig.UserName = ed.AESDecrypt(variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
|
||||||
|
obixApiConfig.Password = ed.AESDecrypt(variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
|
||||||
|
|
||||||
|
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
|
||||||
|
#endregion 取得obix 設定
|
||||||
|
|
||||||
|
var now = DateTime.Now;
|
||||||
|
|
||||||
|
#region 小時歸檔
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var preHour = now.AddHours(-1); //取得前一小時
|
||||||
|
|
||||||
|
var tempHour = string.Empty;
|
||||||
|
if (preHour.Hour < 10)
|
||||||
|
{
|
||||||
|
tempHour = "0" + preHour.Hour.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tempHour = preHour.Hour.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTimestamp = string.Format("{0}T{1}:00:00.000+08:00", preHour.ToString("yyyy-MM-dd"), tempHour);
|
||||||
|
var endTimestamp = string.Format("{0}T{1}:59:59.000+08:00", preHour.ToString("yyyy-MM-dd"), tempHour);
|
||||||
|
|
||||||
|
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
<abstime name='start' val='{startTimestamp}' />
|
||||||
|
<abstime name='end' val='{endTimestamp}' />
|
||||||
|
<reltime name='interval' val = 'PT1H' />
|
||||||
|
</obj>";
|
||||||
|
|
||||||
|
//Stopwatch stopWatch = new Stopwatch();
|
||||||
|
//stopWatch.Start();
|
||||||
|
|
||||||
|
//抓取每個設備的資料
|
||||||
|
List<Dictionary<string, object>> archiveHourRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
foreach (var deviceNumberPoint in deviceNumberPoints)
|
||||||
|
{
|
||||||
|
|
||||||
|
HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
//HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
archiveHourRequest.Method = "POST";
|
||||||
|
archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
archiveHourRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
using (Stream reqStream = archiveHourRequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse archiveHourResponse = (HttpWebResponse)archiveHourRequest.GetResponse();
|
||||||
|
var archiveHourResponseContent = new StreamReader(archiveHourResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
xmlDocument.LoadXml(archiveHourResponseContent);
|
||||||
|
string archiveHourJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
JObject archiveHourJsonResult = (JObject)JsonConvert.DeserializeObject(archiveHourJson);
|
||||||
|
|
||||||
|
if (archiveHourJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
{
|
||||||
|
//logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【取得資料失敗】");
|
||||||
|
//logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveHourJsonResult);
|
||||||
|
|
||||||
|
Dictionary<string, object> archiveHourRawData = new Dictionary<string, object>();
|
||||||
|
archiveHourRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
|
||||||
|
archiveHourRawData.Add("@point", deviceNumberPoint.Point);
|
||||||
|
archiveHourRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19));
|
||||||
|
archiveHourRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19));
|
||||||
|
archiveHourRawData.Add("@is_complete", 0);
|
||||||
|
archiveHourRawData.Add("@repeat_times", 0);
|
||||||
|
archiveHourRawData.Add("@fail_reason", archiveHourJson);
|
||||||
|
|
||||||
|
archiveHourRawDatas.Add(archiveHourRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archiveHourJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
{
|
||||||
|
var histories = archiveHourJsonResult["obj"]["list"];
|
||||||
|
var rawdateCount = Convert.ToInt32(archiveHourJsonResult["obj"]["int"]["@val"].ToString());
|
||||||
|
if (histories != null && histories.HasValues)
|
||||||
|
{
|
||||||
|
if (rawdateCount > 1)
|
||||||
|
{ //多筆資料
|
||||||
|
foreach (var history in histories)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> archiveHourRawData = new Dictionary<string, object>();
|
||||||
|
archiveHourRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
|
||||||
|
archiveHourRawData.Add("@point", deviceNumberPoint.Point);
|
||||||
|
|
||||||
|
//時間
|
||||||
|
if (history["abstime"] != null && history["abstime"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var abstime in history["abstime"])
|
||||||
|
{
|
||||||
|
var name = abstime["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "start":
|
||||||
|
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
archiveHourRawData.Add("@start_timestamp", startTimstamp);
|
||||||
|
break;
|
||||||
|
case "end":
|
||||||
|
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
archiveHourRawData.Add("@end_timestamp", endTimstamp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//區間內資料筆數
|
||||||
|
if (history["int"] != null && history["int"].HasValues)
|
||||||
|
{
|
||||||
|
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@count_rawdata", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
//整合數值(最大、最小、平均、總和)
|
||||||
|
if (history["real"] != null && history["real"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var real in history["real"])
|
||||||
|
{
|
||||||
|
var name = real["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "min":
|
||||||
|
var min = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@min_rawdata", min);
|
||||||
|
break;
|
||||||
|
case "max":
|
||||||
|
var max = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@max_rawdata", max);
|
||||||
|
break;
|
||||||
|
case "avg":
|
||||||
|
var avg = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@avg_rawdata", avg);
|
||||||
|
break;
|
||||||
|
case "sum":
|
||||||
|
var sum = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@sum_rawdata", sum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
archiveHourRawData.Add("@is_complete", 1);
|
||||||
|
|
||||||
|
archiveHourRawDatas.Add(archiveHourRawData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //單筆資料
|
||||||
|
Dictionary<string, object> archiveHourRawData = new Dictionary<string, object>();
|
||||||
|
archiveHourRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
|
||||||
|
archiveHourRawData.Add("@point", deviceNumberPoint.Point);
|
||||||
|
|
||||||
|
//時間
|
||||||
|
if (histories["obj"]["abstime"] != null && histories["obj"]["abstime"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var abstime in histories["obj"]["abstime"])
|
||||||
|
{
|
||||||
|
var name = abstime["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "start":
|
||||||
|
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
archiveHourRawData.Add("@start_timestamp", startTimstamp);
|
||||||
|
break;
|
||||||
|
case "end":
|
||||||
|
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
archiveHourRawData.Add("@end_timestamp", endTimstamp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//區間內資料筆數
|
||||||
|
if (histories["obj"]["int"] != null && histories["obj"]["int"].HasValues)
|
||||||
|
{
|
||||||
|
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@count_rawdata", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
//整合數值(最大、最小、平均、總和)
|
||||||
|
if (histories["obj"]["real"] != null && histories["obj"]["real"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var real in histories["obj"]["real"])
|
||||||
|
{
|
||||||
|
var name = real["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "min":
|
||||||
|
var min = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@min_rawdata", min);
|
||||||
|
break;
|
||||||
|
case "max":
|
||||||
|
var max = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@max_rawdata", max);
|
||||||
|
break;
|
||||||
|
case "avg":
|
||||||
|
var avg = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@avg_rawdata", avg);
|
||||||
|
break;
|
||||||
|
case "sum":
|
||||||
|
var sum = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
archiveHourRawData.Add("@sum_rawdata", sum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
archiveHourRawData.Add("@is_complete", 1);
|
||||||
|
|
||||||
|
archiveHourRawDatas.Add(archiveHourRawData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//stopWatch.Stop();
|
||||||
|
//logger.LogInformation("【ArchiveElectricMeterHourJob】【小時歸檔】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
|
||||||
|
|
||||||
|
if (archiveHourRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
await backgroundServiceRepository.AddMutiByCustomTable(archiveHourRawDatas, "archive_electric_meter_hour");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterHourJob", "All", "任務完成");
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("ArchiveElectricMeterHourJob", "All", exception.ToString());
|
||||||
|
logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【任務失敗】");
|
||||||
|
logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【任務失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
}
|
||||||
|
#endregion 小時歸檔
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("ArchiveElectricMeterHourJob", "All", exception.ToString());
|
||||||
|
logger.LogError("【ArchiveElectricMeterHourJob】【任務失敗】");
|
||||||
|
logger.LogError("【ArchiveElectricMeterHourJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
269
Backend/Quartz/Jobs/DataDeliveryJob.cs
Normal file
269
Backend/Quartz/Jobs/DataDeliveryJob.cs
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Quartz;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Backend.Quartz.Jobs
|
||||||
|
{
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
class DataDeliveryJob : IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<DataDeliveryJob> logger;
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
|
||||||
|
public DataDeliveryJob(
|
||||||
|
ILogger<DataDeliveryJob> logger,
|
||||||
|
IBackgroundServiceRepository backgroundServiceRepository)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> insertLog = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@task_id", 0 },
|
||||||
|
{ "@log_level", "" },
|
||||||
|
{ "@log_content", "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【DataDeliveryJob】【任務開始】");
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"【DataDeliveryJob】任務開始";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
|
||||||
|
//找出所有要派送的資料
|
||||||
|
string sWhere = @"is_complete = 0 AND task_type = @Task_type AND repeat_times < 10";
|
||||||
|
var backgroundServiceTasks = await backgroundServiceRepository.GetAllAsync<BackgroundServiceTask>("background_service_task", sWhere, new { Task_type = BackgroundServiceTaskType.data_delivery });
|
||||||
|
|
||||||
|
if (backgroundServiceTasks.Count == 0)
|
||||||
|
{
|
||||||
|
logger.LogInformation("【DataDeliveryJob】【查無任務列表】");
|
||||||
|
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"【DataDeliveryJob】查無任務列表";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<Dictionary<string, object>> updateObjs = new List<Dictionary<string, object>>();
|
||||||
|
foreach (var task in backgroundServiceTasks)
|
||||||
|
{
|
||||||
|
var DateTimeNow = DateTime.Now;
|
||||||
|
Dictionary<string, object> updateObj = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "Id", task.Id },
|
||||||
|
{ "@repeat_times", 0 },
|
||||||
|
{ "@is_complete", 0 },
|
||||||
|
{ "@fail_reason", null },
|
||||||
|
{ "@complete_at", null },
|
||||||
|
{ "@updated_at", DateTimeNow }
|
||||||
|
};
|
||||||
|
|
||||||
|
insertLog["@task_id"] = task.Id;
|
||||||
|
|
||||||
|
//var parameters = JsonSerializer.Deserialize<Dictionary<string, object>>(task.Target_data);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【DataDeliveryJob】【開始派送】[棟別IP]:{0}", task.Target_ip);
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"開始派送";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
|
||||||
|
var boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
|
||||||
|
|
||||||
|
var boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
|
||||||
|
var endBoundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--");
|
||||||
|
|
||||||
|
HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create($"http://{task.Target_ip}/api/ReceiveDataDelivery/GetData");
|
||||||
|
Postrequest.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||||
|
Postrequest.Method = "POST";
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(task.Target_table))
|
||||||
|
{
|
||||||
|
using (Stream requestStream = Postrequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
//Id
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
string task_id = "Content-Disposition: form-data; name=\"" + "Id" + "\"\r\n\r\n" + task.Id;
|
||||||
|
byte[] task_id_bytes = System.Text.Encoding.UTF8.GetBytes(task_id);
|
||||||
|
requestStream.Write(task_id_bytes, 0, task_id_bytes.Length);
|
||||||
|
|
||||||
|
//Target Table
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
string target_table = "Content-Disposition: form-data; name=\"" + "TargetTable" + "\"\r\n\r\n" + task.Target_table;
|
||||||
|
byte[] target_table_bytes = System.Text.Encoding.UTF8.GetBytes(target_table);
|
||||||
|
requestStream.Write(target_table_bytes, 0, target_table_bytes.Length);
|
||||||
|
|
||||||
|
//mode
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
string target_mode = "Content-Disposition: form-data; name=\"" + "mode" + "\"\r\n\r\n" + task.Mode;
|
||||||
|
byte[] target_mode_bytes = System.Text.Encoding.UTF8.GetBytes(target_mode);
|
||||||
|
requestStream.Write(target_mode_bytes, 0, target_mode_bytes.Length);
|
||||||
|
|
||||||
|
//Target data
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
string target_data = "Content-Disposition: form-data; name=\"" + "TargetData" + "\"\r\n\r\n" + task.Target_data;
|
||||||
|
byte[] target_data_bytes = System.Text.Encoding.UTF8.GetBytes(target_data);
|
||||||
|
requestStream.Write(target_data_bytes, 0, target_data_bytes.Length);
|
||||||
|
|
||||||
|
//解析Files
|
||||||
|
if (task.Target_files != null)
|
||||||
|
{
|
||||||
|
var target_files = JsonSerializer.Deserialize<List<Backend.Models.FileInfo>>(task.Target_files);
|
||||||
|
var file_index = 0;
|
||||||
|
|
||||||
|
foreach (var file in target_files)
|
||||||
|
{
|
||||||
|
//file Folder
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
string file_folder = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].Folder" + "\"\r\n\r\n" + file.Folder;
|
||||||
|
byte[] file_folder_bytes = System.Text.Encoding.UTF8.GetBytes(file_folder);
|
||||||
|
requestStream.Write(file_folder_bytes, 0, file_folder_bytes.Length);
|
||||||
|
|
||||||
|
//file OriginalFileName
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
string orig_file_name = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].OriginalFileName" + "\"\r\n\r\n" + file.OriginalFileName;
|
||||||
|
byte[] orig_file_name_bytes = System.Text.Encoding.UTF8.GetBytes(orig_file_name);
|
||||||
|
requestStream.Write(orig_file_name_bytes, 0, orig_file_name_bytes.Length);
|
||||||
|
|
||||||
|
//file FileName
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
string file_name = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].FileName" + "\"\r\n\r\n" + file.FileName;
|
||||||
|
byte[] file_name_bytes = System.Text.Encoding.UTF8.GetBytes(file_name);
|
||||||
|
requestStream.Write(file_name_bytes, 0, file_name_bytes.Length);
|
||||||
|
|
||||||
|
//取得Content-Type
|
||||||
|
var content_type = string.Empty;
|
||||||
|
string ext = Path.GetExtension(file.File);
|
||||||
|
using (Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext))
|
||||||
|
{
|
||||||
|
if (registryKey != null)
|
||||||
|
{
|
||||||
|
var value = registryKey.GetValue("Content Type");
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
content_type = value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.File != null)
|
||||||
|
{
|
||||||
|
string file_header = "Content-Disposition: form-data; name=\"" + $"FileInfos[{file_index}].File" + "\"; filename=\"" + file.FileName + "\"\r\nContent-Type: " + content_type + "\r\n\r\n";
|
||||||
|
byte[] file_header_bytes = System.Text.Encoding.UTF8.GetBytes(file_header);
|
||||||
|
|
||||||
|
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
|
||||||
|
requestStream.Write(file_header_bytes, 0, file_header_bytes.Length);
|
||||||
|
byte[] buffer = new byte[32768];
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
// upload from file
|
||||||
|
using (FileStream fileStream = File.OpenRead(file.File))
|
||||||
|
{
|
||||||
|
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
|
||||||
|
requestStream.Write(buffer, 0, bytesRead);
|
||||||
|
fileStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
|
||||||
|
requestStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
|
||||||
|
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
|
||||||
|
var statusNumber = (int)response.StatusCode;
|
||||||
|
if (statusNumber != 200)
|
||||||
|
{
|
||||||
|
logger.LogError("【DataDeliveryJob】【派送失敗】[棟別IP]:{0}", task.Target_ip);
|
||||||
|
logger.LogError("【DataDeliveryJob】【派送失敗】[response]:{0}", responseString);
|
||||||
|
updateObj["@repeat_times"] = task.Repeat_times + 1;
|
||||||
|
updateObj["@fail_reason"] = responseString;
|
||||||
|
|
||||||
|
insertLog["@log_level"] = $@"ERR";
|
||||||
|
insertLog["@log_content"] = $@"派送失敗 - [失敗原因]:{responseString}";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//解析回傳內容
|
||||||
|
var final = JObject.Parse(responseString);
|
||||||
|
var code = final["code"].ToString();
|
||||||
|
if (code == "0000")
|
||||||
|
{
|
||||||
|
logger.LogInformation("【DataDeliveryJob】【派送成功】[棟別IP]:{0}", task.Target_ip);
|
||||||
|
updateObj["@repeat_times"] = task.Repeat_times;
|
||||||
|
updateObj["@is_complete"] = 1;
|
||||||
|
updateObj["@complete_at"] = DateTime.Now;
|
||||||
|
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"派送成功";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogError("【DataDeliveryJob】【派送失敗】[棟別IP]:{0}", task.Target_ip);
|
||||||
|
logger.LogError("【DataDeliveryJob】【派送失敗】[response]:{0}", responseString);
|
||||||
|
updateObj["@repeat_times"] = task.Repeat_times + 1;
|
||||||
|
updateObj["@fail_reason"] = responseString;
|
||||||
|
|
||||||
|
insertLog["@log_level"] = $@"ERR";
|
||||||
|
insertLog["@log_content"] = $@"派送失敗 - [失敗原因]:{responseString}";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【DataDeliveryJob】【派送失敗】[棟別IP]:{0}", task.Target_ip);
|
||||||
|
logger.LogError("【DataDeliveryJob】【派送失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
updateObj["@repeat_times"] = task.Repeat_times + 1;
|
||||||
|
updateObj["@fail_reason"] = exception.ToString();
|
||||||
|
|
||||||
|
insertLog["@log_level"] = $@"ERR";
|
||||||
|
insertLog["@log_content"] = $@"派送失敗 - [失敗原因(Exception)]:{exception.ToString()}";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
}
|
||||||
|
|
||||||
|
updateObjs.Add(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
await backgroundServiceRepository.UpdateListByCustomTable(updateObjs, "background_service_task", "id = @Id");
|
||||||
|
logger.LogInformation("【DataDeliveryJob】【任務完成】");
|
||||||
|
|
||||||
|
insertLog["@task_id"] = 0;
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"任務完成";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【DataDeliveryJob】【任務失敗】");
|
||||||
|
logger.LogError("【DataDeliveryJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
|
||||||
|
insertLog["@task_id"] = 0;
|
||||||
|
insertLog["@log_level"] = $@"ERR";
|
||||||
|
insertLog["@log_content"] = $@"任務失敗";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_task_log");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
Backend/Quartz/Jobs/ExecutionBackgroundServicePlanJob.cs
Normal file
113
Backend/Quartz/Jobs/ExecutionBackgroundServicePlanJob.cs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Quartz;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Backend.Quartz.Jobs
|
||||||
|
{
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
public class ExecutionBackgroundServicePlanJob : IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<ExecutionBackgroundServicePlanJob> logger;
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
|
||||||
|
public ExecutionBackgroundServicePlanJob(
|
||||||
|
ILogger<ExecutionBackgroundServicePlanJob> logger,
|
||||||
|
IBackgroundServiceRepository backgroundServiceRepository)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【ExecutionBackgroundServicePlanJob】【任務開始】");
|
||||||
|
|
||||||
|
// 找出當前在起始與結束時間所有計畫
|
||||||
|
var DateTimeNow = DateTime.Now;
|
||||||
|
var sPlanWhere = @"deleted = 0
|
||||||
|
AND
|
||||||
|
(
|
||||||
|
@DateTimeNow Between start_time AND end_time
|
||||||
|
OR (end_time IS NULL AND @DateTimeNow > start_time)
|
||||||
|
)
|
||||||
|
";
|
||||||
|
var backgroundServicePlans = await backgroundServiceRepository.GetAllAsync<BackgroundServicePlan>("background_service_plan", sPlanWhere, new { DateTimeNow = DateTimeNow.ToString("yyyy-MM-dd HH:mm:ss") });
|
||||||
|
|
||||||
|
foreach (var plan in backgroundServicePlans)
|
||||||
|
{
|
||||||
|
//logger.LogInformation("【ExecutionBackgroundServicePlanJob】【計畫編號:{0},計畫名稱:{1}】 - 開始生成下次任務項目", plan.Id, plan.Plane_name);
|
||||||
|
#region 紀錄最後生成任務的時間
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var lastCreateTime = Convert.ToDateTime(plan.Last_create_time);
|
||||||
|
if (lastCreateTime == default(DateTime))
|
||||||
|
{
|
||||||
|
lastCreateTime = Convert.ToDateTime(plan.Start_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime nextCreateTime; //下次待生成的時間
|
||||||
|
nextCreateTime = plan.Execution_type switch
|
||||||
|
{
|
||||||
|
(byte)ExecutionTypeEnum.Min => Convert.ToDateTime(lastCreateTime).AddMinutes(plan.Execution_time),
|
||||||
|
(byte)ExecutionTypeEnum.Hour => Convert.ToDateTime(lastCreateTime).AddHours(plan.Execution_time),
|
||||||
|
(byte)ExecutionTypeEnum.Day => Convert.ToDateTime(lastCreateTime).AddDays(plan.Execution_time),
|
||||||
|
(byte)ExecutionTypeEnum.Week => Convert.ToDateTime(lastCreateTime).AddDays(plan.Execution_time * 7),
|
||||||
|
(byte)ExecutionTypeEnum.Month => Convert.ToDateTime(lastCreateTime).AddMonths(plan.Execution_time),
|
||||||
|
_ => default(DateTime)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (nextCreateTime != default(DateTime) && nextCreateTime < DateTimeNow)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> servicePlanDic = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@last_create_time", nextCreateTime},
|
||||||
|
{ "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
|
};
|
||||||
|
|
||||||
|
await backgroundServiceRepository.UpdateOneByCustomTable(servicePlanDic, "background_service_plan", "id=" + plan.Id + "");
|
||||||
|
|
||||||
|
#region 建立任務
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BackgroundServiceTask backgroundServiceTask = new BackgroundServiceTask()
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch(Exception exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion 建立任務
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
//logger.LogError("【ExecutionBackgroundServicePlanJob】【計畫編號:{0},計畫名稱:{1}】 - 產生下次任務時間失敗", plan.Id, plan.Plane_name);
|
||||||
|
//logger.LogError("【ExecutionBackgroundServicePlanJob】【計畫編號:{0},計畫名稱:{1}】 - 產生下次任務時間失敗[Exception]- {2}", plan.Id, plan.Plane_name, exception.Message); ;
|
||||||
|
}
|
||||||
|
#endregion 紀錄最後該生成任務的時間
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
logger.LogInformation("【ExecutionBackgroundServicePlanJob】【任務完成】");
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【ExecutionBackgroundServicePlanJob】【任務失敗】");
|
||||||
|
logger.LogError("【ExecutionBackgroundServicePlanJob】【任務失敗】[Exception]:{0}", exception.Message); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
163
Backend/Quartz/Jobs/MessageNotificationJob.cs
Normal file
163
Backend/Quartz/Jobs/MessageNotificationJob.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using BackendWorkerService.Services.Interface;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Quartz;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Backend.Quartz.Jobs
|
||||||
|
{
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
class MessageNotificationJob : IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<MessageNotificationJob> logger;
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
|
||||||
|
private readonly ISendEmailService sendEmailService;
|
||||||
|
private readonly ISendSMSService sendSMSService;
|
||||||
|
private readonly ISendLineNotifyService sendLineNotifyService;
|
||||||
|
|
||||||
|
|
||||||
|
public MessageNotificationJob(
|
||||||
|
ILogger<MessageNotificationJob> logger,
|
||||||
|
IBackgroundServiceRepository backgroundServiceRepository,
|
||||||
|
ISendEmailService sendEmailService,
|
||||||
|
ISendSMSService sendSMSService,
|
||||||
|
ISendLineNotifyService sendLineNotifyService)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
||||||
|
this.sendEmailService = sendEmailService;
|
||||||
|
this.sendSMSService = sendSMSService;
|
||||||
|
this.sendLineNotifyService = sendLineNotifyService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> insertLog = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@task_id", 0 },
|
||||||
|
{ "@log_level", "" },
|
||||||
|
{ "@log_content", "" }
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【MessageNotificationJob】【任務開始】");
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"任務開始";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
|
||||||
|
|
||||||
|
//找出所有要通知的清單
|
||||||
|
string sWhere = @"is_complete = 0";
|
||||||
|
var messageNotificationTasks = await backgroundServiceRepository.GetAllAsync<BackgroundServiceMessageNotificationTask>("background_service_message_notification_task", sWhere);
|
||||||
|
|
||||||
|
if(messageNotificationTasks.Count == 0)
|
||||||
|
{
|
||||||
|
logger.LogInformation("【MessageNotificationJob】【查無任務列表】");
|
||||||
|
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"查無任務列表";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<Dictionary<string, object>> updateObjs = new List<Dictionary<string, object>>();
|
||||||
|
foreach (var task in messageNotificationTasks)
|
||||||
|
{
|
||||||
|
var DateTimeNow = DateTime.Now;
|
||||||
|
Dictionary<string, object> updateObj = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "Id", task.Id },
|
||||||
|
{ "@updated_at", DateTimeNow }
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (task.Task_type)
|
||||||
|
{
|
||||||
|
case (byte)MessageNotificationTaskType.email:
|
||||||
|
List<string> recipientEmails = new List<string>()
|
||||||
|
{
|
||||||
|
task.Recipient_email
|
||||||
|
};
|
||||||
|
|
||||||
|
if (sendEmailService.Send(task.Id, recipientEmails, task.Email_subject, task.Message_content))
|
||||||
|
{
|
||||||
|
updateObj.Add("@is_complete", 1);
|
||||||
|
updateObj.Add("@complete_at", DateTimeNow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateObj.Add("@repeat_times", task.Repeat_times + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateObjs.Add(updateObj);
|
||||||
|
break;
|
||||||
|
case (byte)MessageNotificationTaskType.sms:
|
||||||
|
if (sendSMSService.Send(task.Id, task.Recipient_phone, task.Message_content))
|
||||||
|
{
|
||||||
|
updateObj.Add("@is_complete", 1);
|
||||||
|
updateObj.Add("@complete_at", DateTimeNow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateObj.Add("@repeat_times", task.Repeat_times + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateObjs.Add(updateObj);
|
||||||
|
break;
|
||||||
|
case (byte)MessageNotificationTaskType.line_notify:
|
||||||
|
if (sendLineNotifyService.Send(task.Id, task.Line_token, task.Message_content))
|
||||||
|
{
|
||||||
|
updateObj.Add("@is_complete", 1);
|
||||||
|
updateObj.Add("@complete_at", DateTimeNow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateObj.Add("@repeat_times", task.Repeat_times + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateObjs.Add(updateObj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【MessageNotificationJob】【通知失敗】[任務id]:{0}", task.Id);
|
||||||
|
logger.LogError("【MessageNotificationJob】【通知失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
|
||||||
|
insertLog["@log_level"] = $@"ERR";
|
||||||
|
insertLog["@log_content"] = $@"通知失敗 - [失敗原因(Exception)]:{exception.ToString()}";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
await backgroundServiceRepository.UpdateListByCustomTable(updateObjs, "background_service_message_notification_task", "id = @Id");
|
||||||
|
logger.LogInformation("【MessageNotificationJob】【任務完成】");
|
||||||
|
|
||||||
|
insertLog["@task_id"] = 0;
|
||||||
|
insertLog["@log_level"] = $@"INFO";
|
||||||
|
insertLog["@log_content"] = $@"任務完成";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【MessageNotificationJob】【任務失敗】");
|
||||||
|
logger.LogError("【MessageNotificationJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
|
||||||
|
insertLog["@task_id"] = 0;
|
||||||
|
insertLog["@log_level"] = $@"ERR";
|
||||||
|
insertLog["@log_content"] = $@"任務失敗";
|
||||||
|
await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
324
Backend/Quartz/Jobs/ParkingJob.cs
Normal file
324
Backend/Quartz/Jobs/ParkingJob.cs
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Quartz;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Backend.Quartz.Jobs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 停車場管理
|
||||||
|
/// </summary>
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
class ParkingJob : IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<ParkingJob> logger;
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
private readonly IBackendRepository backendRepository;
|
||||||
|
private readonly ILogger<Task_Detail> loggers;
|
||||||
|
|
||||||
|
public ParkingJob(
|
||||||
|
ILogger<ParkingJob> logger,
|
||||||
|
IBackgroundServiceRepository backgroundServiceRepository, ILogger<Task_Detail> loggers, IBackendRepository backendRepository)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(await task_Detail.GetNeedWorkTask("ParkingJob", "All"))
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("ParkingJob", "All", "任務開始");
|
||||||
|
EDFunction ed = new EDFunction();
|
||||||
|
var parkingConfig = new ParkingConfig();
|
||||||
|
|
||||||
|
var sqlParking = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'parkingConfig'";
|
||||||
|
|
||||||
|
var variable = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlParking);
|
||||||
|
parkingConfig.Host = variable.Where(x => x.Name == "Host").Select(x => x.Value).FirstOrDefault();
|
||||||
|
parkingConfig.Prefix = variable.Where(x => x.Name == "Prefix").Select(x => x.Value).FirstOrDefault();
|
||||||
|
parkingConfig.ApiBase = variable.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
|
||||||
|
parkingConfig.UserName = ed.AESDecrypt(variable.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
|
||||||
|
parkingConfig.Password = ed.AESDecrypt(variable.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
|
||||||
|
|
||||||
|
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(parkingConfig.UserName + ":" + parkingConfig.Password));
|
||||||
|
|
||||||
|
#region 取得停車場資訊
|
||||||
|
if (await task_Detail.GetNeedWorkTask("ParkingJob", "Parking"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("ParkingJob", "Parking", "開始執行停車場剩餘車位Job");
|
||||||
|
HttpWebRequest spaceRequest = (HttpWebRequest)WebRequest.Create($"{parkingConfig.Host}{parkingConfig.Prefix}/api/space/details");
|
||||||
|
spaceRequest.Method = "GET";
|
||||||
|
//request.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
spaceRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
//Stopwatch stopWatch = new Stopwatch();
|
||||||
|
//stopWatch.Start();
|
||||||
|
|
||||||
|
HttpWebResponse spaceResponse = (HttpWebResponse)spaceRequest.GetResponse();
|
||||||
|
var spaceResponseContent = new StreamReader(spaceResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
//logger.LogInformation("【ParkingJob】【取得成功停車場車位資訊】");
|
||||||
|
//stopWatch.Stop();
|
||||||
|
//logger.LogInformation("【ParkingJob】【取得停車場車位資訊】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
|
||||||
|
|
||||||
|
var spaceResponseResult = JsonConvert.DeserializeObject<SpaceResponse>(spaceResponseContent);
|
||||||
|
|
||||||
|
//取得停車場車位對應表
|
||||||
|
var sqlSapceMapping = $@"SELECT * FROM variable WHERE deleted = 0 AND system_type = 'parkingSapceMapping'";
|
||||||
|
var parkingSapceMapping = await backgroundServiceRepository.GetAllAsync<VariableInfo>(sqlSapceMapping);
|
||||||
|
|
||||||
|
if (spaceResponseResult != null && spaceResponseResult.Code == "20000")
|
||||||
|
{
|
||||||
|
foreach (var area in spaceResponseResult.Payload.Areas)
|
||||||
|
{
|
||||||
|
//找出對定的設備代碼
|
||||||
|
var selectedMapping = parkingSapceMapping.Where(x => x.System_key == area.Name).FirstOrDefault();
|
||||||
|
if (selectedMapping != null)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parames.Add(tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(apiFormat, parames.ToArray()));
|
||||||
|
request.Method = "POST";
|
||||||
|
request.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
request.PreAuthenticate = true;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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.LogWarning("【ParkingJob】【停車場剩餘車位資訊】[查無該名稱對應表]:{0}", area.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】 - [查無資料]");
|
||||||
|
}
|
||||||
|
await task_Detail.InsertWorkTime_End("ParkingJob", "Parking", "執行成功停車場剩餘車位Job");
|
||||||
|
//logger.LogInformation("【ParkingJob】【執行成功停車場剩餘車位Job】");
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("ParkingJob", "Parking", exception.ToString());
|
||||||
|
logger.LogInformation("【ParkingJob】【執行失敗停車場剩餘車位Job】");
|
||||||
|
logger.LogInformation("【ParkingJob】【執行失敗停車場剩餘車位Job】[Exception]:{0}", exception.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 取得設備資訊
|
||||||
|
if (await task_Detail.GetNeedWorkTask("ParkingJob", "Device"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("ParkingJob", "Device", "開始執行設備資訊Job");
|
||||||
|
//logger.LogInformation("【ParkingJob】【開始執行設備資訊Job】");
|
||||||
|
|
||||||
|
HttpWebRequest equipmentRequest = (HttpWebRequest)WebRequest.Create($"{parkingConfig.Host}{parkingConfig.Prefix}/api/equipment/state");
|
||||||
|
equipmentRequest.Method = "GET";
|
||||||
|
//request.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
equipmentRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
HttpWebResponse equipmentResponse = (HttpWebResponse)equipmentRequest.GetResponse();
|
||||||
|
var equipmentResponseContent = new StreamReader(equipmentResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
var equipmentResponseResult = JsonConvert.DeserializeObject<EquipmentResponse>(equipmentResponseContent);
|
||||||
|
|
||||||
|
//取得設備對應表
|
||||||
|
var sqlEquipmentMapping = $@"SELECT * FROM variable WHERE deleted = 0 AND system_type = 'parkingEquipmentMapping'";
|
||||||
|
var parkingEquipmentMapping = await backgroundServiceRepository.GetAllAsync<VariableInfo>(sqlEquipmentMapping);
|
||||||
|
|
||||||
|
//List<VariableInfo> parkingEquipmentMapping = new List<VariableInfo>();
|
||||||
|
//VariableInfo variableInfo_1 = new VariableInfo();
|
||||||
|
//variableInfo_1.System_key = "APS-000";
|
||||||
|
//variableInfo_1.system_value = "D3_P_B4F_CAPS_B413";
|
||||||
|
|
||||||
|
//parkingEquipmentMapping.Add(variableInfo_1);
|
||||||
|
|
||||||
|
//VariableInfo variableInfo_2 = new VariableInfo();
|
||||||
|
//variableInfo_2.System_key = "APS-001";
|
||||||
|
//variableInfo_2.system_value = "D3_P_B4F_CAPS_B414";
|
||||||
|
//parkingEquipmentMapping.Add(variableInfo_2);
|
||||||
|
|
||||||
|
if (equipmentResponseResult != null && equipmentResponseResult.Code == "20000")
|
||||||
|
{
|
||||||
|
foreach (var equipment in equipmentResponseResult.Payload)
|
||||||
|
{
|
||||||
|
//找出對定的設備代碼
|
||||||
|
var selectedMapping = parkingEquipmentMapping.Where(x => x.System_key == equipment.Name).FirstOrDefault();
|
||||||
|
if (selectedMapping != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(apiFormat, parames.ToArray()));
|
||||||
|
request.Method = "POST";
|
||||||
|
request.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
request.PreAuthenticate = true;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.LogWarning("【ParkingJob】【設備資訊】[查無該名稱對應表]:{0}", equipment.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogWarning("【ParkingJob】【設備資訊】 - [查無資料]");
|
||||||
|
}
|
||||||
|
await task_Detail.InsertWorkTime_End("ParkingJob", "Device", "執行成功設備資訊Job");
|
||||||
|
//logger.LogInformation("【ParkingJob】【執行成功設備資訊Job】");
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("ParkingJob", "Device", exception.ToString());
|
||||||
|
logger.LogInformation("【ParkingJob】【執行失敗設備資訊Job】");
|
||||||
|
logger.LogInformation("【ParkingJob】【執行失敗設備資訊Job】[Exception]:{0}", exception.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
await task_Detail.InsertWorkTime_End("ParkingJob", "All", "任務完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("ParkingJob", "All", exception.ToString());
|
||||||
|
logger.LogError("【ParkingJob】【任務失敗】");
|
||||||
|
logger.LogError("【ParkingJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
Backend/Quartz/Jobs/RegularUpdateDBTableJob.cs
Normal file
77
Backend/Quartz/Jobs/RegularUpdateDBTableJob.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using Backend.Services.Implement;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Quartz;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Backend.Quartz.Jobs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 定時將資料表加入派送任務
|
||||||
|
/// </summary>
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
class RegularUpdateDBTableJob: IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<RegularUpdateDBTableJob> logger;
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
private readonly IBackendRepository backendRepository;
|
||||||
|
|
||||||
|
public RegularUpdateDBTableJob(
|
||||||
|
ILogger<RegularUpdateDBTableJob> logger,
|
||||||
|
IBackgroundServiceRepository backgroundServiceRepository,
|
||||||
|
IBackendRepository backendRepository)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
||||||
|
this.backendRepository = backendRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【RegularUpdateDBTableJob】【任務開始】");
|
||||||
|
|
||||||
|
//要派送的資料表
|
||||||
|
List<string> db_tables = new List<string>() { "variable" };
|
||||||
|
|
||||||
|
foreach (var db_table in db_tables)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【RegularUpdateDBTableJob】【新增資料表 [{0}] 至派送任務】", db_table);
|
||||||
|
//取得資料表所有資料
|
||||||
|
var temp_datas = (await backgroundServiceRepository.GetAllAsync<dynamic>(db_table, ""));
|
||||||
|
|
||||||
|
List<Dictionary<string, object>> dicts = new List<Dictionary<string, object>>();
|
||||||
|
foreach (var temp_data in temp_datas)
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<string, object>((IDictionary<string, object>)temp_data);
|
||||||
|
|
||||||
|
dicts.Add(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
await backendRepository.ManualInsertBackgroundServiceTask("", "", db_table, "purge_all_insert", dicts);
|
||||||
|
|
||||||
|
logger.LogError("【RegularUpdateDBTableJob】【新增成功 資料表 [{0}] 至派送任務】", db_table);
|
||||||
|
}
|
||||||
|
catch(Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【RegularUpdateDBTableJob】【新增失敗 資料表 [{0}] 至派送任務】", db_table);
|
||||||
|
logger.LogError("【RegularUpdateDBTableJob】【新增失敗 資料表 [{0}] 至派送任務】[Exception]:{1}", db_table, exception.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【RegularUpdateDBTableJob】【任務失敗】");
|
||||||
|
logger.LogError("【RegularUpdateDBTableJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
559
Backend/Quartz/Jobs/WeatherAPIJob.cs
Normal file
559
Backend/Quartz/Jobs/WeatherAPIJob.cs
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Quartz;
|
||||||
|
using Repository.BackendRepository.Implement;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using System.Linq;
|
||||||
|
using NCrontab;
|
||||||
|
using BackendWorkerService.Services.Implement;
|
||||||
|
|
||||||
|
namespace Backend.Quartz.Jobs
|
||||||
|
{
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
class WeatherAPIJob : IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<WeatherAPIJob> logger;
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
private readonly IBackendRepository backendRepository;
|
||||||
|
private readonly ILogger<Task_Detail> loggers;
|
||||||
|
public WeatherAPIJob(ILogger<WeatherAPIJob> logger,
|
||||||
|
IBackgroundServiceRepository backgroundServiceRepository, IBackendRepository backendRepository, ILogger<Task_Detail> loggers)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
||||||
|
this.backendRepository = backendRepository;
|
||||||
|
this.loggers = loggers;
|
||||||
|
}
|
||||||
|
public string Fetch_PostWithJSONFormat(string url, string paramter)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string username = "stanGG";
|
||||||
|
string password = "St12345678";
|
||||||
|
string encoded = Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
|
||||||
|
HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(url);
|
||||||
|
Postrequest.Method = "POST";
|
||||||
|
Postrequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
Postrequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream()))
|
||||||
|
{
|
||||||
|
if (paramter != "NULL")
|
||||||
|
{
|
||||||
|
string json = "<real val=\"" + paramter + "\"/>";
|
||||||
|
streamWriter.Write(json);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string json = "<real val= NULL />";
|
||||||
|
streamWriter.Write(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
|
||||||
|
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
|
||||||
|
XmlDocument xmlDoc = new XmlDocument();
|
||||||
|
xmlDoc.LoadXml(responseString);
|
||||||
|
string jsonText = JsonConvert.SerializeXmlNode(xmlDoc);
|
||||||
|
//JObject resultVal = (JObject)JsonConvert.DeserializeObject(jsonText);
|
||||||
|
|
||||||
|
return jsonText;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError("【WeatherAPIJob】" + "Fetch_PostWithJSONFormat:" + ex.ToString());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
Task_Detail task_Detail = new Task_Detail(loggers, backendRepository);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var obixApiConfig = new ObixApiConfig();
|
||||||
|
string encoded = string.Empty;
|
||||||
|
#region 取得obix 設定
|
||||||
|
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
|
||||||
|
|
||||||
|
var variableObix = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlObix);
|
||||||
|
obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
|
||||||
|
obixApiConfig.UserName = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault();
|
||||||
|
obixApiConfig.Password = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault();
|
||||||
|
|
||||||
|
encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
|
||||||
|
#endregion 取得obix 設定
|
||||||
|
//取得氣象預報
|
||||||
|
if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_weateher"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("WeatherAPI", "api_weateher");
|
||||||
|
var client = new HttpClient();
|
||||||
|
var DataNO = "F-D0047-061";
|
||||||
|
var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-D0047-061?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&format=JSON&locationName=%E4%BF%A1%E7%BE%A9%E5%8D%80&elementName=Wx,PoP12h,T,RH";
|
||||||
|
HttpResponseMessage response = client.GetAsync(UVUri).Result;
|
||||||
|
String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString();
|
||||||
|
|
||||||
|
var observation = JsonConvert.DeserializeObject<Root>(jsonUVs);
|
||||||
|
logger.LogInformation("【WeatherAPIJob】【取得成功氣象預報】");
|
||||||
|
|
||||||
|
if (observation.Success != "true")
|
||||||
|
{
|
||||||
|
logger.LogInformation("【WeatherAPIJob】【取得氣象預報資料不正確】");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogInformation("【WeatherAPIJob】【開始存入氣象預報到資料庫】");
|
||||||
|
List<Dictionary<string, object>> WeatherAPIdbS = new List<Dictionary<string, object>>();
|
||||||
|
var Type_ALL = observation.Records.Locations[0].Location[0].WeatherElement;
|
||||||
|
|
||||||
|
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"},
|
||||||
|
{ "@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")},
|
||||||
|
};
|
||||||
|
WeatherAPIdbS.Add(TWeatherAPIdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await backendRepository.AddMutiByCustomTable(WeatherAPIdbS, "api_weateher");
|
||||||
|
}
|
||||||
|
|
||||||
|
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_weateher");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("WeatherAPI", "api_weateher", ex.Message.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_rain"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("WeatherAPI", "api_rain");
|
||||||
|
WebClient mywebClient = new WebClient();
|
||||||
|
mywebClient.DownloadFile("https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/W-C0033-003?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&downloadType=WEB&format=CAP", @"root/PowerfulRain.xml");
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.Load("root/PowerfulRain.xml");
|
||||||
|
var json = JsonConvert.SerializeXmlNode(doc);
|
||||||
|
var haveinfo = json.Split("info");
|
||||||
|
if (haveinfo.Length > 2)
|
||||||
|
{
|
||||||
|
var observation = RainApi.Welcome.FromJson(json);
|
||||||
|
var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
|
var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
|
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
|
|
||||||
|
Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@msgType", observation.Alert.MsgType},
|
||||||
|
{ "@headline", observation.Alert.Info.Headline},
|
||||||
|
{ "@areaDesc", area},
|
||||||
|
{ "@onset", observation.Alert.Info.Onset},
|
||||||
|
{ "@expires", observation.Alert.Info.Expires},
|
||||||
|
{ "@created_by", "system"},
|
||||||
|
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
|
};
|
||||||
|
var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain");
|
||||||
|
if (NeedCallApi != 0)
|
||||||
|
{
|
||||||
|
var val = RainValue(observation.Alert.MsgType, observation.Alert.Info.Headline);
|
||||||
|
if (val < 5)
|
||||||
|
{
|
||||||
|
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString());
|
||||||
|
UpdatedNiagara("api_rain", ReStr, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderFunction folderFunction = new FolderFunction();
|
||||||
|
folderFunction.DeleteFile("root/PowerfulRain.xml");
|
||||||
|
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var observation = RainApi.Welcome.FromJson(json);
|
||||||
|
var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
|
var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
|
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
|
|
||||||
|
Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@msgType", observation.Alert.MsgType},
|
||||||
|
{ "@headline", observation.Alert.Info.Headline},
|
||||||
|
{ "@areaDesc", area},
|
||||||
|
{ "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
|
{ "@expires", observation.Alert.Info.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");
|
||||||
|
if (NeedCallApi != 0)
|
||||||
|
{
|
||||||
|
var val = RainValue(observation.Alert.MsgType, observation.Alert.Info.Headline);
|
||||||
|
if (val < 5)
|
||||||
|
{
|
||||||
|
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString());
|
||||||
|
UpdatedNiagara("api_rain", ReStr, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderFunction folderFunction = new FolderFunction();
|
||||||
|
folderFunction.DeleteFile("root/PowerfulRain.xml");
|
||||||
|
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("WeatherAPI", "api_rain", ex.Message.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_typhoon"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("WeatherAPI", "api_typhoon");
|
||||||
|
WebClient mywebClient = new WebClient();
|
||||||
|
mywebClient.DownloadFile("https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/W-C0034-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&downloadType=WEB&format=CAP", @"root/Typhoon.xml");
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.Load("root/Typhoon.xml");
|
||||||
|
var json = JsonConvert.SerializeXmlNode(doc);
|
||||||
|
var haveinfo = json.Split("info");
|
||||||
|
|
||||||
|
if (haveinfo.Length > 2)
|
||||||
|
{
|
||||||
|
var observation = TyphoonApi.Welcome.FromJson(json);
|
||||||
|
var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
|
var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
|
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
|
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@msgType", observation.Alert.MsgType},
|
||||||
|
{ "@headline", observation.Alert.Info.Headline},
|
||||||
|
{ "@areaDesc", area},
|
||||||
|
{ "@urgency",observation.Alert.Info.Urgency},
|
||||||
|
{ "@severity",observation.Alert.Info.Severity},
|
||||||
|
{ "@onset", observation.Alert.Info.Onset},
|
||||||
|
{ "@expires", observation.Alert.Info.Expires},
|
||||||
|
{ "@created_by", "system"},
|
||||||
|
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
|
};
|
||||||
|
var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon");
|
||||||
|
if (NeedCallApi != 0)
|
||||||
|
{
|
||||||
|
if (observation.Alert.Info.Urgency != null && observation.Alert.Info.Urgency != "Expected")
|
||||||
|
{
|
||||||
|
|
||||||
|
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency);
|
||||||
|
UpdatedNiagara("api_typhoon", ReStr, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FolderFunction folderFunction = new FolderFunction();
|
||||||
|
folderFunction.DeleteFile("root/Typhoon.xml");
|
||||||
|
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var observation = TyphoonApi.Welcome.FromJson(json);
|
||||||
|
//var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
|
var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
|
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
|
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@msgType", observation.Alert.MsgType},
|
||||||
|
{ "@headline", observation.Alert.Info.Headline},
|
||||||
|
//{ "@areaDesc", area},
|
||||||
|
{ "@urgency",observation.Alert.Info.Urgency},
|
||||||
|
{ "@severity",observation.Alert.Info.Severity},
|
||||||
|
{ "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
|
{ "@expires", observation.Alert.Info.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 (NeedCallApi != 0)
|
||||||
|
{
|
||||||
|
if (observation.Alert.Info.Urgency != null && observation.Alert.Info.Urgency != "Expected")
|
||||||
|
{
|
||||||
|
|
||||||
|
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency);
|
||||||
|
UpdatedNiagara("api_typhoon", ReStr, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FolderFunction folderFunction = new FolderFunction();
|
||||||
|
folderFunction.DeleteFile("root/Typhoon.xml");
|
||||||
|
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("WeatherAPI", "api_typhoon", ex.Message.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_earthquake"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await task_Detail.InsertWorkTime("WeatherAPI", "api_earthquake");
|
||||||
|
var client = new HttpClient();
|
||||||
|
var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/E-A0015-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&format=JSON&areaName=%E8%87%BA%E5%8C%97%E5%B8%82";
|
||||||
|
HttpResponseMessage response = client.GetAsync(UVUri).Result;
|
||||||
|
String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString();
|
||||||
|
var observation = QuickType.Welcome.FromJson(jsonUVs);
|
||||||
|
if (!observation.Success)
|
||||||
|
{
|
||||||
|
logger.LogInformation("【WeatherAPIJob】【取得地震觀測資料不正確】");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogInformation("【WeatherAPIJob】【開始存入地震觀測到資料庫】");
|
||||||
|
List<Dictionary<string, object>> EarthquakeAPIdbS = new List<Dictionary<string, object>>();
|
||||||
|
var nowNo = await backendRepository.GetOneAsync<int>("select if( Max(earthquakeNo) is null ,0,Max(earthquakeNo)) earthquakeNo from api_earthquake where newEarthquake = 1");
|
||||||
|
foreach (var a in observation.Records.Earthquake)
|
||||||
|
{
|
||||||
|
if (a.EarthquakeNo <= nowNo)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@earthquakeNo", a.EarthquakeNo},
|
||||||
|
{ "@newEarthquake", 0},
|
||||||
|
{ "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)},
|
||||||
|
{ "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue},
|
||||||
|
{ "@areaName", null},
|
||||||
|
{ "@areaIntensity", null},
|
||||||
|
{ "@created_by", "system"},
|
||||||
|
{ "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
|
};
|
||||||
|
EarthquakeAPIdbS.Add(EarthquakeAPIdb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (a.Intensity.ShakingArea.Length > 0)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@earthquakeNo", a.EarthquakeNo},
|
||||||
|
{ "@newEarthquake", 1},
|
||||||
|
{ "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)},
|
||||||
|
{ "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue},
|
||||||
|
{ "@areaName", a.Intensity.ShakingArea[0].CountyName},
|
||||||
|
{ "@areaIntensity", a.Intensity.ShakingArea[0].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/SeverityLEVL_LMI/set", a.Intensity.ShakingArea[0].AreaIntensity.ToString());
|
||||||
|
|
||||||
|
if (Nag.Contains("err"))
|
||||||
|
{
|
||||||
|
EarthquakeAPIdb.Add("@niagara", Nag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EarthquakeAPIdb.Add("@niagara", "success");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EarthquakeAPIdbS.Add(EarthquakeAPIdb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@earthquakeNo", a.EarthquakeNo},
|
||||||
|
{ "@newEarthquake", 1},
|
||||||
|
{ "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)},
|
||||||
|
{ "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue},
|
||||||
|
{ "@areaName", null},
|
||||||
|
{ "@areaIntensity", null},
|
||||||
|
{ "@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/SeverityLEVL_LMI/set", "NULL");
|
||||||
|
if (Nag.Contains("err"))
|
||||||
|
{
|
||||||
|
EarthquakeAPIdb.Add("@niagara", Nag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EarthquakeAPIdb.Add("@niagara", "success");
|
||||||
|
}
|
||||||
|
EarthquakeAPIdbS.Add(EarthquakeAPIdb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await backendRepository.AddMutiByCustomTable(EarthquakeAPIdbS, "api_earthquake");
|
||||||
|
}
|
||||||
|
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_earthquake");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("WeatherAPI", "api_earthquake", ex.Message.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【WeatherAPIJob】【任務失敗】");
|
||||||
|
logger.LogError("【WeatherAPIJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RainValue(string Ty, string Headline)
|
||||||
|
{
|
||||||
|
var rint = 5;
|
||||||
|
if (Ty == "")
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Headline.Contains("大雨"))
|
||||||
|
{
|
||||||
|
rint = 1;
|
||||||
|
}
|
||||||
|
else if (Headline.Contains("豪雨"))
|
||||||
|
{
|
||||||
|
rint = 2;
|
||||||
|
}
|
||||||
|
else if (Headline.Contains("大豪雨"))
|
||||||
|
{
|
||||||
|
rint = 3;
|
||||||
|
}
|
||||||
|
else if (Headline.Contains("超大豪雨"))
|
||||||
|
{
|
||||||
|
rint = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void UpdatedNiagara(string DBTableName, string ResponseStr, int CheckNumId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var Su = "success";
|
||||||
|
|
||||||
|
if (ResponseStr.Contains("err"))
|
||||||
|
{
|
||||||
|
Su = ResponseStr;
|
||||||
|
}
|
||||||
|
Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@niagara", Su}
|
||||||
|
};
|
||||||
|
await backendRepository.UpdateOneByCustomTable(RainAPIdb, DBTableName, " id = " + CheckNumId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError("【WeatherAPIJob】" + "UpdatedNiagara:" + ex.ToString());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
Backend/Quartz/QuartzHostedService.cs
Normal file
69
Backend/Quartz/QuartzHostedService.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Quartz;
|
||||||
|
using Quartz.Spi;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Backend.Quartz
|
||||||
|
{
|
||||||
|
public class QuartzHostedService : IHostedService
|
||||||
|
{
|
||||||
|
private readonly ISchedulerFactory _schedulerFactory;
|
||||||
|
private readonly IJobFactory _jobFactory;
|
||||||
|
private readonly IEnumerable<JobSchedule> _jobSchedules;
|
||||||
|
public QuartzHostedService(ISchedulerFactory schedulerFactory, IJobFactory jobFactory, IEnumerable<JobSchedule> jobSchedules)
|
||||||
|
{
|
||||||
|
_schedulerFactory = schedulerFactory ?? throw new ArgumentNullException(nameof(schedulerFactory));
|
||||||
|
_jobFactory = jobFactory ?? throw new ArgumentNullException(nameof(jobFactory));
|
||||||
|
_jobSchedules = jobSchedules ?? throw new ArgumentNullException(nameof(jobSchedules));
|
||||||
|
}
|
||||||
|
public IScheduler Scheduler { get; set; }
|
||||||
|
public async Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
|
||||||
|
Scheduler.JobFactory = _jobFactory;
|
||||||
|
foreach (var jobSchedule in _jobSchedules)
|
||||||
|
{
|
||||||
|
var job = CreateJob(jobSchedule);
|
||||||
|
var trigger = CreateTrigger(jobSchedule);
|
||||||
|
await Scheduler.ScheduleJob(job, trigger, cancellationToken);
|
||||||
|
jobSchedule.JobStatu = JobStatus.Scheduling;
|
||||||
|
}
|
||||||
|
await Scheduler.Start(cancellationToken);
|
||||||
|
foreach (var jobSchedule in _jobSchedules)
|
||||||
|
{
|
||||||
|
jobSchedule.JobStatu = JobStatus.Running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await Scheduler?.Shutdown(cancellationToken);
|
||||||
|
foreach (var jobSchedule in _jobSchedules)
|
||||||
|
{
|
||||||
|
|
||||||
|
jobSchedule.JobStatu = JobStatus.Stopped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static IJobDetail CreateJob(JobSchedule schedule)
|
||||||
|
{
|
||||||
|
var jobType = schedule.JobType;
|
||||||
|
return JobBuilder
|
||||||
|
.Create(jobType)
|
||||||
|
.WithIdentity(jobType.FullName)
|
||||||
|
.WithDescription(jobType.Name)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
private static ITrigger CreateTrigger(JobSchedule schedule)
|
||||||
|
{
|
||||||
|
return TriggerBuilder
|
||||||
|
.Create()
|
||||||
|
.WithIdentity($"{schedule.JobType.FullName}.trigger")
|
||||||
|
.WithCronSchedule(schedule.CronExpression)
|
||||||
|
.WithDescription(schedule.CronExpression)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
Backend/Quartz/SingletonJobFactory.cs
Normal file
26
Backend/Quartz/SingletonJobFactory.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Quartz;
|
||||||
|
using Quartz.Spi;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Backend.Quartz
|
||||||
|
{
|
||||||
|
public class SingletonJobFactory : IJobFactory
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
public SingletonJobFactory(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
||||||
|
}
|
||||||
|
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
|
||||||
|
{
|
||||||
|
return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
|
||||||
|
}
|
||||||
|
public void ReturnJob(IJob job)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
935
Backend/Services/Implement/ProcEletricMeterService.cs
Normal file
935
Backend/Services/Implement/ProcEletricMeterService.cs
Normal file
@ -0,0 +1,935 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Text;
|
||||||
|
using Dapper;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Net;
|
||||||
|
using System.IO;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Repository.Helper;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using Repository.BackendRepository.Implement;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BackendWorkerService.Services.Implement
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 電錶補償歸檔
|
||||||
|
/// </summary>
|
||||||
|
public class ProcEletricMeterService
|
||||||
|
{
|
||||||
|
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||||||
|
private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository;
|
||||||
|
|
||||||
|
public ProcEletricMeterService(IBackgroundServiceRepository backgroundServiceRepository,
|
||||||
|
IBackgroundServiceMsSqlRepository backgroundServiceMySqlRepository)
|
||||||
|
{
|
||||||
|
this.backgroundServiceRepository = backgroundServiceRepository;
|
||||||
|
this.backgroundServiceMsSqlRepository = backgroundServiceMySqlRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ArchiveData()
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
int repeatTimes = 0;
|
||||||
|
string targetTable = string.Empty;
|
||||||
|
|
||||||
|
EDFunction ed = new EDFunction();
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
var obixApiConfig = new ObixApiConfig();
|
||||||
|
string encoded = string.Empty;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//取得可錯誤次數
|
||||||
|
var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'";
|
||||||
|
|
||||||
|
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
|
||||||
|
repeatTimes = Convert.ToInt32(variableArchive.Where(x => x.Name == "RepeatTimes").Select(x => x.Value).FirstOrDefault());
|
||||||
|
var saveToMSDB = await backgroundServiceRepository.GetOneAsync<string>("select system_value from variable where system_type = 'save_to_ms_db' and deleted = 0");
|
||||||
|
|
||||||
|
#region 取得obix 設定
|
||||||
|
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
|
||||||
|
|
||||||
|
var variableObix = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlObix);
|
||||||
|
obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
|
||||||
|
obixApiConfig.UserName = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault();
|
||||||
|
obixApiConfig.Password = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault();
|
||||||
|
|
||||||
|
encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
|
||||||
|
#endregion 取得obix 設定
|
||||||
|
|
||||||
|
//取得錯誤的設備sql format
|
||||||
|
var sql_error_format = @"SELECT * FROM {0} WHERE is_complete = 0 AND repeat_times < @RepeatTimes";
|
||||||
|
|
||||||
|
//MY 新增/修改sql format
|
||||||
|
var MYsql_update_format = @"
|
||||||
|
UPDATE {0} SET
|
||||||
|
count_rawdata = @count_rawdata,
|
||||||
|
min_rawdata = @min_rawdata,
|
||||||
|
max_rawdata = @max_rawdata,
|
||||||
|
avg_rawdata = @avg_rawdata,
|
||||||
|
sum_rawdata = @sum_rawdata,
|
||||||
|
is_complete = @is_complete,
|
||||||
|
repeat_times = @repeat_times,
|
||||||
|
fail_reason = @fail_reason,
|
||||||
|
updated_at = @updated_at
|
||||||
|
WHERE device_number = @device_number
|
||||||
|
AND point = @point
|
||||||
|
AND start_timestamp = @start_timestamp;
|
||||||
|
|
||||||
|
INSERT INTO {0} (
|
||||||
|
device_number,
|
||||||
|
point,
|
||||||
|
start_timestamp,
|
||||||
|
end_timestamp,
|
||||||
|
count_rawdata,
|
||||||
|
min_rawdata,
|
||||||
|
max_rawdata,
|
||||||
|
avg_rawdata,
|
||||||
|
sum_rawdata,
|
||||||
|
is_complete,
|
||||||
|
repeat_times,
|
||||||
|
fail_reason)
|
||||||
|
SELECT
|
||||||
|
@device_number,
|
||||||
|
@point,
|
||||||
|
@start_timestamp,
|
||||||
|
@end_timestamp,
|
||||||
|
@count_rawdata,
|
||||||
|
@min_rawdata,
|
||||||
|
@max_rawdata,
|
||||||
|
@avg_rawdata,
|
||||||
|
@sum_rawdata,
|
||||||
|
@is_complete,
|
||||||
|
@repeat_times,
|
||||||
|
@fail_reason
|
||||||
|
WHERE ROW_COUNT() = 0;";
|
||||||
|
//新增/修改sql format
|
||||||
|
var sql_update_format = @"BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
UPDATE {0} SET
|
||||||
|
count_rawdata = @count_rawdata,
|
||||||
|
min_rawdata = @min_rawdata,
|
||||||
|
max_rawdata = @max_rawdata,
|
||||||
|
avg_rawdata = @avg_rawdata,
|
||||||
|
sum_rawdata = @sum_rawdata,
|
||||||
|
is_complete = @is_complete,
|
||||||
|
repeat_times = @repeat_times,
|
||||||
|
fail_reason = @fail_reason,
|
||||||
|
updated_at = @updated_at
|
||||||
|
WHERE device_number = @device_number
|
||||||
|
AND point = @point
|
||||||
|
AND start_timestamp = @start_timestamp;
|
||||||
|
|
||||||
|
IF @@ROWCOUNT = 0
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO {0} (
|
||||||
|
device_number,
|
||||||
|
point,
|
||||||
|
start_timestamp,
|
||||||
|
end_timestamp,
|
||||||
|
count_rawdata,
|
||||||
|
min_rawdata,
|
||||||
|
max_rawdata,
|
||||||
|
avg_rawdata,
|
||||||
|
sum_rawdata,
|
||||||
|
is_complete,
|
||||||
|
repeat_times,
|
||||||
|
fail_reason)
|
||||||
|
VALUES (
|
||||||
|
@device_number,
|
||||||
|
@point,
|
||||||
|
@start_timestamp,
|
||||||
|
@end_timestamp,
|
||||||
|
@count_rawdata,
|
||||||
|
@min_rawdata,
|
||||||
|
@max_rawdata,
|
||||||
|
@avg_rawdata,
|
||||||
|
@sum_rawdata,
|
||||||
|
@is_complete,
|
||||||
|
@repeat_times,
|
||||||
|
@fail_reason)
|
||||||
|
END
|
||||||
|
|
||||||
|
COMMIT TRANSACTION;";
|
||||||
|
|
||||||
|
#region 時歸檔補償
|
||||||
|
//using (IDbConnection conn = new SqlConnection(Connection1))
|
||||||
|
//{
|
||||||
|
// //取得所有須補償的設備資訊
|
||||||
|
// targetTable = "archive_electric_meter_hour";
|
||||||
|
// var sql_error_hour = string.Format(sql_error_format, targetTable);
|
||||||
|
// var error_hours = conn.Query<ArchiveElectricMeter>(sql_error_hour, new { RepeatTimes = repeatTimes }).ToList();
|
||||||
|
|
||||||
|
// List<Dictionary<string, object>> archiveHourRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
// if (error_hours.Count() > 0)
|
||||||
|
// {
|
||||||
|
// foreach (var error_hour in error_hours)
|
||||||
|
// {
|
||||||
|
// DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
// deviceNumberPoint.DeviceNumber = error_hour.Device_number;
|
||||||
|
// deviceNumberPoint.Point = error_hour.Point;
|
||||||
|
// deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_hour.Device_number, error_hour.Point);
|
||||||
|
|
||||||
|
// var startTimestamp = string.Format("{0}+08:00", error_hour.Start_timestamp.Replace(" ", "T"));
|
||||||
|
// var endTimestamp = string.Format("{0}+08:00", error_hour.End_timestamp.Replace(" ", "T"));
|
||||||
|
|
||||||
|
// var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
// <abstime name='start' val='{startTimestamp}' />
|
||||||
|
// <abstime name='end' val='{endTimestamp}' />
|
||||||
|
// <reltime name='interval' val = 'PT1H' />
|
||||||
|
// </obj>";
|
||||||
|
|
||||||
|
// HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
// //HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
// archiveHourRequest.Method = "POST";
|
||||||
|
// archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
// archiveHourRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
// byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
// using (Stream reqStream = archiveHourRequest.GetRequestStream())
|
||||||
|
// {
|
||||||
|
// reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// HttpWebResponse archiveHourResponse = (HttpWebResponse)archiveHourRequest.GetResponse();
|
||||||
|
// var archiveHourResponseContent = new StreamReader(archiveHourResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
// xmlDocument.LoadXml(archiveHourResponseContent);
|
||||||
|
// string archiveHourJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
// JObject archiveHourJsonResult = (JObject)JsonConvert.DeserializeObject(archiveHourJson);
|
||||||
|
|
||||||
|
// if (archiveHourJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
// {
|
||||||
|
// Dictionary<string, object> archiveDayRawData = new Dictionary<string, object>();
|
||||||
|
// archiveDayRawData.Add("@device_number", error_hour.Device_number);
|
||||||
|
// archiveDayRawData.Add("@point", error_hour.Point);
|
||||||
|
// archiveDayRawData.Add("@start_timestamp", error_hour.Start_timestamp);
|
||||||
|
// archiveDayRawData.Add("@end_timestamp", error_hour.End_timestamp);
|
||||||
|
// archiveDayRawData.Add("@is_complete", 0);
|
||||||
|
// archiveDayRawData.Add("@repeat_times", ++error_hour.Repeat_times);
|
||||||
|
// archiveDayRawData.Add("@fail_reason", archiveHourJson);
|
||||||
|
|
||||||
|
// archiveDayRawData.Add("@count_rawdata", 0);
|
||||||
|
// archiveDayRawData.Add("@min_rawdata", 0);
|
||||||
|
// archiveDayRawData.Add("@max_rawdata", 0);
|
||||||
|
// archiveDayRawData.Add("@avg_rawdata", 0);
|
||||||
|
// archiveDayRawData.Add("@sum_rawdata", 0);
|
||||||
|
// archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
// archiveHourRawDatas.Add(archiveDayRawData);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (archiveHourJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
// {
|
||||||
|
// var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveHourJsonResult);
|
||||||
|
// if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
|
||||||
|
// {
|
||||||
|
// archiveHourRawDatas.AddRange(ArrangeRawDatas);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (archiveHourRawDatas.Count() > 0)
|
||||||
|
// {
|
||||||
|
// var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
|
// conn.Execute(sql_error_update, archiveHourRawDatas);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// conn.Close();
|
||||||
|
//}
|
||||||
|
#endregion 時歸檔補償
|
||||||
|
|
||||||
|
#region 天歸檔補償
|
||||||
|
//取得所有須補償的設備資訊
|
||||||
|
targetTable = "archive_electric_meter_day";
|
||||||
|
var sql_error_day = string.Format(sql_error_format, targetTable);
|
||||||
|
var electric_error_days = await backgroundServiceRepository.GetAllAsync<ArchiveElectricMeter>(sql_error_day, new { RepeatTimes = repeatTimes });
|
||||||
|
List<Dictionary<string, object>> electricArchiveDayRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
if (electric_error_days.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var error_day in electric_error_days)
|
||||||
|
{
|
||||||
|
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
deviceNumberPoint.DeviceNumber = error_day.Device_number;
|
||||||
|
deviceNumberPoint.Point = error_day.Point;
|
||||||
|
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_day.Device_number, error_day.Point);
|
||||||
|
|
||||||
|
var startTimestamp = string.Format("{0}+08:00", error_day.Start_timestamp.Replace(" ", "T"));
|
||||||
|
var endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T"));
|
||||||
|
|
||||||
|
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
<abstime name='start' val='{startTimestamp}' />
|
||||||
|
<abstime name='end' val='{endTimestamp}' />
|
||||||
|
<reltime name='interval' val = 'PT1D' />
|
||||||
|
</obj>";
|
||||||
|
|
||||||
|
HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
//HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
archiveDayRequest.Method = "POST";
|
||||||
|
archiveDayRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
archiveDayRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
using (Stream reqStream = archiveDayRequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse archiveDayResponse = (HttpWebResponse)archiveDayRequest.GetResponse();
|
||||||
|
var archiveDayResponseContent = new StreamReader(archiveDayResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
xmlDocument.LoadXml(archiveDayResponseContent);
|
||||||
|
string archiveDayJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
JObject archiveDayJsonResult = (JObject)JsonConvert.DeserializeObject(archiveDayJson);
|
||||||
|
|
||||||
|
if (archiveDayJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
{
|
||||||
|
Dictionary<string, object> archiveDayRawData = new Dictionary<string, object>();
|
||||||
|
archiveDayRawData.Add("@device_number", error_day.Device_number);
|
||||||
|
archiveDayRawData.Add("@point", error_day.Point);
|
||||||
|
archiveDayRawData.Add("@start_timestamp", DateTime.Parse(error_day.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveDayRawData.Add("@end_timestamp", DateTime.Parse(error_day.End_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveDayRawData.Add("@is_complete", 0);
|
||||||
|
archiveDayRawData.Add("@repeat_times", ++error_day.Repeat_times);
|
||||||
|
archiveDayRawData.Add("@fail_reason", archiveDayJson);
|
||||||
|
|
||||||
|
archiveDayRawData.Add("@count_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@min_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@max_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@avg_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@sum_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
electricArchiveDayRawDatas.Add(archiveDayRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
{
|
||||||
|
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult);
|
||||||
|
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
electricArchiveDayRawDatas.AddRange(ArrangeRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (electricArchiveDayRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveDayRawDatas);
|
||||||
|
}
|
||||||
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveDayRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetTable = "archive_water_meter_day";
|
||||||
|
sql_error_day = string.Format(sql_error_format, targetTable);
|
||||||
|
var water_error_days = await backgroundServiceRepository.GetAllAsync<ArchiveElectricMeter>(sql_error_day, new { RepeatTimes = repeatTimes });
|
||||||
|
List<Dictionary<string, object>> waterArchiveDayRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
if (water_error_days.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var error_day in water_error_days)
|
||||||
|
{
|
||||||
|
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
deviceNumberPoint.DeviceNumber = error_day.Device_number;
|
||||||
|
deviceNumberPoint.Point = error_day.Point;
|
||||||
|
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_day.Device_number, error_day.Point);
|
||||||
|
|
||||||
|
var startTimestamp = string.Format("{0}+08:00", error_day.Start_timestamp.Replace(" ", "T"));
|
||||||
|
var endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T"));
|
||||||
|
|
||||||
|
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
<abstime name='start' val='{startTimestamp}' />
|
||||||
|
<abstime name='end' val='{endTimestamp}' />
|
||||||
|
<reltime name='interval' val = 'PT1D' />
|
||||||
|
</obj>";
|
||||||
|
|
||||||
|
HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
//HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
archiveDayRequest.Method = "POST";
|
||||||
|
archiveDayRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
archiveDayRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
using (Stream reqStream = archiveDayRequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse archiveDayResponse = (HttpWebResponse)archiveDayRequest.GetResponse();
|
||||||
|
var archiveDayResponseContent = new StreamReader(archiveDayResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
xmlDocument.LoadXml(archiveDayResponseContent);
|
||||||
|
string archiveDayJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
JObject archiveDayJsonResult = (JObject)JsonConvert.DeserializeObject(archiveDayJson);
|
||||||
|
|
||||||
|
if (archiveDayJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
{
|
||||||
|
Dictionary<string, object> archiveDayRawData = new Dictionary<string, object>();
|
||||||
|
archiveDayRawData.Add("@device_number", error_day.Device_number);
|
||||||
|
archiveDayRawData.Add("@point", error_day.Point);
|
||||||
|
archiveDayRawData.Add("@start_timestamp", DateTime.Parse(error_day.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveDayRawData.Add("@end_timestamp", DateTime.Parse(error_day.End_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveDayRawData.Add("@is_complete", 0);
|
||||||
|
archiveDayRawData.Add("@repeat_times", ++error_day.Repeat_times);
|
||||||
|
archiveDayRawData.Add("@fail_reason", archiveDayJson);
|
||||||
|
|
||||||
|
archiveDayRawData.Add("@count_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@min_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@max_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@avg_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@sum_rawdata", 0);
|
||||||
|
archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
waterArchiveDayRawDatas.Add(archiveDayRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
{
|
||||||
|
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult);
|
||||||
|
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
waterArchiveDayRawDatas.AddRange(ArrangeRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waterArchiveDayRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveDayRawDatas);
|
||||||
|
}
|
||||||
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveDayRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion 天歸檔補償
|
||||||
|
|
||||||
|
#region 週歸檔補償
|
||||||
|
//取得所有須補償的設備資訊
|
||||||
|
targetTable = "archive_electric_meter_week";
|
||||||
|
var sql_error_week = string.Format(sql_error_format, targetTable);
|
||||||
|
var eletric_error_weeks = await backgroundServiceRepository.GetAllAsync<ArchiveElectricMeter>(sql_error_week, new { RepeatTimes = repeatTimes });
|
||||||
|
List<Dictionary<string, object>> electricArchiveWeekRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
if (eletric_error_weeks.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var error_week in eletric_error_weeks)
|
||||||
|
{
|
||||||
|
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
deviceNumberPoint.DeviceNumber = error_week.Device_number;
|
||||||
|
deviceNumberPoint.Point = error_week.Point;
|
||||||
|
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_week.Device_number, error_week.Point);
|
||||||
|
|
||||||
|
var startTimestamp = string.Format("{0}+08:00", error_week.Start_timestamp.Replace(" ", "T"));
|
||||||
|
var endTimestamp = string.Format("{0}+08:00", error_week.End_timestamp.Replace(" ", "T"));
|
||||||
|
|
||||||
|
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
<abstime name='start' val='{startTimestamp}' />
|
||||||
|
<abstime name='end' val='{endTimestamp}' />
|
||||||
|
<reltime name='interval' val = 'PT7D' />
|
||||||
|
</obj>";
|
||||||
|
|
||||||
|
HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
//HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
archiveWeekRequest.Method = "POST";
|
||||||
|
archiveWeekRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
archiveWeekRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
using (Stream reqStream = archiveWeekRequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse archiveWeekResponse = (HttpWebResponse)archiveWeekRequest.GetResponse();
|
||||||
|
var archiveWeekResponseContent = new StreamReader(archiveWeekResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
xmlDocument.LoadXml(archiveWeekResponseContent);
|
||||||
|
string archiveWeekJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
JObject archiveWeekJsonResult = (JObject)JsonConvert.DeserializeObject(archiveWeekJson);
|
||||||
|
|
||||||
|
if (archiveWeekJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
{
|
||||||
|
Dictionary<string, object> archiveWeekRawData = new Dictionary<string, object>();
|
||||||
|
archiveWeekRawData.Add("@device_number", error_week.Device_number);
|
||||||
|
archiveWeekRawData.Add("@point", error_week.Point);
|
||||||
|
archiveWeekRawData.Add("@start_timestamp", DateTime.Parse(error_week.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveWeekRawData.Add("@end_timestamp", DateTime.Parse(error_week.End_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveWeekRawData.Add("@is_complete", 0);
|
||||||
|
archiveWeekRawData.Add("@repeat_times", ++error_week.Repeat_times);
|
||||||
|
archiveWeekRawData.Add("@fail_reason", archiveWeekJson);
|
||||||
|
|
||||||
|
archiveWeekRawData.Add("@count_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@min_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@max_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@avg_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@sum_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
electricArchiveWeekRawDatas.Add(archiveWeekRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archiveWeekJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
{
|
||||||
|
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveWeekJsonResult);
|
||||||
|
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
electricArchiveWeekRawDatas.AddRange(ArrangeRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (electricArchiveWeekRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetTable = "archive_water_meter_week";
|
||||||
|
sql_error_week = string.Format(sql_error_format, targetTable);
|
||||||
|
var water_error_weeks = await backgroundServiceRepository.GetAllAsync<ArchiveElectricMeter>(sql_error_week, new { RepeatTimes = repeatTimes });
|
||||||
|
List<Dictionary<string, object>> waterArchiveWeekRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
if (water_error_weeks.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var error_week in water_error_weeks)
|
||||||
|
{
|
||||||
|
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
deviceNumberPoint.DeviceNumber = error_week.Device_number;
|
||||||
|
deviceNumberPoint.Point = error_week.Point;
|
||||||
|
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_week.Device_number, error_week.Point);
|
||||||
|
|
||||||
|
var startTimestamp = string.Format("{0}+08:00", error_week.Start_timestamp.Replace(" ", "T"));
|
||||||
|
var endTimestamp = string.Format("{0}+08:00", error_week.End_timestamp.Replace(" ", "T"));
|
||||||
|
|
||||||
|
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
<abstime name='start' val='{startTimestamp}' />
|
||||||
|
<abstime name='end' val='{endTimestamp}' />
|
||||||
|
<reltime name='interval' val = 'PT7D' />
|
||||||
|
</obj>";
|
||||||
|
|
||||||
|
HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
//HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
archiveWeekRequest.Method = "POST";
|
||||||
|
archiveWeekRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
archiveWeekRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
using (Stream reqStream = archiveWeekRequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse archiveWeekResponse = (HttpWebResponse)archiveWeekRequest.GetResponse();
|
||||||
|
var archiveWeekResponseContent = new StreamReader(archiveWeekResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
xmlDocument.LoadXml(archiveWeekResponseContent);
|
||||||
|
string archiveWeekJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
JObject archiveWeekJsonResult = (JObject)JsonConvert.DeserializeObject(archiveWeekJson);
|
||||||
|
|
||||||
|
if (archiveWeekJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
{
|
||||||
|
Dictionary<string, object> archiveWeekRawData = new Dictionary<string, object>();
|
||||||
|
archiveWeekRawData.Add("@device_number", error_week.Device_number);
|
||||||
|
archiveWeekRawData.Add("@point", error_week.Point);
|
||||||
|
archiveWeekRawData.Add("@start_timestamp", DateTime.Parse(error_week.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveWeekRawData.Add("@end_timestamp", DateTime.Parse(error_week.End_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveWeekRawData.Add("@is_complete", 0);
|
||||||
|
archiveWeekRawData.Add("@repeat_times", ++error_week.Repeat_times);
|
||||||
|
archiveWeekRawData.Add("@fail_reason", archiveWeekJson);
|
||||||
|
|
||||||
|
archiveWeekRawData.Add("@count_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@min_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@max_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@avg_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@sum_rawdata", 0);
|
||||||
|
archiveWeekRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
waterArchiveWeekRawDatas.Add(archiveWeekRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archiveWeekJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
{
|
||||||
|
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveWeekJsonResult);
|
||||||
|
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
waterArchiveWeekRawDatas.AddRange(ArrangeRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waterArchiveWeekRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion 週歸檔補償
|
||||||
|
|
||||||
|
#region 月歸檔補償
|
||||||
|
//取得所有須補償的設備資訊
|
||||||
|
targetTable = "archive_electric_meter_month";
|
||||||
|
var sql_error_month = string.Format(sql_error_format, targetTable);
|
||||||
|
var electric_error_months = await backgroundServiceRepository.GetAllAsync<ArchiveElectricMeter>(sql_error_month, new { RepeatTimes = repeatTimes });
|
||||||
|
List<Dictionary<string, object>> electricArchiveMonthRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
if (electric_error_months.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var error_month in electric_error_months)
|
||||||
|
{
|
||||||
|
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
deviceNumberPoint.DeviceNumber = error_month.Device_number;
|
||||||
|
deviceNumberPoint.Point = error_month.Point;
|
||||||
|
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_month.Device_number, error_month.Point);
|
||||||
|
|
||||||
|
var startTimestamp = string.Format("{0}+08:00", error_month.Start_timestamp.Replace(" ", "T"));
|
||||||
|
var endTimestamp = string.Format("{0}+08:00", error_month.End_timestamp.Replace(" ", "T"));
|
||||||
|
|
||||||
|
var startDateTime = Convert.ToDateTime(error_month.Start_timestamp);
|
||||||
|
var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month);
|
||||||
|
|
||||||
|
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
<abstime name='start' val='{startTimestamp}' />
|
||||||
|
<abstime name='end' val='{endTimestamp}' />
|
||||||
|
<reltime name='interval' val = 'PT{dayInMonth}D' />
|
||||||
|
</obj>";
|
||||||
|
|
||||||
|
HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
//HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
archiveMonthRequest.Method = "POST";
|
||||||
|
archiveMonthRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
archiveMonthRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
using (Stream reqStream = archiveMonthRequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse archiveMonthResponse = (HttpWebResponse)archiveMonthRequest.GetResponse();
|
||||||
|
var archiveMonthResponseContent = new StreamReader(archiveMonthResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
xmlDocument.LoadXml(archiveMonthResponseContent);
|
||||||
|
string archiveMonthJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
JObject archiveMonthJsonResult = (JObject)JsonConvert.DeserializeObject(archiveMonthJson);
|
||||||
|
|
||||||
|
if (archiveMonthJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
{
|
||||||
|
Dictionary<string, object> archiveMonthRawData = new Dictionary<string, object>();
|
||||||
|
archiveMonthRawData.Add("@device_number", error_month.Device_number);
|
||||||
|
archiveMonthRawData.Add("@point", error_month.Point);
|
||||||
|
archiveMonthRawData.Add("@start_timestamp", DateTime.Parse(error_month.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveMonthRawData.Add("@end_timestamp", DateTime.Parse(error_month.End_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveMonthRawData.Add("@is_complete", 0);
|
||||||
|
archiveMonthRawData.Add("@repeat_times", ++error_month.Repeat_times);
|
||||||
|
archiveMonthRawData.Add("@fail_reason", archiveMonthJson);
|
||||||
|
|
||||||
|
archiveMonthRawData.Add("@count_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@min_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@max_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@avg_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@sum_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
electricArchiveMonthRawDatas.Add(archiveMonthRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
{
|
||||||
|
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult);
|
||||||
|
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
electricArchiveMonthRawDatas.AddRange(ArrangeRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (electricArchiveMonthRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
|
await backgroundServiceRepository.ExecuteSql(MYsql_update_format, electricArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetTable = "archive_electric_meter_month";
|
||||||
|
sql_error_month = string.Format(sql_error_format, targetTable);
|
||||||
|
var water_error_months = await backgroundServiceRepository.GetAllAsync<ArchiveElectricMeter>(sql_error_month, new { RepeatTimes = repeatTimes });
|
||||||
|
List<Dictionary<string, object>> waterArchiveMonthRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
if (water_error_months.Count() > 0)
|
||||||
|
{
|
||||||
|
foreach (var error_month in water_error_months)
|
||||||
|
{
|
||||||
|
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
|
||||||
|
deviceNumberPoint.DeviceNumber = error_month.Device_number;
|
||||||
|
deviceNumberPoint.Point = error_month.Point;
|
||||||
|
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_month.Device_number, error_month.Point);
|
||||||
|
|
||||||
|
var startTimestamp = string.Format("{0}+08:00", error_month.Start_timestamp.Replace(" ", "T"));
|
||||||
|
var endTimestamp = string.Format("{0}+08:00", error_month.End_timestamp.Replace(" ", "T"));
|
||||||
|
|
||||||
|
var startDateTime = Convert.ToDateTime(error_month.Start_timestamp);
|
||||||
|
var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month);
|
||||||
|
|
||||||
|
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
|
||||||
|
<abstime name='start' val='{startTimestamp}' />
|
||||||
|
<abstime name='end' val='{endTimestamp}' />
|
||||||
|
<reltime name='interval' val = 'PT{dayInMonth}D' />
|
||||||
|
</obj>";
|
||||||
|
|
||||||
|
HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
|
||||||
|
//HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
|
||||||
|
archiveMonthRequest.Method = "POST";
|
||||||
|
archiveMonthRequest.Headers.Add("Authorization", "Basic " + encoded);
|
||||||
|
archiveMonthRequest.PreAuthenticate = true;
|
||||||
|
|
||||||
|
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
|
||||||
|
using (Stream reqStream = archiveMonthRequest.GetRequestStream())
|
||||||
|
{
|
||||||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse archiveMonthResponse = (HttpWebResponse)archiveMonthRequest.GetResponse();
|
||||||
|
var archiveMonthResponseContent = new StreamReader(archiveMonthResponse.GetResponseStream()).ReadToEnd();
|
||||||
|
|
||||||
|
xmlDocument.LoadXml(archiveMonthResponseContent);
|
||||||
|
string archiveMonthJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
||||||
|
JObject archiveMonthJsonResult = (JObject)JsonConvert.DeserializeObject(archiveMonthJson);
|
||||||
|
|
||||||
|
if (archiveMonthJsonResult.ContainsKey("err")) //抓取錯誤
|
||||||
|
{
|
||||||
|
Dictionary<string, object> archiveMonthRawData = new Dictionary<string, object>();
|
||||||
|
archiveMonthRawData.Add("@device_number", error_month.Device_number);
|
||||||
|
archiveMonthRawData.Add("@point", error_month.Point);
|
||||||
|
archiveMonthRawData.Add("@start_timestamp", DateTime.Parse(error_month.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveMonthRawData.Add("@end_timestamp", DateTime.Parse(error_month.End_timestamp, System.Globalization.CultureInfo.CurrentCulture));
|
||||||
|
archiveMonthRawData.Add("@is_complete", 0);
|
||||||
|
archiveMonthRawData.Add("@repeat_times", ++error_month.Repeat_times);
|
||||||
|
archiveMonthRawData.Add("@fail_reason", archiveMonthJson);
|
||||||
|
|
||||||
|
archiveMonthRawData.Add("@count_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@min_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@max_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@avg_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@sum_rawdata", 0);
|
||||||
|
archiveMonthRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
waterArchiveMonthRawDatas.Add(archiveMonthRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
||||||
|
{
|
||||||
|
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult);
|
||||||
|
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
waterArchiveMonthRawDatas.AddRange(ArrangeRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waterArchiveMonthRawDatas.Count() > 0)
|
||||||
|
{
|
||||||
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
|
await backgroundServiceRepository.ExecuteSql(MYsql_update_format, waterArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion 月歸檔補償
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Dictionary<string, object>> ArrangeRawData(DeviceNumberPoint deviceNumberPoint, JObject jsonResult)
|
||||||
|
{
|
||||||
|
List<Dictionary<string, object>> arrangeRawDatas = new List<Dictionary<string, object>>();
|
||||||
|
var histories = jsonResult["obj"]["list"];
|
||||||
|
var rawdateCount = Convert.ToInt32(jsonResult["obj"]["int"]["@val"].ToString());
|
||||||
|
|
||||||
|
if (rawdateCount == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (histories != null && histories.HasValues)
|
||||||
|
{
|
||||||
|
if (rawdateCount > 1)
|
||||||
|
{ //多筆資料
|
||||||
|
foreach (var history in histories)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
|
||||||
|
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
|
||||||
|
arrangeRawData.Add("@point", deviceNumberPoint.Point);
|
||||||
|
|
||||||
|
//時間
|
||||||
|
if (history["abstime"] != null && history["abstime"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var abstime in history["abstime"])
|
||||||
|
{
|
||||||
|
var name = abstime["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "start":
|
||||||
|
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
arrangeRawData.Add("@start_timestamp", startTimstamp);
|
||||||
|
break;
|
||||||
|
case "end":
|
||||||
|
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
arrangeRawData.Add("@end_timestamp", endTimstamp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//區間內資料筆數
|
||||||
|
if (history["int"] != null && history["int"].HasValues)
|
||||||
|
{
|
||||||
|
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@count_rawdata", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
//整合數值(最大、最小、平均、總和)
|
||||||
|
if (history["real"] != null && history["real"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var real in history["real"])
|
||||||
|
{
|
||||||
|
var name = real["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "min":
|
||||||
|
var min = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@min_rawdata", min);
|
||||||
|
break;
|
||||||
|
case "max":
|
||||||
|
var max = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@max_rawdata", max);
|
||||||
|
break;
|
||||||
|
case "avg":
|
||||||
|
var avg = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@avg_rawdata", avg);
|
||||||
|
break;
|
||||||
|
case "sum":
|
||||||
|
var sum = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
|
||||||
|
arrangeRawData.Add("@sum_rawdata", sum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arrangeRawData.Add("@is_complete", 1);
|
||||||
|
arrangeRawData.Add("@repeat_times", 0);
|
||||||
|
arrangeRawData.Add("@fail_reason", null);
|
||||||
|
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
arrangeRawDatas.Add(arrangeRawData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //單筆資料
|
||||||
|
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
|
||||||
|
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
|
||||||
|
arrangeRawData.Add("@point", deviceNumberPoint.Point);
|
||||||
|
|
||||||
|
//時間
|
||||||
|
if (histories["obj"]["abstime"] != null && histories["obj"]["abstime"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var abstime in histories["obj"]["abstime"])
|
||||||
|
{
|
||||||
|
var name = abstime["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "start":
|
||||||
|
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
arrangeRawData.Add("@start_timestamp", startTimstamp);
|
||||||
|
break;
|
||||||
|
case "end":
|
||||||
|
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
arrangeRawData.Add("@end_timestamp", endTimstamp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//區間內資料筆數
|
||||||
|
if (histories["obj"]["int"] != null && histories["obj"]["int"].HasValues)
|
||||||
|
{
|
||||||
|
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@count_rawdata", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
//整合數值(最大、最小、平均、總和)
|
||||||
|
if (histories["obj"]["real"] != null && histories["obj"]["real"].HasValues)
|
||||||
|
{
|
||||||
|
foreach (var real in histories["obj"]["real"])
|
||||||
|
{
|
||||||
|
var name = real["@name"].ToString();
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case "min":
|
||||||
|
var min = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@min_rawdata", min);
|
||||||
|
break;
|
||||||
|
case "max":
|
||||||
|
var max = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@max_rawdata", max);
|
||||||
|
break;
|
||||||
|
case "avg":
|
||||||
|
var avg = Convert.ToDecimal(real["@val"].ToString());
|
||||||
|
arrangeRawData.Add("@avg_rawdata", avg);
|
||||||
|
break;
|
||||||
|
case "sum":
|
||||||
|
var sum = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
|
||||||
|
arrangeRawData.Add("@sum_rawdata", sum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arrangeRawData.Add("@is_complete", 1);
|
||||||
|
arrangeRawData.Add("@repeat_times", 0);
|
||||||
|
arrangeRawData.Add("@fail_reason", null);
|
||||||
|
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
arrangeRawDatas.Add(arrangeRawData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arrangeRawDatas;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
640
Backend/Services/Implement/Quicktype.cs
Normal file
640
Backend/Services/Implement/Quicktype.cs
Normal file
@ -0,0 +1,640 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
// <auto-generated />
|
||||||
|
//
|
||||||
|
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||||
|
//
|
||||||
|
// using QuickType;
|
||||||
|
//
|
||||||
|
// var welcome = Welcome.FromJson(jsonString);
|
||||||
|
|
||||||
|
namespace QuickType
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
[JsonProperty("success")]
|
||||||
|
[JsonConverter(typeof(ParseStringConverter))]
|
||||||
|
public bool Success { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("result")]
|
||||||
|
public Result Result { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("records")]
|
||||||
|
public Records Records { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Records
|
||||||
|
{
|
||||||
|
[JsonProperty("datasetDescription")]
|
||||||
|
public DatasetDescription DatasetDescription { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("Earthquake")]
|
||||||
|
public Earthquake[] Earthquake { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Earthquake
|
||||||
|
{
|
||||||
|
[JsonProperty("EarthquakeNo")]
|
||||||
|
public long EarthquakeNo { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ReportType")]
|
||||||
|
public DatasetDescription ReportType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ReportColor")]
|
||||||
|
public ReportColor ReportColor { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ReportContent")]
|
||||||
|
public string ReportContent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ReportImageURI")]
|
||||||
|
public Uri ReportImageUri { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ReportRemark")]
|
||||||
|
public ReportRemark ReportRemark { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("Web")]
|
||||||
|
public Uri Web { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ShakemapImageURI")]
|
||||||
|
public Uri ShakemapImageUri { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("EarthquakeInfo")]
|
||||||
|
public EarthquakeInfo EarthquakeInfo { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("Intensity")]
|
||||||
|
public Intensity Intensity { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EarthquakeInfo
|
||||||
|
{
|
||||||
|
[JsonProperty("OriginTime")]
|
||||||
|
public DateTimeOffset OriginTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("Source")]
|
||||||
|
public Source Source { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("FocalDepth")]
|
||||||
|
public double FocalDepth { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("Epicenter")]
|
||||||
|
public Epicenter Epicenter { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("EarthquakeMagnitude")]
|
||||||
|
public EarthquakeMagnitude EarthquakeMagnitude { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EarthquakeMagnitude
|
||||||
|
{
|
||||||
|
[JsonProperty("MagnitudeType")]
|
||||||
|
public MagnitudeType MagnitudeType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("MagnitudeValue")]
|
||||||
|
public double MagnitudeValue { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Epicenter
|
||||||
|
{
|
||||||
|
[JsonProperty("Location")]
|
||||||
|
public string Location { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("EpicenterLatitude")]
|
||||||
|
public double EpicenterLatitude { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("EpicenterLongitude")]
|
||||||
|
public double EpicenterLongitude { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Intensity
|
||||||
|
{
|
||||||
|
[JsonProperty("ShakingArea")]
|
||||||
|
public ShakingArea[] ShakingArea { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class ShakingArea
|
||||||
|
{
|
||||||
|
[JsonProperty("AreaDesc")]
|
||||||
|
public string AreaDesc { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("CountyName")]
|
||||||
|
public string CountyName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("InfoStatus", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public InfoStatus? InfoStatus { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("AreaIntensity")]
|
||||||
|
public AreaIntensityEnum AreaIntensity { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("EqStation")]
|
||||||
|
public EqStation[] EqStation { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EqStation
|
||||||
|
{
|
||||||
|
[JsonProperty("pga", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public Pga Pga { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("pgv", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public Pga Pgv { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("StationName")]
|
||||||
|
public string StationName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("StationID")]
|
||||||
|
public string StationId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("InfoStatus", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public InfoStatus? InfoStatus { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("BackAzimuth")]
|
||||||
|
public double BackAzimuth { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("EpicenterDistance")]
|
||||||
|
public double EpicenterDistance { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("SeismicIntensity")]
|
||||||
|
public AreaIntensityEnum SeismicIntensity { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("StationLatitude")]
|
||||||
|
public double StationLatitude { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("StationLongitude")]
|
||||||
|
public double StationLongitude { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("WaveImageURI", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public Uri WaveImageUri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Pga
|
||||||
|
{
|
||||||
|
[JsonProperty("unit")]
|
||||||
|
public Unit Unit { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("EWComponent")]
|
||||||
|
public double EwComponent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("NSComponent")]
|
||||||
|
public double NsComponent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("VComponent")]
|
||||||
|
public double VComponent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("IntScaleValue")]
|
||||||
|
public double IntScaleValue { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Result
|
||||||
|
{
|
||||||
|
[JsonProperty("resource_id")]
|
||||||
|
public string ResourceId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("fields")]
|
||||||
|
public Field[] Fields { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Field
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("type")]
|
||||||
|
public TypeEnum Type { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DatasetDescription { 地震報告 };
|
||||||
|
|
||||||
|
public enum MagnitudeType { 芮氏規模 };
|
||||||
|
|
||||||
|
public enum Source { 中央氣象局 };
|
||||||
|
|
||||||
|
public enum AreaIntensityEnum { The1級, The2級, The3級, The4級 };
|
||||||
|
|
||||||
|
public enum InfoStatus { Observe };
|
||||||
|
|
||||||
|
public enum Unit { Gal, Kine };
|
||||||
|
|
||||||
|
public enum ReportColor { 綠色 };
|
||||||
|
|
||||||
|
public enum ReportRemark { 本報告係中央氣象局地震觀測網即時地震資料地震速報之結果 };
|
||||||
|
|
||||||
|
public enum TypeEnum { Float, Integer, String, Timestamp };
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serialize
|
||||||
|
{
|
||||||
|
public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Converter
|
||||||
|
{
|
||||||
|
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||||
|
DateParseHandling = DateParseHandling.None,
|
||||||
|
Converters =
|
||||||
|
{
|
||||||
|
MagnitudeTypeConverter.Singleton,
|
||||||
|
SourceConverter.Singleton,
|
||||||
|
AreaIntensityEnumConverter.Singleton,
|
||||||
|
InfoStatusConverter.Singleton,
|
||||||
|
UnitConverter.Singleton,
|
||||||
|
ReportColorConverter.Singleton,
|
||||||
|
ReportRemarkConverter.Singleton,
|
||||||
|
DatasetDescriptionConverter.Singleton,
|
||||||
|
TypeEnumConverter.Singleton,
|
||||||
|
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MagnitudeTypeConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(MagnitudeType) || t == typeof(MagnitudeType?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
if (value == "芮氏規模")
|
||||||
|
{
|
||||||
|
return MagnitudeType.芮氏規模;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type MagnitudeType");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (MagnitudeType)untypedValue;
|
||||||
|
if (value == MagnitudeType.芮氏規模)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, "芮氏規模");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type MagnitudeType");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly MagnitudeTypeConverter Singleton = new MagnitudeTypeConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class SourceConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(Source) || t == typeof(Source?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
if (value == "中央氣象局")
|
||||||
|
{
|
||||||
|
return Source.中央氣象局;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type Source");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (Source)untypedValue;
|
||||||
|
if (value == Source.中央氣象局)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, "中央氣象局");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type Source");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly SourceConverter Singleton = new SourceConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class AreaIntensityEnumConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(AreaIntensityEnum) || t == typeof(AreaIntensityEnum?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case "1級":
|
||||||
|
return AreaIntensityEnum.The1級;
|
||||||
|
case "2級":
|
||||||
|
return AreaIntensityEnum.The2級;
|
||||||
|
case "3級":
|
||||||
|
return AreaIntensityEnum.The3級;
|
||||||
|
case "4級":
|
||||||
|
return AreaIntensityEnum.The4級;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type AreaIntensityEnum");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (AreaIntensityEnum)untypedValue;
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case AreaIntensityEnum.The1級:
|
||||||
|
serializer.Serialize(writer, "1級");
|
||||||
|
return;
|
||||||
|
case AreaIntensityEnum.The2級:
|
||||||
|
serializer.Serialize(writer, "2級");
|
||||||
|
return;
|
||||||
|
case AreaIntensityEnum.The3級:
|
||||||
|
serializer.Serialize(writer, "3級");
|
||||||
|
return;
|
||||||
|
case AreaIntensityEnum.The4級:
|
||||||
|
serializer.Serialize(writer, "4級");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type AreaIntensityEnum");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly AreaIntensityEnumConverter Singleton = new AreaIntensityEnumConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class InfoStatusConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(InfoStatus) || t == typeof(InfoStatus?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
if (value == "observe")
|
||||||
|
{
|
||||||
|
return InfoStatus.Observe;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type InfoStatus");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (InfoStatus)untypedValue;
|
||||||
|
if (value == InfoStatus.Observe)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, "observe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type InfoStatus");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly InfoStatusConverter Singleton = new InfoStatusConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class UnitConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(Unit) || t == typeof(Unit?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case "gal":
|
||||||
|
return Unit.Gal;
|
||||||
|
case "kine":
|
||||||
|
return Unit.Kine;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type Unit");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (Unit)untypedValue;
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case Unit.Gal:
|
||||||
|
serializer.Serialize(writer, "gal");
|
||||||
|
return;
|
||||||
|
case Unit.Kine:
|
||||||
|
serializer.Serialize(writer, "kine");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type Unit");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly UnitConverter Singleton = new UnitConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ReportColorConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(ReportColor) || t == typeof(ReportColor?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
if (value == "綠色")
|
||||||
|
{
|
||||||
|
return ReportColor.綠色;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type ReportColor");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (ReportColor)untypedValue;
|
||||||
|
if (value == ReportColor.綠色)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, "綠色");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type ReportColor");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly ReportColorConverter Singleton = new ReportColorConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ReportRemarkConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(ReportRemark) || t == typeof(ReportRemark?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
if (value == "本報告係中央氣象局地震觀測網即時地震資料地震速報之結果。")
|
||||||
|
{
|
||||||
|
return ReportRemark.本報告係中央氣象局地震觀測網即時地震資料地震速報之結果;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type ReportRemark");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (ReportRemark)untypedValue;
|
||||||
|
if (value == ReportRemark.本報告係中央氣象局地震觀測網即時地震資料地震速報之結果)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, "本報告係中央氣象局地震觀測網即時地震資料地震速報之結果。");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type ReportRemark");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly ReportRemarkConverter Singleton = new ReportRemarkConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DatasetDescriptionConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(DatasetDescription) || t == typeof(DatasetDescription?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
if (value == "地震報告")
|
||||||
|
{
|
||||||
|
return DatasetDescription.地震報告;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type DatasetDescription");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (DatasetDescription)untypedValue;
|
||||||
|
if (value == DatasetDescription.地震報告)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, "地震報告");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type DatasetDescription");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DatasetDescriptionConverter Singleton = new DatasetDescriptionConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class TypeEnumConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(TypeEnum) || t == typeof(TypeEnum?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case "Float":
|
||||||
|
return TypeEnum.Float;
|
||||||
|
case "Integer":
|
||||||
|
return TypeEnum.Integer;
|
||||||
|
case "String":
|
||||||
|
return TypeEnum.String;
|
||||||
|
case "Timestamp":
|
||||||
|
return TypeEnum.Timestamp;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type TypeEnum");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (TypeEnum)untypedValue;
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case TypeEnum.Float:
|
||||||
|
serializer.Serialize(writer, "Float");
|
||||||
|
return;
|
||||||
|
case TypeEnum.Integer:
|
||||||
|
serializer.Serialize(writer, "Integer");
|
||||||
|
return;
|
||||||
|
case TypeEnum.String:
|
||||||
|
serializer.Serialize(writer, "String");
|
||||||
|
return;
|
||||||
|
case TypeEnum.Timestamp:
|
||||||
|
serializer.Serialize(writer, "Timestamp");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type TypeEnum");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly TypeEnumConverter Singleton = new TypeEnumConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ParseStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(bool) || t == typeof(bool?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
bool b;
|
||||||
|
if (Boolean.TryParse(value, out b))
|
||||||
|
{
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type bool");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (bool)untypedValue;
|
||||||
|
var boolString = value ? "true" : "false";
|
||||||
|
serializer.Serialize(writer, boolString);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly ParseStringConverter Singleton = new ParseStringConverter();
|
||||||
|
}
|
||||||
|
}
|
213
Backend/Services/Implement/RainApi.cs
Normal file
213
Backend/Services/Implement/RainApi.cs
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
// <auto-generated />
|
||||||
|
//
|
||||||
|
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||||
|
//
|
||||||
|
// using QuickType;
|
||||||
|
//
|
||||||
|
// var welcome = Welcome.FromJson(jsonString);
|
||||||
|
|
||||||
|
namespace RainApi
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
[JsonProperty("?xml")]
|
||||||
|
public Xml Xml { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("alert")]
|
||||||
|
public Alert Alert { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Alert
|
||||||
|
{
|
||||||
|
[JsonProperty("@xmlns")]
|
||||||
|
public string Xmlns { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("identifier")]
|
||||||
|
public string Identifier { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sender")]
|
||||||
|
public string Sender { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sent")]
|
||||||
|
public DateTimeOffset Sent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("status")]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("msgType")]
|
||||||
|
public string MsgType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("scope")]
|
||||||
|
public string Scope { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("references")]
|
||||||
|
public string References { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("info")]
|
||||||
|
public Info Info { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Info
|
||||||
|
{
|
||||||
|
[JsonProperty("language")]
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("category")]
|
||||||
|
public string Category { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("event")]
|
||||||
|
public string Event { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("urgency")]
|
||||||
|
public string Urgency { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("severity")]
|
||||||
|
public string Severity { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("certainty")]
|
||||||
|
public string Certainty { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("eventCode")]
|
||||||
|
public EventCode EventCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("effective")]
|
||||||
|
public DateTimeOffset Effective { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("onset")]
|
||||||
|
public DateTimeOffset Onset { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("expires")]
|
||||||
|
public DateTimeOffset Expires { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("senderName")]
|
||||||
|
public string SenderName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("headline")]
|
||||||
|
public string Headline { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("instruction")]
|
||||||
|
public string Instruction { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("web")]
|
||||||
|
public Uri Web { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("parameter")]
|
||||||
|
public EventCode Parameter { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("area")]
|
||||||
|
public List<Area> Area { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Area
|
||||||
|
{
|
||||||
|
[JsonProperty("areaDesc")]
|
||||||
|
public string AreaDesc { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("geocode")]
|
||||||
|
public EventCode Geocode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EventCode
|
||||||
|
{
|
||||||
|
[JsonProperty("valueName")]
|
||||||
|
public string ValueName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("value")]
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Xml
|
||||||
|
{
|
||||||
|
[JsonProperty("@version")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("@encoding")]
|
||||||
|
public string Encoding { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ValueName { AlertTitle, ProfileCapTwpEvent10, TaiwanGeocode103 };
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serialize
|
||||||
|
{
|
||||||
|
public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Converter
|
||||||
|
{
|
||||||
|
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||||
|
DateParseHandling = DateParseHandling.None,
|
||||||
|
Converters =
|
||||||
|
{
|
||||||
|
ValueNameConverter.Singleton,
|
||||||
|
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ValueNameConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(ValueName) || t == typeof(ValueName?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case "Taiwan_Geocode_103":
|
||||||
|
return ValueName.TaiwanGeocode103;
|
||||||
|
case "alert_title":
|
||||||
|
return ValueName.AlertTitle;
|
||||||
|
case "profile:CAP-TWP:Event:1.0":
|
||||||
|
return ValueName.ProfileCapTwpEvent10;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type ValueName");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (ValueName)untypedValue;
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case ValueName.TaiwanGeocode103:
|
||||||
|
serializer.Serialize(writer, "Taiwan_Geocode_103");
|
||||||
|
return;
|
||||||
|
case ValueName.AlertTitle:
|
||||||
|
serializer.Serialize(writer, "alert_title");
|
||||||
|
return;
|
||||||
|
case ValueName.ProfileCapTwpEvent10:
|
||||||
|
serializer.Serialize(writer, "profile:CAP-TWP:Event:1.0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type ValueName");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly ValueNameConverter Singleton = new ValueNameConverter();
|
||||||
|
}
|
||||||
|
}
|
81
Backend/Services/Implement/SendEmailService.cs
Normal file
81
Backend/Services/Implement/SendEmailService.cs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Backend.Models;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Mail;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BackendWorkerService.Services.Interface;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace BackendWorkerService.Services.Implement
|
||||||
|
{
|
||||||
|
public class SendEmailService : ISendEmailService
|
||||||
|
{
|
||||||
|
private readonly ILogger<SendEmailService> logger;
|
||||||
|
private readonly IOptions<SMTPConfig> _options;
|
||||||
|
|
||||||
|
private SMTPConfig smtp;
|
||||||
|
|
||||||
|
public SendEmailService(ILogger<SendEmailService> logger, IOptions<SMTPConfig> options)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
smtp = options.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Send(int id, List<string> recipientEmails, string subject, string content)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【SendEmailSMSService】【Email開始寄送】[任務編號]:{0}", id);
|
||||||
|
|
||||||
|
MailMessage MyMail = new MailMessage();
|
||||||
|
|
||||||
|
MyMail.SubjectEncoding = System.Text.Encoding.UTF8;//郵件標題編碼
|
||||||
|
MyMail.BodyEncoding = System.Text.Encoding.UTF8; //郵件內容編碼
|
||||||
|
MyMail.IsBodyHtml = true; //是否使用html格式
|
||||||
|
|
||||||
|
var mailFrom = $"FIC IBMS管理系統通知 <{smtp.UserName}>";
|
||||||
|
|
||||||
|
MyMail.From = new System.Net.Mail.MailAddress(mailFrom); //寄件人
|
||||||
|
foreach (var email in recipientEmails)
|
||||||
|
{
|
||||||
|
MyMail.To.Add(email); //設定收件者Email
|
||||||
|
}
|
||||||
|
|
||||||
|
MyMail.Subject = subject; //主題
|
||||||
|
MyMail.Body = content; //設定信件內容
|
||||||
|
|
||||||
|
//讀取 SMTP Config
|
||||||
|
SmtpClient MySMTP = new SmtpClient(smtp.Host, smtp.Port);
|
||||||
|
MySMTP.EnableSsl = smtp.EnableSsl;
|
||||||
|
MySMTP.Credentials = new System.Net.NetworkCredential(smtp.UserName, smtp.Password);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MySMTP.Send(MyMail);
|
||||||
|
MySMTP.Dispose();
|
||||||
|
MyMail.Dispose(); //釋放資源
|
||||||
|
|
||||||
|
logger.LogInformation("【SendEmailSMSService】【Email寄送成功】[任務編號]:{0}", id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【SendEmailSMSService】【Email寄送失敗】[任務編號]:{0}", id);
|
||||||
|
logger.LogError("【SendEmailSMSService】【Email寄送失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【SendEmailSMSService】【Email寄送失敗】[任務編號]:{0}", id);
|
||||||
|
logger.LogError("【SendEmailSMSService】【Email寄送失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
throw;
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
Backend/Services/Implement/SendLineNotifyService.cs
Normal file
54
Backend/Services/Implement/SendLineNotifyService.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using BackendWorkerService.Services.Interface;
|
||||||
|
using Microsoft. Extensions.Logging;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BackendWorkerService.Services.Implement
|
||||||
|
{
|
||||||
|
class SendLineNotifyService: ISendLineNotifyService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ILogger<SendLineNotifyService> logger;
|
||||||
|
|
||||||
|
public SendLineNotifyService(ILogger<SendLineNotifyService> logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Send(int id, string lineToken, string message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInformation("【SendLineNotifyService】【Line Notify開始發送】[任務編號]:{0}", id);
|
||||||
|
HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create("https://notify-api.line.me/api/notify?message=" + message);
|
||||||
|
Postrequest.Method = "POST";
|
||||||
|
Postrequest.Headers.Add("Authorization", "Bearer " + lineToken);
|
||||||
|
Postrequest.PreAuthenticate = true;
|
||||||
|
HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
|
||||||
|
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
|
||||||
|
var final = JObject.Parse(responseString);
|
||||||
|
var get = final["status"].ToString();
|
||||||
|
if (get != "200")
|
||||||
|
{
|
||||||
|
logger.LogError("【SendLineNotifyService】【Line Notify發送失敗】[任務編號]:{0}", id);
|
||||||
|
logger.LogError("【SendLineNotifyService】【Line Notify發送失敗】[失敗內容]:{0}", responseString);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation("【SendLineNotifyService】【Line Notify發送成功】[任務編號]:{0}", id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【SendLineNotifyService】【Line Notify發送失敗】[任務編號]:{0}", id);
|
||||||
|
logger.LogError("【SendLineNotifyService】【Line Notify發送失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
throw;
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
Backend/Services/Implement/SendSMSService.cs
Normal file
84
Backend/Services/Implement/SendSMSService.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using Backend.Models;
|
||||||
|
using BackendWorkerService.Services.Interface;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace BackendWorkerService.Services.Implement
|
||||||
|
{
|
||||||
|
class SendSMSService : ISendSMSService
|
||||||
|
{
|
||||||
|
private readonly ILogger<SendSMSService> logger;
|
||||||
|
private readonly IOptions<SMSConfig> _options;
|
||||||
|
|
||||||
|
private SMSConfig sms;
|
||||||
|
|
||||||
|
public SendSMSService(ILogger<SendSMSService> logger, IOptions<SMSConfig> options)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
sms = options.Value;
|
||||||
|
sms.Encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(sms.UserName + ":" + sms.Password));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Send(int id, string phone, string content)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogError("【SendSMSService】【SMS開始寄送】[任務編號]:{0}", id);
|
||||||
|
//設定傳送的Request
|
||||||
|
HttpWebRequest Postrequest = (HttpWebRequest)WebRequest.Create(sms.Api);
|
||||||
|
Postrequest.Method = "POST";
|
||||||
|
Postrequest.Headers.Add("Authorization", "Basic " + sms.Encoded);
|
||||||
|
Postrequest.PreAuthenticate = true;
|
||||||
|
using (var streamWriter = new StreamWriter(Postrequest.GetRequestStream()))
|
||||||
|
{
|
||||||
|
string json = string.Format("<real val=\"{0},{1}\"/>", phone, content);
|
||||||
|
|
||||||
|
streamWriter.Write(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
//設定回傳的Request
|
||||||
|
HttpWebResponse response = (HttpWebResponse)Postrequest.GetResponse();
|
||||||
|
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
|
||||||
|
XmlDocument xmlDoc = new XmlDocument();
|
||||||
|
xmlDoc.LoadXml(responseString);
|
||||||
|
string jsonText = JsonConvert.SerializeXmlNode(xmlDoc);
|
||||||
|
JObject resultVal = (JObject)JsonConvert.DeserializeObject(jsonText);
|
||||||
|
|
||||||
|
if (resultVal.ContainsKey("obj"))
|
||||||
|
{
|
||||||
|
var display_split = resultVal["obj"]["@display"].ToString().Split(' ');
|
||||||
|
var responseStatus = display_split[display_split.Length - 1];
|
||||||
|
|
||||||
|
if (responseStatus == "{ok}")
|
||||||
|
{
|
||||||
|
logger.LogInformation("【SendSMSService】【SMS寄送成功】[任務編號]:{0}", id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.LogError("【SendSMSService】【SMS寄送失敗】[任務編號]:{0}", id);
|
||||||
|
logger.LogError("【SendSMSService】【SMS寄送失敗】[失敗內容]:{0}", resultVal);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【SendSMSService】【SMS寄送失敗】[任務編號]:{0}", id);
|
||||||
|
logger.LogError("【SendSMSService】【SMS寄送失敗】[Exception]:{0}", exception.ToString());
|
||||||
|
throw;
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
213
Backend/Services/Implement/TyphoonApi.cs
Normal file
213
Backend/Services/Implement/TyphoonApi.cs
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
// <auto-generated />
|
||||||
|
//
|
||||||
|
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||||
|
//
|
||||||
|
// using QuickType;
|
||||||
|
//
|
||||||
|
// var welcome = Welcome.FromJson(jsonString);
|
||||||
|
|
||||||
|
namespace TyphoonApi
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
[JsonProperty("?xml")]
|
||||||
|
public Xml Xml { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("alert")]
|
||||||
|
public Alert Alert { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Alert
|
||||||
|
{
|
||||||
|
[JsonProperty("@xmlns")]
|
||||||
|
public string Xmlns { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("identifier")]
|
||||||
|
public string Identifier { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sender")]
|
||||||
|
public string Sender { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sent")]
|
||||||
|
public DateTimeOffset Sent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("status")]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("msgType")]
|
||||||
|
public string MsgType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("scope")]
|
||||||
|
public string Scope { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("references")]
|
||||||
|
public string References { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("info")]
|
||||||
|
public Info Info { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Info
|
||||||
|
{
|
||||||
|
[JsonProperty("language")]
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("category")]
|
||||||
|
public string Category { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("event")]
|
||||||
|
public string Event { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("urgency")]
|
||||||
|
public string Urgency { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("severity")]
|
||||||
|
public string Severity { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("certainty")]
|
||||||
|
public string Certainty { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("eventCode")]
|
||||||
|
public EventCode EventCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("effective")]
|
||||||
|
public DateTimeOffset Effective { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("onset")]
|
||||||
|
public DateTimeOffset Onset { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("expires")]
|
||||||
|
public DateTimeOffset Expires { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("senderName")]
|
||||||
|
public string SenderName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("headline")]
|
||||||
|
public string Headline { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("instruction")]
|
||||||
|
public string Instruction { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("web")]
|
||||||
|
public Uri Web { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("parameter")]
|
||||||
|
public EventCode Parameter { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("area")]
|
||||||
|
public List<Area> Area { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Area
|
||||||
|
{
|
||||||
|
[JsonProperty("areaDesc")]
|
||||||
|
public string AreaDesc { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("geocode")]
|
||||||
|
public EventCode Geocode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EventCode
|
||||||
|
{
|
||||||
|
[JsonProperty("valueName")]
|
||||||
|
public string ValueName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("value")]
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Xml
|
||||||
|
{
|
||||||
|
[JsonProperty("@version")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("@encoding")]
|
||||||
|
public string Encoding { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ValueName { AlertTitle, ProfileCapTwpEvent10, TaiwanGeocode103 };
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serialize
|
||||||
|
{
|
||||||
|
public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Converter
|
||||||
|
{
|
||||||
|
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||||
|
DateParseHandling = DateParseHandling.None,
|
||||||
|
Converters =
|
||||||
|
{
|
||||||
|
ValueNameConverter.Singleton,
|
||||||
|
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ValueNameConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(ValueName) || t == typeof(ValueName?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case "Taiwan_Geocode_103":
|
||||||
|
return ValueName.TaiwanGeocode103;
|
||||||
|
case "alert_title":
|
||||||
|
return ValueName.AlertTitle;
|
||||||
|
case "profile:CAP-TWP:Event:1.0":
|
||||||
|
return ValueName.ProfileCapTwpEvent10;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type ValueName");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (ValueName)untypedValue;
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case ValueName.TaiwanGeocode103:
|
||||||
|
serializer.Serialize(writer, "Taiwan_Geocode_103");
|
||||||
|
return;
|
||||||
|
case ValueName.AlertTitle:
|
||||||
|
serializer.Serialize(writer, "alert_title");
|
||||||
|
return;
|
||||||
|
case ValueName.ProfileCapTwpEvent10:
|
||||||
|
serializer.Serialize(writer, "profile:CAP-TWP:Event:1.0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type ValueName");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly ValueNameConverter Singleton = new ValueNameConverter();
|
||||||
|
}
|
||||||
|
}
|
12
Backend/Services/Interface/ISendEmailService.cs
Normal file
12
Backend/Services/Interface/ISendEmailService.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BackendWorkerService.Services.Interface
|
||||||
|
{
|
||||||
|
public interface ISendEmailService
|
||||||
|
{
|
||||||
|
bool Send(int id, List<string> recipientEmails, string subject, string content);
|
||||||
|
}
|
||||||
|
}
|
11
Backend/Services/Interface/ISendLineNotifyService.cs
Normal file
11
Backend/Services/Interface/ISendLineNotifyService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BackendWorkerService.Services.Interface
|
||||||
|
{
|
||||||
|
public interface ISendLineNotifyService
|
||||||
|
{
|
||||||
|
bool Send(int id, string lineToken, string message);
|
||||||
|
}
|
||||||
|
}
|
11
Backend/Services/Interface/ISendSMSService.cs
Normal file
11
Backend/Services/Interface/ISendSMSService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BackendWorkerService.Services.Interface
|
||||||
|
{
|
||||||
|
public interface ISendSMSService
|
||||||
|
{
|
||||||
|
bool Send(int id, string phone, string message);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.HttpsPolicy;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
@ -16,15 +15,18 @@ using Repository.FrontendRepository.Interface;
|
|||||||
using Repository.Models;
|
using Repository.Models;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Backend.Jwt;
|
using Backend.Jwt;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Backend.Quartz.Jobs;
|
||||||
|
using Backend.Quartz;
|
||||||
|
using Quartz.Impl;
|
||||||
|
using Quartz.Spi;
|
||||||
|
using Quartz;
|
||||||
|
|
||||||
namespace Backend
|
namespace Backend
|
||||||
{
|
{
|
||||||
@ -115,8 +117,16 @@ namespace Backend
|
|||||||
services.AddTransient<IDeviceManageRepository, DeviceManageRepository>();
|
services.AddTransient<IDeviceManageRepository, DeviceManageRepository>();
|
||||||
services.AddTransient<IDeviceImportRepository, DeviceImportRepository>();
|
services.AddTransient<IDeviceImportRepository, DeviceImportRepository>();
|
||||||
services.AddTransient<INiagaraDataSynchronizeRepository, NiagaraDataSynchronizeRepository>();
|
services.AddTransient<INiagaraDataSynchronizeRepository, NiagaraDataSynchronizeRepository>();
|
||||||
|
services.AddTransient<IBackgroundServiceRepository, BackgroundServiceRepository>();
|
||||||
|
services.AddTransient<IBackgroundServiceMsSqlRepository, BackgroundServiceMsSqlRepository>();
|
||||||
#endregion Repository ª`¤J
|
#endregion Repository ª`¤J
|
||||||
|
|
||||||
|
#region 添加Quartz服務
|
||||||
|
services.AddTransient<IJobFactory, SingletonJobFactory>();
|
||||||
|
services.AddTransient<ISchedulerFactory, StdSchedulerFactory>();
|
||||||
|
services.AddHostedService<QuartzHostedService>();
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region JWT ª`¤J
|
#region JWT ª`¤J
|
||||||
services.AddTransient<IJwtHelpers, JwtHelpers>();
|
services.AddTransient<IJwtHelpers, JwtHelpers>();
|
||||||
services
|
services
|
||||||
@ -153,6 +163,20 @@ namespace Backend
|
|||||||
});
|
});
|
||||||
#endregion JWT ª`¤J
|
#endregion JWT ª`¤J
|
||||||
|
|
||||||
|
#region 電錶歸檔(設定每 天 執行一次)
|
||||||
|
services.AddSingleton<ArchiveElectricMeterDayJob>();
|
||||||
|
services.AddSingleton(
|
||||||
|
new JobSchedule(jobType: typeof(ArchiveElectricMeterDayJob), cronExpression: Configuration.GetValue<string>("BackgroundServiceCron:ArchiveElectricMeterDayJob"))
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 定時取得氣象API
|
||||||
|
services.AddSingleton<WeatherAPIJob>();
|
||||||
|
services.AddSingleton(
|
||||||
|
new JobSchedule(jobType: typeof(WeatherAPIJob), cronExpression: Configuration.GetValue<string>("BackgroundServiceCron:WeatherAPIJob"))
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
|
||||||
double loginExpireMinute = this.Configuration.GetValue<double>("LoginExpireMinute");
|
double loginExpireMinute = this.Configuration.GetValue<double>("LoginExpireMinute");
|
||||||
services.AddSession(options =>
|
services.AddSession(options =>
|
||||||
{
|
{
|
||||||
|
@ -814,7 +814,7 @@
|
|||||||
if (rel.data.length > 0) {
|
if (rel.data.length > 0) {
|
||||||
$('#select_building').empty();
|
$('#select_building').empty();
|
||||||
$.each(rel.data, function (index, val) {
|
$.each(rel.data, function (index, val) {
|
||||||
$("#select_building").append($("<option />").val(val.building_guid).text(val.full_name));
|
$("#select_building").append($("<option />").val(val.building_tag).text(val.full_name));
|
||||||
});
|
});
|
||||||
//預設查詢第一個
|
//預設查詢第一個
|
||||||
$("#select_building").val($("#select_building option:first").val());
|
$("#select_building").val($("#select_building option:first").val());
|
||||||
|
@ -12,6 +12,17 @@
|
|||||||
"SignKey": "TaipeiDome123456", //簽章//最少16字元
|
"SignKey": "TaipeiDome123456", //簽章//最少16字元
|
||||||
"JwtLifeSeconds": 3600
|
"JwtLifeSeconds": 3600
|
||||||
},
|
},
|
||||||
|
"LoggerPath": "C:\\Project\\ASP.NET\\BIMS\\Backend",
|
||||||
|
"BackgroundServiceCron": {
|
||||||
|
"ExecutionBackgroundServicePlanJob": "0 0 2 * * ?",
|
||||||
|
"MessageNotificationJob": "0 0 2 * * ?",
|
||||||
|
"DataDeliveryJob": "0 0 2 * * ?",
|
||||||
|
"RegularUpdateDBTableJob": "0 0 2 * * ?",
|
||||||
|
"ParkingJob": "0 0 2 * * ?",
|
||||||
|
"ArchiveElectricMeterHourJob": "0 0 2 * * ?",
|
||||||
|
"ArchiveElectricMeterDayJob": "0 0 2 * * ?",
|
||||||
|
"WeatherAPIJob": "0/5 * * * * ?"
|
||||||
|
},
|
||||||
"DBConfig": {
|
"DBConfig": {
|
||||||
"MySqlDBConfig": {
|
"MySqlDBConfig": {
|
||||||
"Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
|
"Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
|
||||||
@ -23,6 +34,13 @@
|
|||||||
//"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
|
//"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
|
||||||
"Root": "SzdxEgaJJ7tcTCrUl2zKsA==",
|
"Root": "SzdxEgaJJ7tcTCrUl2zKsA==",
|
||||||
"Password": "FVAPxztxpY4gJJKQ/se4bQ=="
|
"Password": "FVAPxztxpY4gJJKQ/se4bQ=="
|
||||||
|
},
|
||||||
|
"MSSqlDBConfig": {
|
||||||
|
"Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
|
||||||
|
"Port": "S5cUXKnKOacFtFy9+0dtpw==",
|
||||||
|
"Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome
|
||||||
|
"Root": "sD8GZ9UPiIQGU6dU011/4A==",
|
||||||
|
"Password": "0O24es2ZRF5uoJ4aU+YCdg=="
|
||||||
}
|
}
|
||||||
//"MSSqlDBConfig": {
|
//"MSSqlDBConfig": {
|
||||||
// "Server": "zp3Nilx0PISEEC4caZWqCg==", //172.16.220.250
|
// "Server": "zp3Nilx0PISEEC4caZWqCg==", //172.16.220.250
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"SignKey": "TaipeiDome123456", //簽章//最少16字元
|
"SignKey": "TaipeiDome123456", //簽章//最少16字元
|
||||||
"JwtLifeSeconds": 3600
|
"JwtLifeSeconds": 3600
|
||||||
},
|
},
|
||||||
|
"LoggerPath": "C:\\Project\\ASP.NET\\BIMS\\Backend",
|
||||||
"DBConfig": {
|
"DBConfig": {
|
||||||
"MySqlDBConfig": {
|
"MySqlDBConfig": {
|
||||||
"Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
|
"Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
|
||||||
@ -22,6 +23,13 @@
|
|||||||
//"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
|
//"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
|
||||||
"Root": "SzdxEgaJJ7tcTCrUl2zKsA==",
|
"Root": "SzdxEgaJJ7tcTCrUl2zKsA==",
|
||||||
"Password": "FVAPxztxpY4gJJKQ/se4bQ=="
|
"Password": "FVAPxztxpY4gJJKQ/se4bQ=="
|
||||||
|
},
|
||||||
|
"MSSqlDBConfig": {
|
||||||
|
"Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
|
||||||
|
"Port": "S5cUXKnKOacFtFy9+0dtpw==",
|
||||||
|
"Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome
|
||||||
|
"Root": "sD8GZ9UPiIQGU6dU011/4A==",
|
||||||
|
"Password": "0O24es2ZRF5uoJ4aU+YCdg=="
|
||||||
}
|
}
|
||||||
//"MSSqlDBConfig": {
|
//"MSSqlDBConfig": {
|
||||||
// "Server": "ueFp+VFb200lhh1Uctc97WH0/tX6tfXYU2v1oxCWuuM=",
|
// "Server": "ueFp+VFb200lhh1Uctc97WH0/tX6tfXYU2v1oxCWuuM=",
|
||||||
|
@ -97,47 +97,47 @@ namespace BackendWorkerService
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region 背景執行計畫(設定1min執行一次)
|
//#region 背景執行計畫(設定1min執行一次)
|
||||||
services.AddSingleton<ExecutionBackgroundServicePlanJob>();
|
//services.AddSingleton<ExecutionBackgroundServicePlanJob>();
|
||||||
services.AddSingleton(
|
//services.AddSingleton(
|
||||||
new JobSchedule(jobType: typeof(ExecutionBackgroundServicePlanJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:ExecutionBackgroundServicePlanJob"))
|
//new JobSchedule(jobType: typeof(ExecutionBackgroundServicePlanJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:ExecutionBackgroundServicePlanJob"))
|
||||||
);
|
//);
|
||||||
#endregion
|
//#endregion
|
||||||
|
|
||||||
#region 訊息通知(設定每 30min 執行一次)
|
//#region 訊息通知(設定每 30min 執行一次)
|
||||||
services.AddSingleton<MessageNotificationJob>();
|
//services.AddSingleton<MessageNotificationJob>();
|
||||||
services.AddSingleton(
|
//services.AddSingleton(
|
||||||
new JobSchedule(jobType: typeof(MessageNotificationJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:MessageNotificationJob"))
|
//new JobSchedule(jobType: typeof(MessageNotificationJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:MessageNotificationJob"))
|
||||||
);
|
//);
|
||||||
#endregion
|
//#endregion
|
||||||
|
|
||||||
#region 定時將特定資料表加入至派送任務(設定每日 2AM 執行一次)
|
//#region 定時將特定資料表加入至派送任務(設定每日 2AM 執行一次)
|
||||||
services.AddSingleton<RegularUpdateDBTableJob>();
|
//services.AddSingleton<RegularUpdateDBTableJob>();
|
||||||
services.AddSingleton(
|
//services.AddSingleton(
|
||||||
new JobSchedule(jobType: typeof(RegularUpdateDBTableJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:RegularUpdateDBTableJob"))
|
//new JobSchedule(jobType: typeof(RegularUpdateDBTableJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:RegularUpdateDBTableJob"))
|
||||||
);
|
//);
|
||||||
#endregion
|
//#endregion
|
||||||
|
|
||||||
#region 資料派送(設定每 5min 執行一次)
|
//#region 資料派送(設定每 5min 執行一次)
|
||||||
services.AddSingleton<DataDeliveryJob>();
|
//services.AddSingleton<DataDeliveryJob>();
|
||||||
services.AddSingleton(
|
//services.AddSingleton(
|
||||||
new JobSchedule(jobType: typeof(DataDeliveryJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:DataDeliveryJob"))
|
//new JobSchedule(jobType: typeof(DataDeliveryJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:DataDeliveryJob"))
|
||||||
);
|
//);
|
||||||
#endregion
|
//#endregion
|
||||||
|
|
||||||
#region 停車場管理(設定每 5秒 執行一次)
|
//#region 停車場管理(設定每 5秒 執行一次)
|
||||||
services.AddSingleton<ParkingJob>();
|
//services.AddSingleton<ParkingJob>();
|
||||||
services.AddSingleton(
|
//services.AddSingleton(
|
||||||
new JobSchedule(jobType: typeof(ParkingJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:ParkingJob"))
|
//new JobSchedule(jobType: typeof(ParkingJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:ParkingJob"))
|
||||||
);
|
//);
|
||||||
#endregion
|
//#endregion
|
||||||
|
|
||||||
#region 電錶歸檔(設定每 小時 執行一次)
|
//#region 電錶歸檔(設定每 小時 執行一次)
|
||||||
services.AddSingleton<ArchiveElectricMeterHourJob>();
|
//services.AddSingleton<ArchiveElectricMeterHourJob>();
|
||||||
services.AddSingleton(
|
//services.AddSingleton(
|
||||||
new JobSchedule(jobType: typeof(ArchiveElectricMeterHourJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:ArchiveElectricMeterHourJob"))
|
//new JobSchedule(jobType: typeof(ArchiveElectricMeterHourJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:ArchiveElectricMeterHourJob"))
|
||||||
);
|
//);
|
||||||
#endregion
|
//#endregion
|
||||||
#region 電錶歸檔(設定每 天 執行一次)
|
#region 電錶歸檔(設定每 天 執行一次)
|
||||||
services.AddSingleton<ArchiveElectricMeterDayJob>();
|
services.AddSingleton<ArchiveElectricMeterDayJob>();
|
||||||
services.AddSingleton(
|
services.AddSingleton(
|
||||||
|
@ -56,6 +56,7 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
XmlDocument xmlDocument = new XmlDocument();
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
|
||||||
var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'";
|
var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'";
|
||||||
|
var saveToMSDB = await backgroundServiceRepository.GetOneAsync<string>("select system_value from variable where system_type = 'save_to_ms_db' and deleted = 0");
|
||||||
|
|
||||||
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
|
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
|
||||||
var electricMeterGuid = variableArchive.Where(x => x.Name == "ElectricMeterGuid").Select(x => x.Value).FirstOrDefault();
|
var electricMeterGuid = variableArchive.Where(x => x.Name == "ElectricMeterGuid").Select(x => x.Value).FirstOrDefault();
|
||||||
@ -126,6 +127,7 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
{
|
{
|
||||||
await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Day", "任務開始");
|
await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Day", "任務開始");
|
||||||
var preDay = now.AddDays(-1); //取得前一天
|
var preDay = now.AddDays(-1); //取得前一天
|
||||||
|
var dbDateName = preDay.Year.ToString().PadLeft(4, '0') + preDay.Month.ToString().PadLeft(2, '0');
|
||||||
|
|
||||||
var startTimestamp = string.Format("{0}T00:00:00.000+08:00", preDay.ToString("yyyy-MM-dd"));
|
var startTimestamp = string.Format("{0}T00:00:00.000+08:00", preDay.ToString("yyyy-MM-dd"));
|
||||||
var endTimestamp = string.Format("{0}T23:59:59.000+08:00", preDay.ToString("yyyy-MM-dd"));
|
var endTimestamp = string.Format("{0}T23:59:59.000+08:00", preDay.ToString("yyyy-MM-dd"));
|
||||||
@ -258,8 +260,26 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
if (electericArchiveDayRawDatas.Count() > 0)
|
if (electericArchiveDayRawDatas.Count() > 0)
|
||||||
{
|
{
|
||||||
var sql = $@"
|
var sql = $@"CREATE TABLE IF NOT EXISTS `archive_electric_meter_day_{dbDateName}` (
|
||||||
UPDATE archive_electric_meter_day SET
|
`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,
|
||||||
|
`start_timestamp` datetime(6) NOT NULL,
|
||||||
|
`end_timestamp` datetime(6) NULL DEFAULT NULL,
|
||||||
|
`count_rawdata` int(11) NULL DEFAULT NULL,
|
||||||
|
`min_rawdata` decimal(15, 3) NULL DEFAULT NULL,
|
||||||
|
`max_rawdata` decimal(15, 3) NULL DEFAULT NULL,
|
||||||
|
`avg_rawdata` decimal(15, 3) NULL DEFAULT NULL,
|
||||||
|
`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 '失敗原因',
|
||||||
|
`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;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
UPDATE archive_electric_meter_day_{dbDateName} SET
|
||||||
count_rawdata = @count_rawdata,
|
count_rawdata = @count_rawdata,
|
||||||
min_rawdata = @min_rawdata,
|
min_rawdata = @min_rawdata,
|
||||||
max_rawdata = @max_rawdata,
|
max_rawdata = @max_rawdata,
|
||||||
@ -273,8 +293,7 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
AND point = @point
|
AND point = @point
|
||||||
AND start_timestamp = @start_timestamp;
|
AND start_timestamp = @start_timestamp;
|
||||||
|
|
||||||
|
INSERT INTO archive_electric_meter_day_{dbDateName} (
|
||||||
INSERT INTO archive_electric_meter_day (
|
|
||||||
device_number,
|
device_number,
|
||||||
point,
|
point,
|
||||||
start_timestamp,
|
start_timestamp,
|
||||||
@ -303,8 +322,45 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
WHERE ROW_COUNT() = 0;";
|
WHERE ROW_COUNT() = 0;";
|
||||||
|
|
||||||
var mySql = $@"BEGIN TRANSACTION;
|
var mySql = $@"BEGIN TRANSACTION;
|
||||||
|
IF OBJECT_ID(N'dbo.archive_electric_meter_day_{dbDateName}', N'U') is null
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE [dbo].[archive_electric_meter_day_{dbDateName}](
|
||||||
|
[device_number] [varchar](50) NOT NULL,
|
||||||
|
[point] [varchar](20) NOT NULL,
|
||||||
|
[start_timestamp] [datetime] NOT NULL,
|
||||||
|
[end_timestamp] [datetime] NULL,
|
||||||
|
[count_rawdata] [int] NULL,
|
||||||
|
[min_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[max_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[avg_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[sum_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[is_complete] [tinyint] NULL,
|
||||||
|
[repeat_times] [int] NULL,
|
||||||
|
[fail_reason] [nvarchar](max) NULL,
|
||||||
|
[created_at] [datetime] NULL,
|
||||||
|
[updated_at] [datetime] NULL,
|
||||||
|
CONSTRAINT [PK_archive_electric_meter_day_{dbDateName}] PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[device_number] ASC,
|
||||||
|
[point] ASC,
|
||||||
|
[start_timestamp] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
||||||
|
|
||||||
UPDATE archive_electric_meter_day SET
|
ALTER TABLE [dbo].[archive_electric_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_meter_day_{dbDateName}_repeat_times] DEFAULT ((0)) FOR [repeat_times]
|
||||||
|
|
||||||
|
ALTER TABLE [dbo].[archive_electric_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_meter_day_{dbDateName}_created_at] DEFAULT (getdate()) FOR [created_at]
|
||||||
|
|
||||||
|
ALTER TABLE [dbo].[archive_electric_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_meter_day_{dbDateName}_updated_at] DEFAULT (NULL) FOR [updated_at]
|
||||||
|
|
||||||
|
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否完成,0:未完成 1:完成' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'is_complete'
|
||||||
|
|
||||||
|
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重複次數' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'repeat_times'
|
||||||
|
|
||||||
|
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'失敗原因' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'fail_reason'
|
||||||
|
END
|
||||||
|
|
||||||
|
UPDATE archive_electric_meter_day_{dbDateName} SET
|
||||||
count_rawdata = @count_rawdata,
|
count_rawdata = @count_rawdata,
|
||||||
min_rawdata = @min_rawdata,
|
min_rawdata = @min_rawdata,
|
||||||
max_rawdata = @max_rawdata,
|
max_rawdata = @max_rawdata,
|
||||||
@ -320,7 +376,7 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
IF @@ROWCOUNT = 0
|
IF @@ROWCOUNT = 0
|
||||||
BEGIN
|
BEGIN
|
||||||
INSERT INTO archive_electric_meter_day (
|
INSERT INTO archive_electric_meter_day_{dbDateName} (
|
||||||
device_number,
|
device_number,
|
||||||
point,
|
point,
|
||||||
start_timestamp,
|
start_timestamp,
|
||||||
@ -350,12 +406,33 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
COMMIT TRANSACTION;";
|
COMMIT TRANSACTION;";
|
||||||
await backgroundServiceRepository.ExecuteSql(sql, electericArchiveDayRawDatas);
|
await backgroundServiceRepository.ExecuteSql(sql, electericArchiveDayRawDatas);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electericArchiveDayRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electericArchiveDayRawDatas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (waterArchiveDayRawDatas.Count() > 0)
|
if (waterArchiveDayRawDatas.Count() > 0)
|
||||||
{
|
{
|
||||||
var sql = $@"
|
var sql = $@"
|
||||||
UPDATE archive_water_meter_day SET
|
CREATE TABLE IF NOT EXISTS `archive_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,
|
||||||
|
`start_timestamp` datetime(6) NOT NULL,
|
||||||
|
`end_timestamp` datetime(6) NULL DEFAULT NULL,
|
||||||
|
`count_rawdata` int(11) NULL DEFAULT NULL,
|
||||||
|
`min_rawdata` decimal(15, 3) NULL DEFAULT NULL,
|
||||||
|
`max_rawdata` decimal(15, 3) NULL DEFAULT NULL,
|
||||||
|
`avg_rawdata` decimal(15, 3) NULL DEFAULT NULL,
|
||||||
|
`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 '失敗原因',
|
||||||
|
`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;
|
||||||
|
|
||||||
|
UPDATE archive_water_meter_day_{dbDateName} SET
|
||||||
count_rawdata = @count_rawdata,
|
count_rawdata = @count_rawdata,
|
||||||
min_rawdata = @min_rawdata,
|
min_rawdata = @min_rawdata,
|
||||||
max_rawdata = @max_rawdata,
|
max_rawdata = @max_rawdata,
|
||||||
@ -370,7 +447,7 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
AND start_timestamp = @start_timestamp;
|
AND start_timestamp = @start_timestamp;
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO archive_water_meter_day (
|
INSERT INTO archive_water_meter_day_{dbDateName} (
|
||||||
device_number,
|
device_number,
|
||||||
point,
|
point,
|
||||||
start_timestamp,
|
start_timestamp,
|
||||||
@ -399,8 +476,45 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
WHERE ROW_COUNT() = 0;";
|
WHERE ROW_COUNT() = 0;";
|
||||||
|
|
||||||
var mySql = $@"BEGIN TRANSACTION;
|
var mySql = $@"BEGIN TRANSACTION;
|
||||||
|
IF OBJECT_ID(N'dbo.archive_water_meter_day_{dbDateName}', N'U') is null
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE [dbo].[archive_water_meter_day_{dbDateName}](
|
||||||
|
[device_number] [varchar](50) NOT NULL,
|
||||||
|
[point] [varchar](20) NOT NULL,
|
||||||
|
[start_timestamp] [datetime] NOT NULL,
|
||||||
|
[end_timestamp] [datetime] NULL,
|
||||||
|
[count_rawdata] [int] NULL,
|
||||||
|
[min_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[max_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[avg_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[sum_rawdata] [decimal](15, 3) NULL,
|
||||||
|
[is_complete] [tinyint] NULL,
|
||||||
|
[repeat_times] [int] NULL,
|
||||||
|
[fail_reason] [nvarchar](max) NULL,
|
||||||
|
[created_at] [datetime] NULL,
|
||||||
|
[updated_at] [datetime] NULL,
|
||||||
|
CONSTRAINT [PK_archive_water_meter_day_{dbDateName}] PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[device_number] ASC,
|
||||||
|
[point] ASC,
|
||||||
|
[start_timestamp] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
||||||
|
|
||||||
UPDATE archive_water_meter_day SET
|
ALTER TABLE [dbo].[archive_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_water_meter_day_{dbDateName}_repeat_times] DEFAULT ((0)) FOR [repeat_times]
|
||||||
|
|
||||||
|
ALTER TABLE [dbo].[archive_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_water_meter_day_{dbDateName}_created_at] DEFAULT (getdate()) FOR [created_at]
|
||||||
|
|
||||||
|
ALTER TABLE [dbo].[archive_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_water_meter_day_{dbDateName}_updated_at] DEFAULT (NULL) FOR [updated_at]
|
||||||
|
|
||||||
|
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否完成,0:未完成 1:完成' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'is_complete'
|
||||||
|
|
||||||
|
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重複次數' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'repeat_times'
|
||||||
|
|
||||||
|
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'失敗原因' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'fail_reason'
|
||||||
|
END
|
||||||
|
|
||||||
|
UPDATE archive_water_meter_day_{dbDateName} SET
|
||||||
count_rawdata = @count_rawdata,
|
count_rawdata = @count_rawdata,
|
||||||
min_rawdata = @min_rawdata,
|
min_rawdata = @min_rawdata,
|
||||||
max_rawdata = @max_rawdata,
|
max_rawdata = @max_rawdata,
|
||||||
@ -416,7 +530,7 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
IF @@ROWCOUNT = 0
|
IF @@ROWCOUNT = 0
|
||||||
BEGIN
|
BEGIN
|
||||||
INSERT INTO archive_water_meter_day (
|
INSERT INTO archive_water_meter_day_{dbDateName} (
|
||||||
device_number,
|
device_number,
|
||||||
point,
|
point,
|
||||||
start_timestamp,
|
start_timestamp,
|
||||||
@ -446,7 +560,10 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
COMMIT TRANSACTION;";
|
COMMIT TRANSACTION;";
|
||||||
await backgroundServiceRepository.ExecuteSql(sql, waterArchiveDayRawDatas);
|
await backgroundServiceRepository.ExecuteSql(sql, waterArchiveDayRawDatas);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveDayRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveDayRawDatas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Day", "任務完成");
|
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Day", "任務完成");
|
||||||
}
|
}
|
||||||
@ -691,7 +808,10 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
COMMIT TRANSACTION;";
|
COMMIT TRANSACTION;";
|
||||||
await backgroundServiceRepository.ExecuteSql(sql, electricArchiveWeekRawDatas);
|
await backgroundServiceRepository.ExecuteSql(sql, electricArchiveWeekRawDatas);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveWeekRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (waterArchiveWeekRawDatas.Count() > 0)
|
if (waterArchiveWeekRawDatas.Count() > 0)
|
||||||
@ -790,8 +910,10 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
COMMIT TRANSACTION;";
|
COMMIT TRANSACTION;";
|
||||||
await backgroundServiceRepository.ExecuteSql(sql, waterArchiveWeekRawDatas);
|
await backgroundServiceRepository.ExecuteSql(sql, waterArchiveWeekRawDatas);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveWeekRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Week", "任務完成");
|
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Week", "任務完成");
|
||||||
}
|
}
|
||||||
@ -1035,7 +1157,10 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
COMMIT TRANSACTION;";
|
COMMIT TRANSACTION;";
|
||||||
await backgroundServiceRepository.ExecuteSql(sql, electricArchiveMonthRawDatas);
|
await backgroundServiceRepository.ExecuteSql(sql, electricArchiveMonthRawDatas);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveMonthRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (waterArchiveMonthRawDatas.Count() > 0)
|
if (waterArchiveMonthRawDatas.Count() > 0)
|
||||||
{
|
{
|
||||||
@ -1130,7 +1255,10 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
|
|
||||||
COMMIT TRANSACTION;";
|
COMMIT TRANSACTION;";
|
||||||
await backgroundServiceRepository.ExecuteSql(sql, waterArchiveMonthRawDatas);
|
await backgroundServiceRepository.ExecuteSql(sql, waterArchiveMonthRawDatas);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveMonthRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Month", "任務完成");
|
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Month", "任務完成");
|
||||||
}
|
}
|
||||||
|
@ -200,71 +200,71 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
doc.Load("root/PowerfulRain.xml");
|
doc.Load("root/PowerfulRain.xml");
|
||||||
var json = JsonConvert.SerializeXmlNode(doc);
|
var json = JsonConvert.SerializeXmlNode(doc);
|
||||||
var haveinfo = json.Split("info");
|
var haveinfo = json.Split("info");
|
||||||
if (haveinfo.Length > 2)
|
//if (haveinfo.Length > 2)
|
||||||
{
|
//{
|
||||||
var observation = JsonConvert.DeserializeObject<RainAPIInfoList>(json);
|
// var observation = RainApi.Welcome.FromJson(json);
|
||||||
var area = observation.Alert.Info[0].Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
// var area = observation.Alert.Info[0].Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info[0].Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info[0].Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
// var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info[0].Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info[0].Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
// var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
|
|
||||||
Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
|
// Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
|
||||||
{
|
// {
|
||||||
{ "@msgType", observation.Alert.MsgType},
|
// { "@msgType", observation.Alert.MsgType},
|
||||||
{ "@headline", observation.Alert.Info[0].Headline},
|
// { "@headline", observation.Alert.Info[0].Headline},
|
||||||
{ "@areaDesc", area},
|
// { "@areaDesc", area},
|
||||||
{ "@onset", observation.Alert.Info[0].Onset},
|
// { "@onset", observation.Alert.Info[0].Onset},
|
||||||
{ "@expires", observation.Alert.Info[0].Expires},
|
// { "@expires", observation.Alert.Info[0].Expires},
|
||||||
{ "@created_by", "system"},
|
// { "@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")},
|
||||||
};
|
// };
|
||||||
var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain");
|
// var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain");
|
||||||
if (NeedCallApi != 0)
|
// if (NeedCallApi != 0)
|
||||||
{
|
// {
|
||||||
var val = RainValue(observation.Alert.MsgType, observation.Alert.Info[0].Headline);
|
// var val = RainValue(observation.Alert.MsgType, observation.Alert.Info[0].Headline);
|
||||||
if (val < 5)
|
// if (val < 5)
|
||||||
{
|
// {
|
||||||
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString());
|
// var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString());
|
||||||
UpdatedNiagara("api_rain", ReStr, id);
|
// UpdatedNiagara("api_rain", ReStr, id);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
FolderFunction folderFunction = new FolderFunction();
|
// FolderFunction folderFunction = new FolderFunction();
|
||||||
folderFunction.DeleteFile("root/PowerfulRain.xml");
|
// folderFunction.DeleteFile("root/PowerfulRain.xml");
|
||||||
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain");
|
// await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain");
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
var observation = JsonConvert.DeserializeObject<RainAPI>(json);
|
// var observation = RainApi.Welcome.FromJson(json);
|
||||||
var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
// var area = observation.Alert.Info[0].Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
// var sql = $"select id from api_rain where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info[0].Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info[0].Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
// var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
|
|
||||||
Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
|
// Dictionary<string, object> RainAPIdb = new Dictionary<string, object>()
|
||||||
{
|
// {
|
||||||
{ "@msgType", observation.Alert.MsgType},
|
// { "@msgType", observation.Alert.MsgType},
|
||||||
{ "@headline", observation.Alert.Info.Headline},
|
// { "@headline", observation.Alert.Info[0].Headline},
|
||||||
{ "@areaDesc", area},
|
// { "@areaDesc", area},
|
||||||
{ "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
|
// { "@onset", observation.Alert.Info[0].Onset.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
{ "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")},
|
// { "@expires", observation.Alert.Info[0].Expires.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
{ "@created_by", "system"},
|
// { "@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")},
|
||||||
};
|
// };
|
||||||
var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain");
|
// var id = await backendRepository.AddOneByCustomTableReturnId(RainAPIdb, "api_rain");
|
||||||
if (NeedCallApi != 0)
|
// if (NeedCallApi != 0)
|
||||||
{
|
// {
|
||||||
var val = RainValue(observation.Alert.MsgType, observation.Alert.Info.Headline);
|
// var val = RainValue(observation.Alert.MsgType, observation.Alert.Info[0].Headline);
|
||||||
if (val < 5)
|
// if (val < 5)
|
||||||
{
|
// {
|
||||||
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString());
|
// var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString());
|
||||||
UpdatedNiagara("api_rain", ReStr, id);
|
// UpdatedNiagara("api_rain", ReStr, id);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
FolderFunction folderFunction = new FolderFunction();
|
// FolderFunction folderFunction = new FolderFunction();
|
||||||
folderFunction.DeleteFile("root/PowerfulRain.xml");
|
// folderFunction.DeleteFile("root/PowerfulRain.xml");
|
||||||
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain");
|
// await task_Detail.InsertWorkTime_End("WeatherAPI", "api_rain");
|
||||||
|
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -284,71 +284,71 @@ namespace BackendWorkerService.Quartz.Jobs
|
|||||||
var json = JsonConvert.SerializeXmlNode(doc);
|
var json = JsonConvert.SerializeXmlNode(doc);
|
||||||
var haveinfo = json.Split("info");
|
var haveinfo = json.Split("info");
|
||||||
|
|
||||||
if (haveinfo.Length > 2)
|
//if (haveinfo.Length > 2)
|
||||||
{
|
//{
|
||||||
var observation = JsonConvert.DeserializeObject<RainAPIInfoList>(json);
|
// var observation = TyphoonApi.Welcome.FromJson(json);
|
||||||
var area = observation.Alert.Info[0].Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
// var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info[0].Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info[0].Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
// var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info[0].Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info[0].Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
// var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
// Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
||||||
{
|
// {
|
||||||
{ "@msgType", observation.Alert.MsgType},
|
// { "@msgType", observation.Alert.MsgType},
|
||||||
{ "@headline", observation.Alert.Info[0].Headline},
|
// { "@headline", observation.Alert.Info[0].Headline},
|
||||||
{ "@areaDesc", area},
|
// { "@areaDesc", area},
|
||||||
{ "@urgency",observation.Alert.Info[0].Urgency},
|
// { "@urgency",observation.Alert.Info[0].Urgency},
|
||||||
{ "@severity",observation.Alert.Info[0].Severity},
|
// { "@severity",observation.Alert.Info[0].Severity},
|
||||||
{ "@onset", observation.Alert.Info[0].Onset},
|
// { "@onset", observation.Alert.Info[0].Onset},
|
||||||
{ "@expires", observation.Alert.Info[0].Expires},
|
// { "@expires", observation.Alert.Info[0].Expires},
|
||||||
{ "@created_by", "system"},
|
// { "@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")},
|
||||||
};
|
// };
|
||||||
var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon");
|
// var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon");
|
||||||
if (NeedCallApi != 0)
|
// if (NeedCallApi != 0)
|
||||||
{
|
// {
|
||||||
if (observation.Alert.Info[0].Urgency != null && observation.Alert.Info[0].Urgency != "Expected")
|
// if (observation.Alert.Info[0].Urgency != null && observation.Alert.Info[0].Urgency != "Expected")
|
||||||
{
|
// {
|
||||||
|
|
||||||
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info[0].Urgency);
|
// var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info[0].Urgency);
|
||||||
UpdatedNiagara("api_typhoon", ReStr, id);
|
// UpdatedNiagara("api_typhoon", ReStr, id);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
FolderFunction folderFunction = new FolderFunction();
|
// FolderFunction folderFunction = new FolderFunction();
|
||||||
folderFunction.DeleteFile("root/Typhoon.xml");
|
// folderFunction.DeleteFile("root/Typhoon.xml");
|
||||||
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon");
|
// await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon");
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
var observation = JsonConvert.DeserializeObject<RainAPI>(json);
|
// var observation = TyphoonApi.Welcome.FromJson(json);
|
||||||
var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
// //var area = observation.Alert.Info.Area.Where(a => a.Geocode.Value == "63").Select(a => a.AreaDesc).FirstOrDefault();
|
||||||
var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
// var sql = $"select id from api_typhoon where msgType = '{observation.Alert.MsgType}' and onset = '{observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}' and expires = '{observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}'";
|
||||||
var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
// var NeedCallApi = await backendRepository.GetOneAsync<int>(sql);
|
||||||
Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
// Dictionary<string, object> EarthquakeAPIdb = new Dictionary<string, object>()
|
||||||
{
|
// {
|
||||||
{ "@msgType", observation.Alert.MsgType},
|
// { "@msgType", observation.Alert.MsgType},
|
||||||
{ "@headline", observation.Alert.Info.Headline},
|
// { "@headline", observation.Alert.Info.Headline},
|
||||||
{ "@areaDesc", area},
|
// //{ "@areaDesc", area},
|
||||||
{ "@urgency",observation.Alert.Info.Urgency},
|
// { "@urgency",observation.Alert.Info.Urgency},
|
||||||
{ "@severity",observation.Alert.Info.Severity},
|
// { "@severity",observation.Alert.Info.Severity},
|
||||||
{ "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
|
// { "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
{ "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")},
|
// { "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")},
|
||||||
{ "@created_by", "system"},
|
// { "@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")},
|
||||||
};
|
// };
|
||||||
var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon");
|
// var id = await backendRepository.AddOneByCustomTableReturnId(EarthquakeAPIdb, "api_typhoon");
|
||||||
if (NeedCallApi != 0)
|
// if (NeedCallApi != 0)
|
||||||
{
|
// {
|
||||||
if (observation.Alert.Info.Urgency != null && observation.Alert.Info.Urgency != "Expected")
|
// if (observation.Alert.Info.Urgency != null && observation.Alert.Info.Urgency != "Expected")
|
||||||
{
|
// {
|
||||||
|
|
||||||
var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency);
|
// var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency);
|
||||||
UpdatedNiagara("api_typhoon", ReStr, id);
|
// UpdatedNiagara("api_typhoon", ReStr, id);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
FolderFunction folderFunction = new FolderFunction();
|
// FolderFunction folderFunction = new FolderFunction();
|
||||||
folderFunction.DeleteFile("root/Typhoon.xml");
|
// folderFunction.DeleteFile("root/Typhoon.xml");
|
||||||
await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon");
|
// await task_Detail.InsertWorkTime_End("WeatherAPI", "api_typhoon");
|
||||||
|
|
||||||
}
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -52,6 +52,7 @@ namespace BackendWorkerService.Services.Implement
|
|||||||
|
|
||||||
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
|
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
|
||||||
repeatTimes = Convert.ToInt32(variableArchive.Where(x => x.Name == "RepeatTimes").Select(x => x.Value).FirstOrDefault());
|
repeatTimes = Convert.ToInt32(variableArchive.Where(x => x.Name == "RepeatTimes").Select(x => x.Value).FirstOrDefault());
|
||||||
|
var saveToMSDB = await backgroundServiceRepository.GetOneAsync<string>("select system_value from variable where system_type = 'save_to_ms_db' and deleted = 0");
|
||||||
|
|
||||||
#region 取得obix 設定
|
#region 取得obix 設定
|
||||||
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
|
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
|
||||||
@ -324,7 +325,10 @@ namespace BackendWorkerService.Services.Implement
|
|||||||
{
|
{
|
||||||
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
var sql_error_update = string.Format(sql_update_format, targetTable);
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveDayRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveDayRawDatas);
|
||||||
|
}
|
||||||
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveDayRawDatas);
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveDayRawDatas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +409,10 @@ namespace BackendWorkerService.Services.Implement
|
|||||||
{
|
{
|
||||||
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
var sql_error_update = string.Format(sql_update_format, targetTable);
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveDayRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveDayRawDatas);
|
||||||
|
}
|
||||||
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveDayRawDatas);
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveDayRawDatas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,7 +496,10 @@ namespace BackendWorkerService.Services.Implement
|
|||||||
{
|
{
|
||||||
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
var sql_error_update = string.Format(sql_update_format, targetTable);
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveWeekRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveWeekRawDatas);
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveWeekRawDatas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,7 +580,10 @@ namespace BackendWorkerService.Services.Implement
|
|||||||
{
|
{
|
||||||
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
var sql_error_update = string.Format(sql_update_format, targetTable);
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveWeekRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveWeekRawDatas);
|
||||||
|
}
|
||||||
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveWeekRawDatas);
|
await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveWeekRawDatas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -657,7 +670,10 @@ namespace BackendWorkerService.Services.Implement
|
|||||||
{
|
{
|
||||||
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
var sql_error_update = string.Format(sql_update_format, targetTable);
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveMonthRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
await backgroundServiceRepository.ExecuteSql(MYsql_update_format, electricArchiveMonthRawDatas);
|
await backgroundServiceRepository.ExecuteSql(MYsql_update_format, electricArchiveMonthRawDatas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -741,7 +757,10 @@ namespace BackendWorkerService.Services.Implement
|
|||||||
{
|
{
|
||||||
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
var Mysql_error_update = string.Format(MYsql_update_format, targetTable);
|
||||||
var sql_error_update = string.Format(sql_update_format, targetTable);
|
var sql_error_update = string.Format(sql_update_format, targetTable);
|
||||||
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveMonthRawDatas);
|
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
|
||||||
|
{
|
||||||
|
await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveMonthRawDatas);
|
||||||
|
}
|
||||||
await backgroundServiceRepository.ExecuteSql(MYsql_update_format, waterArchiveMonthRawDatas);
|
await backgroundServiceRepository.ExecuteSql(MYsql_update_format, waterArchiveMonthRawDatas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
228
BackendWorkerService/Services/Implement/RainApi.cs
Normal file
228
BackendWorkerService/Services/Implement/RainApi.cs
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
// <auto-generated />
|
||||||
|
//
|
||||||
|
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||||
|
//
|
||||||
|
// using QuickType;
|
||||||
|
//
|
||||||
|
// var welcome = Welcome.FromJson(jsonString);
|
||||||
|
|
||||||
|
namespace RainApi
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
[JsonProperty("?xml")]
|
||||||
|
public Xml Xml { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("alert")]
|
||||||
|
public Alert Alert { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Alert
|
||||||
|
{
|
||||||
|
[JsonProperty("@xmlns")]
|
||||||
|
public string Xmlns { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("identifier")]
|
||||||
|
public string Identifier { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sender")]
|
||||||
|
public string Sender { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sent")]
|
||||||
|
public DateTimeOffset Sent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("status")]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("msgType")]
|
||||||
|
public string MsgType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("scope")]
|
||||||
|
public string Scope { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("references")]
|
||||||
|
public string References { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("info")]
|
||||||
|
public Info[] Info { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Info
|
||||||
|
{
|
||||||
|
[JsonProperty("language")]
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("category")]
|
||||||
|
public string Category { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("event")]
|
||||||
|
public string Event { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("responseType")]
|
||||||
|
public string ResponseType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("urgency")]
|
||||||
|
public string Urgency { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("severity")]
|
||||||
|
public string Severity { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("certainty")]
|
||||||
|
public string Certainty { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("eventCode")]
|
||||||
|
public EventCode EventCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("effective")]
|
||||||
|
public DateTimeOffset Effective { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("onset")]
|
||||||
|
public DateTimeOffset Onset { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("expires")]
|
||||||
|
public DateTimeOffset Expires { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("senderName")]
|
||||||
|
public string SenderName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("headline")]
|
||||||
|
public string Headline { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("web")]
|
||||||
|
public Uri Web { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("parameter")]
|
||||||
|
public EventCode[] Parameter { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("area")]
|
||||||
|
public Area[] Area { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Area
|
||||||
|
{
|
||||||
|
[JsonProperty("areaDesc")]
|
||||||
|
public string AreaDesc { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("geocode")]
|
||||||
|
public EventCode Geocode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EventCode
|
||||||
|
{
|
||||||
|
[JsonProperty("valueName")]
|
||||||
|
public ValueName ValueName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("value")]
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Xml
|
||||||
|
{
|
||||||
|
[JsonProperty("@version")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("@encoding")]
|
||||||
|
public string Encoding { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ValueName { AlertColor, AlertTitle, ProfileCapTwpEvent10, SeverityLevel, TaiwanGeocode103, WebsiteColor };
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serialize
|
||||||
|
{
|
||||||
|
public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Converter
|
||||||
|
{
|
||||||
|
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||||
|
DateParseHandling = DateParseHandling.None,
|
||||||
|
Converters =
|
||||||
|
{
|
||||||
|
ValueNameConverter.Singleton,
|
||||||
|
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ValueNameConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(ValueName) || t == typeof(ValueName?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case "Taiwan_Geocode_103":
|
||||||
|
return ValueName.TaiwanGeocode103;
|
||||||
|
case "alert_color":
|
||||||
|
return ValueName.AlertColor;
|
||||||
|
case "alert_title":
|
||||||
|
return ValueName.AlertTitle;
|
||||||
|
case "profile:CAP-TWP:Event:1.0":
|
||||||
|
return ValueName.ProfileCapTwpEvent10;
|
||||||
|
case "severity_level":
|
||||||
|
return ValueName.SeverityLevel;
|
||||||
|
case "website_color":
|
||||||
|
return ValueName.WebsiteColor;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type ValueName");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (ValueName)untypedValue;
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case ValueName.TaiwanGeocode103:
|
||||||
|
serializer.Serialize(writer, "Taiwan_Geocode_103");
|
||||||
|
return;
|
||||||
|
case ValueName.AlertColor:
|
||||||
|
serializer.Serialize(writer, "alert_color");
|
||||||
|
return;
|
||||||
|
case ValueName.AlertTitle:
|
||||||
|
serializer.Serialize(writer, "alert_title");
|
||||||
|
return;
|
||||||
|
case ValueName.ProfileCapTwpEvent10:
|
||||||
|
serializer.Serialize(writer, "profile:CAP-TWP:Event:1.0");
|
||||||
|
return;
|
||||||
|
case ValueName.SeverityLevel:
|
||||||
|
serializer.Serialize(writer, "severity_level");
|
||||||
|
return;
|
||||||
|
case ValueName.WebsiteColor:
|
||||||
|
serializer.Serialize(writer, "website_color");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot marshal type ValueName");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly ValueNameConverter Singleton = new ValueNameConverter();
|
||||||
|
}
|
||||||
|
}
|
283
BackendWorkerService/Services/Implement/TyphoonApi.cs
Normal file
283
BackendWorkerService/Services/Implement/TyphoonApi.cs
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
// <auto-generated />
|
||||||
|
//
|
||||||
|
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
||||||
|
//
|
||||||
|
// using QuickType;
|
||||||
|
//
|
||||||
|
// var welcome = Welcome.FromJson(jsonString);
|
||||||
|
|
||||||
|
namespace TyphoonApi
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
[JsonProperty("?xml")]
|
||||||
|
public Xml Xml { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("alert")]
|
||||||
|
public Alert Alert { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Alert
|
||||||
|
{
|
||||||
|
[JsonProperty("@xmlns")]
|
||||||
|
public string Xmlns { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("identifier")]
|
||||||
|
public string Identifier { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sender")]
|
||||||
|
public string Sender { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("sent")]
|
||||||
|
public DateTimeOffset Sent { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("status")]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("msgType")]
|
||||||
|
public string MsgType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("scope")]
|
||||||
|
public string Scope { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("references")]
|
||||||
|
public string References { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("info")]
|
||||||
|
public Info Info { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Info
|
||||||
|
{
|
||||||
|
[JsonProperty("language")]
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("category")]
|
||||||
|
public string Category { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("event")]
|
||||||
|
public string Event { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("responseType")]
|
||||||
|
public string ResponseType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("urgency")]
|
||||||
|
public string Urgency { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("severity")]
|
||||||
|
public string Severity { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("certainty")]
|
||||||
|
public string Certainty { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("eventCode")]
|
||||||
|
public EventCode EventCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("effective")]
|
||||||
|
public DateTimeOffset Effective { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("onset")]
|
||||||
|
public DateTimeOffset Onset { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("expires")]
|
||||||
|
public DateTimeOffset Expires { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("senderName")]
|
||||||
|
public string SenderName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("headline")]
|
||||||
|
public string Headline { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public Description Description { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("web")]
|
||||||
|
public Uri Web { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("parameter")]
|
||||||
|
public EventCode[] Parameter { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("area")]
|
||||||
|
public Area[] Area { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Area
|
||||||
|
{
|
||||||
|
[JsonProperty("areaDesc")]
|
||||||
|
public string AreaDesc { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("polygon")]
|
||||||
|
public string Polygon { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Description
|
||||||
|
{
|
||||||
|
[JsonProperty("typhoon-info")]
|
||||||
|
public TyphoonInfo TyphoonInfo { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("section")]
|
||||||
|
public DescriptionSection[] Section { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class DescriptionSection
|
||||||
|
{
|
||||||
|
[JsonProperty("@title")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("#text")]
|
||||||
|
public string Text { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class TyphoonInfo
|
||||||
|
{
|
||||||
|
[JsonProperty("section")]
|
||||||
|
public TyphoonInfoSection[] Section { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class TyphoonInfoSection
|
||||||
|
{
|
||||||
|
[JsonProperty("@title")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("#text", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("typhoon_name", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string TyphoonName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("cwb_typhoon_name", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string CwbTyphoonName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("analysis", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public Analysis Analysis { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("prediction", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public Analysis Prediction { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Analysis
|
||||||
|
{
|
||||||
|
[JsonProperty("time")]
|
||||||
|
public DateTimeOffset Time { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("position")]
|
||||||
|
public string Position { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("max_winds")]
|
||||||
|
public Gust MaxWinds { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("gust")]
|
||||||
|
public Gust Gust { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("pressure")]
|
||||||
|
public Gust Pressure { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("radius_of_15mps")]
|
||||||
|
public Gust RadiusOf15Mps { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("scale", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public Scale[] Scale { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Gust
|
||||||
|
{
|
||||||
|
[JsonProperty("@unit")]
|
||||||
|
public string Unit { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("#text")]
|
||||||
|
[JsonConverter(typeof(ParseStringConverter))]
|
||||||
|
public long Text { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Scale
|
||||||
|
{
|
||||||
|
[JsonProperty("@lang")]
|
||||||
|
public string Lang { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("#text")]
|
||||||
|
public string Text { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EventCode
|
||||||
|
{
|
||||||
|
[JsonProperty("valueName")]
|
||||||
|
public string ValueName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("value")]
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Xml
|
||||||
|
{
|
||||||
|
[JsonProperty("@version")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("@encoding")]
|
||||||
|
public string Encoding { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class Welcome
|
||||||
|
{
|
||||||
|
public static Welcome FromJson(string json) => JsonConvert.DeserializeObject<Welcome>(json, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serialize
|
||||||
|
{
|
||||||
|
public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Converter
|
||||||
|
{
|
||||||
|
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||||
|
DateParseHandling = DateParseHandling.None,
|
||||||
|
Converters =
|
||||||
|
{
|
||||||
|
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ParseStringConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null) return null;
|
||||||
|
var value = serializer.Deserialize<string>(reader);
|
||||||
|
long l;
|
||||||
|
if (Int64.TryParse(value, out l))
|
||||||
|
{
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
throw new Exception("Cannot unmarshal type long");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (untypedValue == null)
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = (long)untypedValue;
|
||||||
|
serializer.Serialize(writer, value.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly ParseStringConverter Singleton = new ParseStringConverter();
|
||||||
|
}
|
||||||
|
}
|
@ -7,13 +7,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BackgroundServiceCron": {
|
"BackgroundServiceCron": {
|
||||||
"ExecutionBackgroundServicePlanJob": "0 0 1 * * ?",
|
"ExecutionBackgroundServicePlanJob": "0 0 2 * * ?",
|
||||||
"MessageNotificationJob": "0 0 1 * * ?",
|
"MessageNotificationJob": "0 0 2 * * ?",
|
||||||
"DataDeliveryJob": "0 0 1 * * ?",
|
"DataDeliveryJob": "0 0 2 * * ?",
|
||||||
"RegularUpdateDBTableJob": "0 0 1 * * ?",
|
"RegularUpdateDBTableJob": "0 0 2 * * ?",
|
||||||
"ParkingJob": "0 0 1 * * ?",
|
"ParkingJob": "0 0 2 * * ?",
|
||||||
"ArchiveElectricMeterHourJob": "0 0 1 * * ?",
|
"ArchiveElectricMeterHourJob": "0 0 2 * * ?",
|
||||||
"ArchiveElectricMeterDayJob": "0 0 1 * * ?",
|
"ArchiveElectricMeterDayJob": "0 0 2 * * ?",
|
||||||
"WeatherAPIJob": "0/5 * * * * ?"
|
"WeatherAPIJob": "0/5 * * * * ?"
|
||||||
},
|
},
|
||||||
"DBConfig": {
|
"DBConfig": {
|
||||||
|
@ -1,192 +1,526 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
|
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
|
||||||
|
|
||||||
<identifier>CWB-Weather_extremely-rain_202305081515001</identifier>
|
<identifier>CWB-Weather_extremely-rain_202306010655001</identifier>
|
||||||
<sender>weather@cwb.gov.tw</sender>
|
<sender>weather@cwb.gov.tw</sender>
|
||||||
<sent>2023-05-08T15:21:31+08:00</sent>
|
<sent>2023-06-01T07:02:17+08:00</sent>
|
||||||
<status>Actual</status>
|
<status>Actual</status>
|
||||||
<msgType>Cancel</msgType>
|
<msgType>Update</msgType>
|
||||||
<scope>Public</scope>
|
<scope>Public</scope>
|
||||||
<references>weather@cwb.gov.tw,CWB-Weather_extremely-rain_202305081030001,2023-05-08T10:37:48+08:00 weather@cwb.gov.tw,CWB-Weather_extremely-rain_202305080840001,2023-05-08T08:51:11+08:00</references>
|
<references>weather@cwb.gov.tw,CWB-Weather_extremely-rain_202306010345001,2023-06-01T03:56:19+08:00</references>
|
||||||
<info>
|
<info>
|
||||||
<language>zh-TW</language>
|
<language>zh-TW</language>
|
||||||
<category>Met</category>
|
<category>Met</category>
|
||||||
<event>降雨</event>
|
<event>降雨</event>
|
||||||
<urgency>Past</urgency>
|
<responseType>Monitor</responseType>
|
||||||
<severity>Minor</severity>
|
<urgency>Future</urgency>
|
||||||
<certainty>Observed</certainty>
|
<severity>Moderate</severity>
|
||||||
|
<certainty>Likely</certainty>
|
||||||
<eventCode>
|
<eventCode>
|
||||||
<valueName>profile:CAP-TWP:Event:1.0</valueName>
|
<valueName>profile:CAP-TWP:Event:1.0</valueName>
|
||||||
<value>rainfall</value>
|
<value>rainfall</value>
|
||||||
</eventCode>
|
</eventCode>
|
||||||
<effective>2023-05-08T15:15:00+08:00</effective>
|
<effective>2023-06-01T06:55:00+08:00</effective>
|
||||||
<onset>2023-05-08T15:17:00+08:00</onset>
|
<onset>2023-06-01T06:59:00+08:00</onset>
|
||||||
<expires>2023-05-08T15:31:31+08:00</expires>
|
<expires>2023-06-01T11:00:00+08:00</expires>
|
||||||
<senderName>中央氣象局</senderName>
|
<senderName>中央氣象局</senderName>
|
||||||
<headline>解除大雨特報</headline>
|
<headline>大雨特報</headline>
|
||||||
<description>
|
<description>
|
||||||
由於降雨趨於緩和,發生大雨的機率降低,故解除大雨特報;今(8)日屏東及臺東山區仍有局部較大雨勢發生,請注意。
|
颱風外圍環流影響,今(1)日大臺北、桃園、新竹、宜蘭地區有局部大雨發生的機率,請注意瞬間大雨、強陣風及溪水暴漲,山區請注意落石及坍方。
|
||||||
</description>
|
</description>
|
||||||
<instruction></instruction>
|
|
||||||
<web>https://www.cwb.gov.tw/V8/C/P/Warning/FIFOWS.html</web>
|
<web>https://www.cwb.gov.tw/V8/C/P/Warning/FIFOWS.html</web>
|
||||||
<parameter>
|
<parameter>
|
||||||
<valueName>alert_title</valueName>
|
<valueName>alert_title</valueName>
|
||||||
<value>大雨特報</value>
|
<value>大雨特報</value>
|
||||||
</parameter>
|
</parameter>
|
||||||
|
<parameter>
|
||||||
|
<valueName>severity_level</valueName>
|
||||||
|
<value>大雨</value>
|
||||||
|
</parameter>
|
||||||
|
<parameter>
|
||||||
|
<valueName>alert_color</valueName>
|
||||||
|
<value>黃色</value>
|
||||||
|
</parameter>
|
||||||
|
<parameter>
|
||||||
|
<valueName>website_color</valueName>
|
||||||
|
<value>255,255,0</value>
|
||||||
|
</parameter>
|
||||||
|
|
||||||
<area>
|
<area>
|
||||||
<areaDesc>基隆市</areaDesc>
|
<areaDesc>新竹縣橫山鄉</areaDesc>
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10017</value>
|
<value>1000408</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>新竹縣北埔鄉</areaDesc>
|
||||||
<areaDesc>臺北市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>63</value>
|
<value>1000409</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>桃園市觀音區</areaDesc>
|
||||||
<areaDesc>新北市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>65</value>
|
<value>6801200</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>桃園市復興區</areaDesc>
|
||||||
<areaDesc>桃園市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>68</value>
|
<value>6801300</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>臺北市信義區</areaDesc>
|
||||||
<areaDesc>新竹市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10018</value>
|
<value>6300200</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>桃園市新屋區</areaDesc>
|
||||||
<areaDesc>新竹縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10004</value>
|
<value>6801100</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>新竹縣竹東鎮</areaDesc>
|
||||||
<areaDesc>苗栗縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10005</value>
|
<value>1000402</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>臺北市文山區</areaDesc>
|
||||||
<areaDesc>臺中市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>66</value>
|
<value>6300800</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>新竹縣竹北市</areaDesc>
|
||||||
<areaDesc>彰化縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10007</value>
|
<value>1000401</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>新竹縣新豐鄉</areaDesc>
|
||||||
<areaDesc>雲林縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10009</value>
|
<value>1000406</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>臺北市松山區</areaDesc>
|
||||||
<areaDesc>南投縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10008</value>
|
<value>6300100</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>新竹縣關西鎮</areaDesc>
|
||||||
<areaDesc>嘉義縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10010</value>
|
<value>1000404</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>新竹縣湖口鄉</areaDesc>
|
||||||
<areaDesc>嘉義市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10020</value>
|
<value>1000405</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣冬山鄉</areaDesc>
|
||||||
<areaDesc>臺南市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>67</value>
|
<value>1000208</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣五結鄉</areaDesc>
|
||||||
<areaDesc>高雄市</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>64</value>
|
<value>1000209</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣頭城鎮</areaDesc>
|
||||||
<areaDesc>屏東縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10013</value>
|
<value>1000204</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣礁溪鄉</areaDesc>
|
||||||
<areaDesc>宜蘭縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10002</value>
|
<value>1000205</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣壯圍鄉</areaDesc>
|
||||||
<areaDesc>花蓮縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10015</value>
|
<value>1000206</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣員山鄉</areaDesc>
|
||||||
<areaDesc>臺東縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10014</value>
|
<value>1000207</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣宜蘭市</areaDesc>
|
||||||
<areaDesc>澎湖縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>10016</value>
|
<value>1000201</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>宜蘭縣羅東鎮</areaDesc>
|
||||||
<areaDesc>金門縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>09020</value>
|
<value>1000202</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area><area>
|
||||||
<area>
|
<areaDesc>臺北市大安區</areaDesc>
|
||||||
<areaDesc>連江縣</areaDesc>
|
|
||||||
<geocode>
|
<geocode>
|
||||||
<valueName>Taiwan_Geocode_103</valueName>
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
<value>09007</value>
|
<value>6300300</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市三重區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500200</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市中和區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500300</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新竹縣尖石鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000412</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市板橋區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500100</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市新店區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500600</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市樹林區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500700</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市永和區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500400</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市新莊區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500500</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市鶯歌區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500800</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市三峽區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6500900</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市萬里區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502800</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市中山區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6300400</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市烏來區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502900</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>宜蘭縣大同鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000211</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新竹縣新埔鎮</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000403</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市坪林區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502000</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市三芝區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502100</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市石門區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502200</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市大園區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800600</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市平溪區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502400</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市雙溪區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502500</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市貢寮區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502600</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市金山區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502700</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市大同區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6300600</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市士林區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6301100</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市中正區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6300500</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>宜蘭縣三星鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000210</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新竹縣峨眉鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000411</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市北投區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6301200</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新竹縣五峰鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000413</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新竹縣芎林鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000407</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市龍潭區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800900</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市八德區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800800</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>宜蘭縣蘇澳鎮</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000203</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市桃園區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800100</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市大溪區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800300</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市萬華區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6300700</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市蘆竹區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800500</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市楊梅區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800400</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市龜山區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800700</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市內湖區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6301000</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市五股區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501500</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市蘆洲區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501400</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市林口區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501700</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市泰山區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501600</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市汐止區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501100</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>臺北市南港區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6300900</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市土城區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501300</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市瑞芳區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501200</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>宜蘭縣南澳鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000212</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市中壢區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6800200</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市石碇區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501900</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市深坑區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501800</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>桃園市平鎮區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6801000</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新竹縣寶山鄉</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>1000410</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市淡水區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6501000</value>
|
||||||
|
</geocode>
|
||||||
|
</area><area>
|
||||||
|
<areaDesc>新北市八里區</areaDesc>
|
||||||
|
<geocode>
|
||||||
|
<valueName>Taiwan_Geocode_103</valueName>
|
||||||
|
<value>6502300</value>
|
||||||
</geocode>
|
</geocode>
|
||||||
</area>
|
</area>
|
||||||
</info>
|
</info>
|
||||||
|
|
||||||
</alert>
|
</alert>
|
@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
|
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
|
||||||
|
|
||||||
<identifier>CWB-Weather_typhoon-warning_202210162030001</identifier>
|
<identifier>CWB-Weather_typhoon-warning_202305311730001</identifier>
|
||||||
<sender>weather@cwb.gov.tw</sender>
|
<sender>weather@cwb.gov.tw</sender>
|
||||||
<sent>2022-10-16T20:20:41+08:00</sent>
|
<sent>2023-05-31T17:17:30+08:00</sent>
|
||||||
<status>Actual</status>
|
<status>Actual</status>
|
||||||
<msgType>Cancel</msgType>
|
<msgType>Cancel</msgType>
|
||||||
<scope>Public</scope>
|
<scope>Public</scope>
|
||||||
<references>weather@cwb.gov.tw,CWB-Weather_typhoon-warning_202210161730001,2022-10-16T17:20:00+08:00</references>
|
<references>weather@cwb.gov.tw,CWB-Weather_typhoon-warning_202305311430001,2023-05-31T14:22:23+08:00</references>
|
||||||
<info>
|
<info>
|
||||||
<language>zh-TW</language>
|
<language>zh-TW</language>
|
||||||
<category>Met</category>
|
<category>Met</category>
|
||||||
@ -19,17 +19,17 @@
|
|||||||
<valueName>profile:CAP-TWP:Event:1.0</valueName>
|
<valueName>profile:CAP-TWP:Event:1.0</valueName>
|
||||||
<value>typhoon</value>
|
<value>typhoon</value>
|
||||||
</eventCode>
|
</eventCode>
|
||||||
<effective>2022-10-16T20:30:00+08:00</effective>
|
<effective>2023-05-31T17:30:00+08:00</effective>
|
||||||
<onset>2022-10-16T20:30:00+08:00</onset>
|
<onset>2023-05-31T17:30:00+08:00</onset>
|
||||||
<expires>2022-10-16T20:40:00+08:00</expires>
|
<expires>2023-05-31T17:40:00+08:00</expires>
|
||||||
<senderName>中央氣象局</senderName>
|
<senderName>中央氣象局</senderName>
|
||||||
<headline>解除颱風警報</headline>
|
<headline>解除颱風警報</headline>
|
||||||
<description>
|
<description>
|
||||||
[颱風動態]
|
[颱風動態]
|
||||||
根據最新資料顯示,第20號颱風已增強為中度颱風,中心目前在鵝鑾鼻西南方海面,向西南西移動,對巴士海峽近海的威脅已解除。
|
根據最新資料顯示,第2號颱風暴風半徑略為縮小,中心目前在鵝鑾鼻東北東方海面,向北北東轉東北移動,對巴士海峽及臺灣東半部近海威脅已解除。
|
||||||
|
|
||||||
[注意事項]
|
[注意事項]
|
||||||
*今(16日)晚至明(17)日巴士海峽及臺灣附近各海面風浪仍偏大,各沿海地區(含蘭嶼、綠島)及澎湖、金門、馬祖有長浪發生的機率,請避免前往海邊活動。*今(16日)晚雲林以北、恆春半島沿海空曠地區及澎湖、馬祖易有9至10級強陣風,東半部、嘉義、臺南沿海空曠地區及蘭嶼、綠島、金門亦有較強陣風;明(17)日臺南以北沿海空曠地區、蘭嶼、綠島、澎湖、金門、馬祖易有9至12級強陣風,東半部沿海地區及西半部地區有8至9級強陣風,路樹、懸掛物、招牌等物品宜加強固定,外出活動、機車騎士行車或行經高架橋車輛,請特別注意安全。*自15日0時至16日20時出現較大累積雨量如下:臺北市擎天崗989.0毫米,宜蘭縣樂水分校973.5毫米,新北市汐止579.5毫米,基隆市五堵578.0毫米,桃園市嘎拉賀555.0毫米,新竹縣西丘斯山478.0毫米,臺中市南湖圈谷394.5毫米,花蓮縣和平林道361.0毫米。*本警報單之颱風半徑為平均半徑,第20號颱風之7級風暴風半徑北半象限約220公里,南半象限約180公里,平均半徑約為200公里。颱風詳細特性請參考本局颱風輔助說明(https://www.cwb.gov.tw/Data/typhoon/TY_ PDF.pdf)。*此為第20號颱風警報最後一次報告。
|
*巴士海峽及臺灣附近各海面風浪明顯偏大;基隆北海岸、南部、東半部(含蘭嶼、綠島)、恆春半島沿海及澎湖、馬祖易有長浪發生,尤其東半部(含蘭嶼、綠島)、基隆北海岸、恆春半島沿海易有4至5米浪高,請避免前往海邊活動。*陸上強風特報:今(31)日臺南至苗栗沿海空曠地區及澎湖、蘭嶼、綠島易有9至10級強陣風,新竹以北、基隆北海岸、東半部沿海空曠地區、臺南至苗栗地區、恆春半島、金門、馬祖亦有較強陣風,請特別注意。*30日0時至31日17時出現較大累積雨量如下:宜蘭縣翠峰湖334.5毫米,臺中市南湖圈谷257.0毫米。*本警報單之颱風半徑為平均半徑,第2號颱風之7級風暴風半徑近似正圓,平均半徑約為280公里。颱風詳細特性請參考本局颱輔助說明(https://www.cwb.gov.tw/Data/typhoon/TY_PDF.pdf)。*此為第2號颱風警報最後一次報告。
|
||||||
|
|
||||||
</description>
|
</description>
|
||||||
<instruction></instruction>
|
<instruction></instruction>
|
||||||
|
@ -218,6 +218,10 @@
|
|||||||
pageAct.alrSelSysSub = [];
|
pageAct.alrSelSysSub = [];
|
||||||
pageAct.selAllSysSub = false;
|
pageAct.selAllSysSub = false;
|
||||||
first = true;
|
first = true;
|
||||||
|
let dataAlarm = [];
|
||||||
|
var historyTable = null;
|
||||||
|
var elemIndex = 0;
|
||||||
|
var index = 0;
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
initDropzone();
|
initDropzone();
|
||||||
@ -247,13 +251,12 @@
|
|||||||
// console.log(this);
|
// console.log(this);
|
||||||
pageAct.selAllSysSub = true;
|
pageAct.selAllSysSub = true;
|
||||||
|
|
||||||
|
//$.each($('input[type=checkbox][data-type=sub]:checked'), function (i, v) {
|
||||||
$.each($('input[type=checkbox][data-type=sub]:checked'), function (i, v) {
|
// $(v).click();
|
||||||
$(v).click();
|
//});
|
||||||
});
|
|
||||||
|
|
||||||
if (pageAct.SysType == "all") {
|
if (pageAct.SysType == "all") {
|
||||||
if (!$(this).is(':checked')) {
|
if ($(this).is(':checked')) {
|
||||||
$(this).prop('checked', true);
|
$(this).prop('checked', true);
|
||||||
$(this).click();
|
$(this).click();
|
||||||
}
|
}
|
||||||
@ -595,7 +598,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function selAllSysVal(elem) {
|
function selAllSysVal(elem) {
|
||||||
$(loadEle).Loading("start");
|
|
||||||
pageAct.selAllSysSub = true;
|
pageAct.selAllSysSub = true;
|
||||||
if ($(elem).html() == '全選類別') {
|
if ($(elem).html() == '全選類別') {
|
||||||
$('#alr_mainList input').map(function (i, v) {
|
$('#alr_mainList input').map(function (i, v) {
|
||||||
@ -630,6 +632,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getData(type = null) {
|
function getData(type = null) {
|
||||||
|
dataAlarm = [];
|
||||||
|
$(loadEle).Loading("start");
|
||||||
let enddate = new Date(new Date().setDate(new Date(pageAct.alr_enddate).getDate() + 1)).getTime();
|
let enddate = new Date(new Date().setDate(new Date(pageAct.alr_enddate).getDate() + 1)).getTime();
|
||||||
|
|
||||||
if (pageAct.SysType == "all") {
|
if (pageAct.SysType == "all") {
|
||||||
@ -637,19 +641,42 @@
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let elem = $('input[type=checkbox][data-type=sub]:checked');
|
let elem = $('input[type=checkbox][data-type=sub]:checked');
|
||||||
if (elem[0]?.id === "other") {
|
elemIndex = 0;
|
||||||
console.log(elem[0]?.id)
|
index = 0;
|
||||||
getOtherAlarmByBaja(new Date(pageAct.alr_startdate).getTime(), enddate, pageAct.return, pageAct.confirm, callBackFromAllDeviceAlert);
|
if (elem && elem.length > 0) {
|
||||||
return
|
elemIndex = elem.length;
|
||||||
|
elem.each(function (i, v) {
|
||||||
|
if (v?.id === "other") {
|
||||||
|
console.log(v?.id)
|
||||||
|
getOtherAlarmByBaja(new Date(pageAct.alr_startdate).getTime(), enddate, pageAct.return, pageAct.confirm, stackData);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pageAct.selSysMain = $(v).parent().data('main');
|
||||||
|
pageAct.selSysSub = $(v).prop('id');
|
||||||
|
getAlarmByBaja(new Date(pageAct.alr_startdate).getTime(), enddate, pageAct.return, pageAct.confirm, pageAct.selSysMain + "_" + pageAct.selSysSub + "_AlarmClass", stackData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#alertTable').DataTable().clear().draw();
|
||||||
|
$(loadEle).Loading("close");
|
||||||
}
|
}
|
||||||
pageAct.selSysMain = $(elem).parent().data('main');
|
|
||||||
pageAct.selSysSub = $(elem).prop('id');
|
|
||||||
getAlarmByBaja(new Date(pageAct.alr_startdate).getTime(), enddate, pageAct.return, pageAct.confirm, pageAct.selSysMain + "_" + pageAct.selSysSub + "_AlarmClass", callBackFromOneDeviceAlert);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stackData(res) {
|
||||||
|
res.data.forEach(v => {
|
||||||
|
dataAlarm.push(v);
|
||||||
|
});
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (elemIndex == index)
|
||||||
|
callBackFromOneDeviceAlert(dataAlarm);
|
||||||
|
}
|
||||||
|
|
||||||
function callBackFromAllDeviceAlert(res) {
|
function callBackFromAllDeviceAlert(res) {
|
||||||
refTable(res.data);
|
AlertList(res.data);
|
||||||
|
|
||||||
if (historyTable != null) {
|
if (historyTable != null) {
|
||||||
let t = $('#alertTable').dataTable();
|
let t = $('#alertTable').dataTable();
|
||||||
|
|
||||||
@ -657,31 +684,23 @@
|
|||||||
if (res.data.length > 0)
|
if (res.data.length > 0)
|
||||||
t.fnAddData(res.data);
|
t.fnAddData(res.data);
|
||||||
}
|
}
|
||||||
$(loadEle).Loading("close");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function callBackFromOneDeviceAlert(res) {
|
function callBackFromOneDeviceAlert(res) {
|
||||||
//res = JSON.parse(res);
|
AlertList(res);
|
||||||
refTable(res.data);
|
|
||||||
if (historyTable != null) {
|
if (historyTable != null) {
|
||||||
let t = $('#alertTable').dataTable();
|
let t = $('#alertTable').dataTable();
|
||||||
|
|
||||||
t.fnClearTable();
|
t.fnClearTable();
|
||||||
if (res.data.length > 0)
|
if (res.length > 0)
|
||||||
t.fnAddData(res.data);
|
t.fnAddData(res);
|
||||||
}
|
}
|
||||||
$(loadEle).Loading("close");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function refTable(data) {
|
function refTable(data) {
|
||||||
console.log(data)
|
|
||||||
let tag = "#alertTable";
|
let tag = "#alertTable";
|
||||||
|
|
||||||
$.each(data, function (i, v) {
|
|
||||||
// console.log(v.uuid.$val, v.uuid)
|
|
||||||
v.formId = AlertList(v.uuid.$val || v.uuid);
|
|
||||||
});
|
|
||||||
|
|
||||||
let column_defs = [
|
let column_defs = [
|
||||||
{ "targets": [0], "width": "5%", "sortable": true },
|
{ "targets": [0], "width": "5%", "sortable": true },
|
||||||
{ "targets": [1], "width": "5%", "sortable": true },
|
{ "targets": [1], "width": "5%", "sortable": true },
|
||||||
@ -759,19 +778,25 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
historyTable = new YourTeam.JqDataTables.getTableByStatic(tag, data, columns, column_defs, null, null, null, null, "tpi");
|
historyTable = new YourTeam.JqDataTables.getTableByStatic(tag, data, columns, column_defs, null, null, null, null, "tpi");
|
||||||
|
$(loadEle).Loading("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertList(errCode) {
|
function AlertList(data) {
|
||||||
objSendData.Data = { uuid: errCode };
|
objSendData.Data = [];
|
||||||
let a = null
|
$.each(data, function (i, v) {
|
||||||
|
objSendData.Data.push({ uuid: v.uuid.$val || v.uuid })
|
||||||
|
});
|
||||||
|
|
||||||
url = baseApiUrl + "/Alert/AlertList";
|
url = baseApiUrl + "/Alert/AlertList";
|
||||||
ytAjax = new YourTeam.Ajax(url, objSendData, function (rel) {
|
ytAjax = new YourTeam.Ajax(url, objSendData, function (rel) {
|
||||||
if (rel.code == "0000")
|
if (rel.code == "0000") {
|
||||||
a = rel.data;
|
$.each(rel.data, function (i, v) {
|
||||||
// console.log(rel)
|
let index = data.findIndex(x => (x.uuid.$val || x.uuid) === v.uuid);
|
||||||
|
data[index].formId = v.formId;
|
||||||
|
});
|
||||||
|
refTable(data)
|
||||||
|
}
|
||||||
}, null, "POST").send();
|
}, null, "POST").send();
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function selDevice() {
|
function selDevice() {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -337,7 +337,7 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
function getGraCatList(callback) {
|
function getGraCatList(callback) {
|
||||||
let url = baseApiUrl + "/GraphManage/VarList";
|
let url = baseApiUrl + "/GraphManage/GraphManageTreeList";
|
||||||
|
|
||||||
ytAjax = new YourTeam.Ajax(url, null, function (res) {
|
ytAjax = new YourTeam.Ajax(url, null, function (res) {
|
||||||
if (!res || res.code != "0000" || !res.data) {
|
if (!res || res.code != "0000" || !res.data) {
|
||||||
|
@ -264,9 +264,9 @@
|
|||||||
function getData(start = null, end = null) {
|
function getData(start = null, end = null) {
|
||||||
var sdt = new Date();
|
var sdt = new Date();
|
||||||
var edt = new Date(new Date().setDate(sdt.getDate() + 1));
|
var edt = new Date(new Date().setDate(sdt.getDate() + 1));
|
||||||
|
$(loadEle).Loading("start");
|
||||||
start = start ?? sdt.toLocaleDateString();
|
start = start ?? sdt.toLocaleDateString();
|
||||||
end = end ?? edt.toLocaleDateString();
|
end = end ?? edt.toLocaleDateString();
|
||||||
$(loadEle).Loading("start");
|
|
||||||
callBackFromHistory()
|
callBackFromHistory()
|
||||||
getHistoryDataByBaja(pageAct.deviceNumber + "_" + pageAct.deviceItem,
|
getHistoryDataByBaja(pageAct.deviceNumber + "_" + pageAct.deviceItem,
|
||||||
new Date(start).getTime(),
|
new Date(start).getTime(),
|
||||||
@ -363,7 +363,7 @@
|
|||||||
let start = new Date($('#his_startdate').val());
|
let start = new Date($('#his_startdate').val());
|
||||||
let end = new Date(new Date().setDate(new Date($('#his_enddate input').val()).getDate() + 1));
|
let end = new Date(new Date().setDate(new Date($('#his_enddate input').val()).getDate() + 1));
|
||||||
|
|
||||||
if (pageAct.dateType == "day")
|
if (pageAct.dateType == "today")
|
||||||
end = new Date(new Date().setDate(start.getDate() + 1));
|
end = new Date(new Date().setDate(start.getDate() + 1));
|
||||||
else if (pageAct.dateType == "month") {
|
else if (pageAct.dateType == "month") {
|
||||||
start = new Date($('#getmonth').val());
|
start = new Date($('#getmonth').val());
|
||||||
@ -394,48 +394,49 @@
|
|||||||
v.type = pageAct.devicePoiName.split(" ")[0];
|
v.type = pageAct.devicePoiName.split(" ")[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
let tag = "#historyTable";
|
let tag = "#historyTable";
|
||||||
|
|
||||||
let column_defs = [
|
let column_defs = [
|
||||||
{ "targets": [0], "width": "20%", "sortable": true },
|
{ "targets": [0], "width": "20%", "sortable": true },
|
||||||
{ "targets": [1], "width": "20%", "sortable": true },
|
{ "targets": [1], "width": "20%", "sortable": true },
|
||||||
{ "targets": [2], "width": "20%", "sortable": true }
|
{ "targets": [2], "width": "20%", "sortable": true }
|
||||||
];
|
];
|
||||||
|
|
||||||
let columns = [
|
let columns = [
|
||||||
{
|
{
|
||||||
"title": "類別",
|
"title": "類別",
|
||||||
"data": "type"
|
"data": "type"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "設備名稱",
|
"title": "設備名稱",
|
||||||
"data": "deviceName",
|
"data": "deviceName",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "數值",
|
"title": "數值",
|
||||||
"data": "value",
|
"data": "value",
|
||||||
"render": function (data) {
|
"render": function (data) {
|
||||||
if (isNaN(data.toString())) {
|
if (isNaN(data.toString())) {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
return data.roundDecimal(2);
|
return data.roundDecimal(2);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "紀錄時間",
|
"title": "紀錄時間",
|
||||||
"data": "timestamp",
|
"data": "timestamp",
|
||||||
"render": function (data) {
|
"render": function (data) {
|
||||||
// console.log(data)
|
// console.log(data)
|
||||||
return displayDate(data, "datetime");
|
return displayDate(data, "datetime");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
historyTable = new YourTeam.JqDataTables.getTableByStatic(tag, data, columns, column_defs, null, null, null, null, "tpi");
|
historyTable = new YourTeam.JqDataTables.getTableByStatic(tag, data, columns, column_defs, null, null, null, null, "tpi");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportExcel() {
|
function exportExcel() {
|
||||||
|
$(loadEle).Loading("start");
|
||||||
let url = baseApiUrl + "/History/OpeExportExcel";
|
let url = baseApiUrl + "/History/OpeExportExcel";
|
||||||
objSendData.Data = $('#historyTable').dataTable().fnGetData();
|
objSendData.Data = $('#historyTable').dataTable().fnGetData();
|
||||||
|
|
||||||
@ -444,10 +445,11 @@
|
|||||||
v.endtime = $('#his_enddate input').val() === "" ? null : new Date($('#his_enddate input').val());
|
v.endtime = $('#his_enddate input').val() === "" ? null : new Date($('#his_enddate input').val());
|
||||||
v.dateType = pageAct.dateType;
|
v.dateType = pageAct.dateType;
|
||||||
});
|
});
|
||||||
|
|
||||||
ytAjax = new YourTeam.Ajax(url, objSendData, function (rel) {
|
ytAjax = new YourTeam.Ajax(url, objSendData, function (rel) {
|
||||||
if (rel.code == "0000")
|
if (rel.code == "0000") {
|
||||||
location.href = baseApiUrl + "/api/df?path=" + rel.data.split('/')[0] + "&fileName=" + rel.data.split('/')[1] + "&token=" + cookies.get("JWT-Authorization");
|
location.href = baseApiUrl + "/api/df?path=" + rel.data.split('/')[0] + "&fileName=" + rel.data.split('/')[1] + "&token=" + cookies.get("JWT-Authorization");
|
||||||
|
}
|
||||||
}, null, "POST").send();
|
}, null, "POST").send();
|
||||||
|
$(loadEle).Loading("close");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -8,22 +8,13 @@
|
|||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button type="button" onclick="setType(2)" class="btn btn-secondary waves-effect waves-themed">維修</button>
|
<button type="button" onclick="setType(2)" class="btn btn-secondary waves-effect waves-themed">維修</button>
|
||||||
<button type="button" onclick="setType(1)" class="btn btn-secondary waves-effect waves-themed">保養記錄</button>
|
<button type="button" onclick="setType(1)" class="btn btn-secondary waves-effect waves-themed">保養記錄</button>
|
||||||
<button type="button" onclick="setType(null)"
|
<button type="button" onclick="setType(null)" class="btn btn-secondary waves-effect waves-themed">廠商資料</button>
|
||||||
class="btn btn-secondary waves-effect waves-themed">
|
|
||||||
廠商資料
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="setDate" class="col-auto">
|
<div id="setDate" class="col-auto">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button onclick="setDate('tdy')" type="button"
|
<button onclick="setDate('tdy')" type="button" class="btn btn-secondary waves-effect waves-themed">今天</button>
|
||||||
class="btn btn-secondary waves-effect waves-themed">
|
<button onclick="setDate('ytd')" type="button" class="btn btn-secondary waves-effect waves-themed">昨天</button>
|
||||||
今天
|
|
||||||
</button>
|
|
||||||
<button onclick="setDate('ytd')" type="button"
|
|
||||||
class="btn btn-secondary waves-effect waves-themed">
|
|
||||||
昨天
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
@ -69,7 +60,7 @@
|
|||||||
<a href="#" id="newForm" class="btn btn-success" data-toggle="modal" data-target="#opeFirmModal">新增</a>
|
<a href="#" id="newForm" class="btn btn-success" data-toggle="modal" data-target="#opeFirmModal">新增</a>
|
||||||
<a href="#" onclick="exportExcel()" class="btn btn-info waves-effect waves-themed">
|
<a href="#" onclick="exportExcel()" class="btn btn-info waves-effect waves-themed">
|
||||||
<span class="fal fa-file-excel mr-1"></span>
|
<span class="fal fa-file-excel mr-1"></span>
|
||||||
<span>匯出</span>
|
匯出
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<table id="opeFirmTable" class="table table-bordered table-striped text-center m-0 w-100">
|
<table id="opeFirmTable" class="table table-bordered table-striped text-center m-0 w-100">
|
||||||
@ -85,8 +76,7 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Modal center 廠商資料 -->
|
<!-- Modal center 廠商資料 -->
|
||||||
<div class="modal fade" id="opeFirmModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static"
|
<div class="modal fade" id="opeFirmModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="false">
|
||||||
data-keyboard="false">
|
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@ -162,8 +152,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal center 維修-->
|
<!-- Modal center 維修-->
|
||||||
<div class="modal fade" id="opeRecModal_2" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static"
|
<div class="modal fade" id="opeRecModal_2" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="false">
|
||||||
data-keyboard="false">
|
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@ -233,14 +222,12 @@
|
|||||||
<div class="form-control" id="inpStatus_2">
|
<div class="form-control" id="inpStatus_2">
|
||||||
<div class="row container">
|
<div class="row container">
|
||||||
<div class="">
|
<div class="">
|
||||||
<input class="custom-radio-input" type="radio" name="inpSta_2" id="inpSta_2_0" value="0"
|
<input class="custom-radio-input" type="radio" name="inpSta_2" id="inpSta_2_0" value="0" data-value="0" checked>
|
||||||
data-value="0" checked>
|
|
||||||
<label class="form-label" for="inpSta_0">未完成</label>
|
<label class="form-label" for="inpSta_0">未完成</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
<input class="custom-radio-input" type="radio" name="inpSta_2" id="inpSta_2_1" value="1"
|
<input class="custom-radio-input" type="radio" name="inpSta_2" id="inpSta_2_1" value="1" data-value="1">
|
||||||
data-value="1">
|
|
||||||
<label class="form-label" for="inpSta_1">完成</label>
|
<label class="form-label" for="inpSta_1">完成</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -264,8 +251,7 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="inpDescription_2">結果描述</label>
|
<label class="form-label" for="inpDescription_2">結果描述</label>
|
||||||
<textarea class="form-control" type="text" id="inpDescription_2" name="inpDescription_2"
|
<textarea class="form-control" type="text" id="inpDescription_2" name="inpDescription_2" rows="7"></textarea>
|
||||||
rows="7"></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@ -302,8 +288,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal center 保養 -->
|
<!-- Modal center 保養 -->
|
||||||
<div class="modal fade" id="opeRecModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static"
|
<div class="modal fade" id="opeRecModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="false">
|
||||||
data-keyboard="false">
|
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@ -365,14 +350,12 @@
|
|||||||
<div class="form-control" id="inpStatus">
|
<div class="form-control" id="inpStatus">
|
||||||
<div class="row container">
|
<div class="row container">
|
||||||
<div class="">
|
<div class="">
|
||||||
<input class="custom-radio-input" type="radio" name="inpSta" id="inpSta_0" data-value="0"
|
<input class="custom-radio-input" type="radio" name="inpSta" id="inpSta_0" data-value="0" value="0" checked>
|
||||||
value="0" checked>
|
|
||||||
<label class="form-label" for="inpSta_0">未完成</label>
|
<label class="form-label" for="inpSta_0">未完成</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
<input class="custom-radio-input" type="radio" name="inpSta" id="inpSta_1" data-value="1"
|
<input class="custom-radio-input" type="radio" name="inpSta" id="inpSta_1" data-value="1" value="1">
|
||||||
value="1">
|
|
||||||
<label class="form-label" for="inpSta_1">完成</label>
|
<label class="form-label" for="inpSta_1">完成</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -396,8 +379,7 @@
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="inpDescription">結果描述</label>
|
<label class="form-label" for="inpDescription">結果描述</label>
|
||||||
<textarea class="form-control" type="text" id="inpDescription" name="inpDescription"
|
<textarea class="form-control" type="text" id="inpDescription" name="inpDescription" rows="7"></textarea>
|
||||||
rows="7"></textarea>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@ -434,8 +416,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal center 刪除 -->
|
<!-- Modal center 刪除 -->
|
||||||
<div class="modal fade" id="delModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static"
|
<div class="modal fade" id="delModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="false">
|
||||||
data-keyboard="false">
|
|
||||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@ -536,6 +517,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
function loadOpeFirmTable() {
|
function loadOpeFirmTable() {
|
||||||
|
$(loadEle).Loading("start");
|
||||||
$('#opeFirmTable_wrapper').css('display', 'block');
|
$('#opeFirmTable_wrapper').css('display', 'block');
|
||||||
$('#opeRecTable_wrapper').css('display', 'none');
|
$('#opeRecTable_wrapper').css('display', 'none');
|
||||||
$('#opeRecTable_2_wrapper').css('display', 'none');
|
$('#opeRecTable_2_wrapper').css('display', 'none');
|
||||||
@ -601,9 +583,11 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
opeFirmTable = new YourTeam.JqDataTables.getTableByAjax(ajaxObj, tag, null, columns, column_defs);
|
opeFirmTable = new YourTeam.JqDataTables.getTableByAjax(ajaxObj, tag, null, columns, column_defs);
|
||||||
|
$(loadEle).Loading("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadOpeRecTable() {
|
function loadOpeRecTable() {
|
||||||
|
$(loadEle).Loading("start");
|
||||||
$('#opeFirmTable_wrapper').css('display', 'none');
|
$('#opeFirmTable_wrapper').css('display', 'none');
|
||||||
|
|
||||||
$('#serial_number').parent().parent().css('display', 'block');
|
$('#serial_number').parent().parent().css('display', 'block');
|
||||||
@ -860,6 +844,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
opeRecTable = new YourTeam.JqDataTables.getTableByAjax(ajaxObj, tag, null, columns, column_defs);
|
opeRecTable = new YourTeam.JqDataTables.getTableByAjax(ajaxObj, tag, null, columns, column_defs);
|
||||||
|
$(loadEle).Loading("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
function setType(wt) {
|
function setType(wt) {
|
||||||
@ -998,8 +983,8 @@
|
|||||||
loadOpeRecTable();
|
loadOpeRecTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportExcel(e) {
|
function exportExcel() {
|
||||||
console.log("export", e)
|
$(loadEle).Loading("start");
|
||||||
let url = baseApiUrl + "/operation/OpeExportExcel";
|
let url = baseApiUrl + "/operation/OpeExportExcel";
|
||||||
|
|
||||||
objSendData.Data = {
|
objSendData.Data = {
|
||||||
@ -1007,11 +992,12 @@
|
|||||||
startdate: pageAct.startdate == undefined ? null : pageAct.startdate,
|
startdate: pageAct.startdate == undefined ? null : pageAct.startdate,
|
||||||
enddate: pageAct.enddate == undefined ? null : pageAct.enddate,
|
enddate: pageAct.enddate == undefined ? null : pageAct.enddate,
|
||||||
};
|
};
|
||||||
console.log("data", objSendData.Data)
|
|
||||||
ytAjax = new YourTeam.Ajax(url, objSendData, function (rel) {
|
ytAjax = new YourTeam.Ajax(url, objSendData, function (rel) {
|
||||||
if (rel.code == "0000")
|
if (rel.code == "0000")
|
||||||
location.href = baseApiUrl + "/api/df?path=" + rel.data.split('/')[0] + "&fileName=" + rel.data.split('/')[1] + "&token=" + cookies.get("JWT-Authorization");
|
location.href = baseApiUrl + "/api/df?path=" + rel.data.split('/')[0] + "&fileName=" + rel.data.split('/')[1] + "&token=" + cookies.get("JWT-Authorization");
|
||||||
}, null, "POST").send();
|
}, null, "POST").send();
|
||||||
|
$(loadEle).Loading("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
function selSysMain() {
|
function selSysMain() {
|
||||||
@ -1100,7 +1086,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function selAllSysVal(elem) {
|
function selAllSysVal(elem) {
|
||||||
$(loadEle).Loading("start");
|
|
||||||
if ($(elem).html() == '全選類別') {
|
if ($(elem).html() == '全選類別') {
|
||||||
$('#mainList input').map(function (i, v) {
|
$('#mainList input').map(function (i, v) {
|
||||||
if (!$(v).is(':checked')) {
|
if (!$(v).is(':checked')) {
|
||||||
@ -1127,7 +1112,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
refTable();
|
refTable();
|
||||||
$(loadEle).Loading("close");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function event() {
|
function event() {
|
||||||
@ -1375,18 +1359,12 @@
|
|||||||
if (!res || res.code != "0000" || !res.data) {
|
if (!res || res.code != "0000" || !res.data) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
pageAct.sysMain = res.data.device_system_category_layer2;
|
|
||||||
pageAct.sysSub = res.data.device_system_category_layer3;
|
pageAct.sysSub = res.data.device_system_category_layer3;
|
||||||
pageAct.number = res.data.fix_do_code;
|
pageAct.number = res.data.fix_do_code;
|
||||||
|
selOpeFir();
|
||||||
|
errCodeList();
|
||||||
callbackForErr(JSON.stringify({
|
|
||||||
count: [res.data].length,
|
|
||||||
data: [{ uuid: res.data.error_code }]
|
|
||||||
}));
|
|
||||||
$(pageAct.work_type == "1" ? '#inpNumber' : '#inpNumber_2').val(res.data.formId);
|
$(pageAct.work_type == "1" ? '#inpNumber' : '#inpNumber_2').val(res.data.formId);
|
||||||
$(pageAct.work_type == "1" ? '#inpWorTyp' : '#inpWorTyp_2').val(res.data.work_type);
|
$(pageAct.work_type == "1" ? '#inpWorTyp' : '#inpWorTyp_2').val(res.data.work_type);
|
||||||
$(pageAct.work_type == "1" ? '#inpErrCode' : '#inpErrCode_2').val(res.data.error_code);
|
|
||||||
$(pageAct.work_type == "1" ? '#inpFixDo' : '#inpFixDo_2').val(res.data.fix_do);
|
$(pageAct.work_type == "1" ? '#inpFixDo' : '#inpFixDo_2').val(res.data.fix_do);
|
||||||
$(pageAct.work_type == "1" ? '#inpFixDoCode' : '#inpFixDoCode_2').val(res.data.fix_do_code);
|
$(pageAct.work_type == "1" ? '#inpFixDoCode' : '#inpFixDoCode_2').val(res.data.fix_do_code);
|
||||||
$(pageAct.work_type == "1" ? '#inpFixFirm' : '#inpFixFirm_2').val(res.data.fix_firm);
|
$(pageAct.work_type == "1" ? '#inpFixFirm' : '#inpFixFirm_2').val(res.data.fix_firm);
|
||||||
@ -1395,9 +1373,6 @@
|
|||||||
$(pageAct.work_type == "1" ? '#inpStaTime' : '#inpStaTime_2').val(displayDate(res.data.start_time, 'date').replaceAll('/', '-'));
|
$(pageAct.work_type == "1" ? '#inpStaTime' : '#inpStaTime_2').val(displayDate(res.data.start_time, 'date').replaceAll('/', '-'));
|
||||||
$(pageAct.work_type == "1" ? '#inpNotice' : '#inpNotice_2').val(res.data.notice);
|
$(pageAct.work_type == "1" ? '#inpNotice' : '#inpNotice_2').val(res.data.notice);
|
||||||
$(pageAct.work_type == "1" ? '#inpDescription' : '#inpDescription_2').val(res.data.description);
|
$(pageAct.work_type == "1" ? '#inpDescription' : '#inpDescription_2').val(res.data.description);
|
||||||
let elemSel = $(pageAct.work_type == "1" ? '#inpFixDoCode' : '#inpFixDoCode_2').find('option:selected');;
|
|
||||||
pageAct.number = elemSel.val();
|
|
||||||
selOpeFir();
|
|
||||||
|
|
||||||
ope_imgHtml = null;
|
ope_imgHtml = null;
|
||||||
$.each(res.data.lorf, function (i, v) {
|
$.each(res.data.lorf, function (i, v) {
|
||||||
@ -1493,18 +1468,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function callbackForErr(res) {
|
function callbackForErr(res) {
|
||||||
res = JSON.parse(res) || res;
|
res = JSON.parse(res);
|
||||||
console.log(res)
|
|
||||||
strHtml = ``;
|
strHtml = ``;
|
||||||
|
|
||||||
$.each(res.data, function (i, v) {
|
$.each(res.data, function (i, v) {
|
||||||
msg = v.msgText != null ? ($.trim(v.msgText.toString()).length > 0 ? v.msgText.split(':')[0] : '') : '';
|
msg = v.msgText != null ? ($.trim(v.msgText.toString()).length > 0 ? v.msgText.split(':')[0] : '') : '';
|
||||||
strHtml += `<option value=${v.uuid}>${v.uuid.split("-")[0]}</option>`;
|
strHtml += `<option value=${v.uuid}>${v.uuid}</option>`;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.count > 0)
|
if (res.count > 0)
|
||||||
$(pageAct.work_type == '1' ? '#inpErrCode' : '#inpErrCode_2').html(strHtml);
|
$(pageAct.work_type == '1' ? '#inpErrCode' : '#inpErrCode_2').html(strHtml);
|
||||||
else
|
|
||||||
$(pageAct.work_type == '1' ? '#inpErrCode' : '#inpErrCode_2').html("");
|
|
||||||
$(loadEle).Loading("close");
|
$(loadEle).Loading("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1964,7 +1964,7 @@
|
|||||||
|
|
||||||
})
|
})
|
||||||
.fail(function () {
|
.fail(function () {
|
||||||
toast_warning("查無該樓層地圖")
|
// toast_warning("查無該樓層地圖")
|
||||||
floChart.clear();
|
floChart.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3927
Frontend/index.html
3927
Frontend/index.html
File diff suppressed because it is too large
Load Diff
@ -910,6 +910,7 @@ async function testNewLight(dataList) {
|
|||||||
|
|
||||||
//------------------- 加入熱點 -----------------
|
//------------------- 加入熱點 -----------------
|
||||||
async function addHotPoint(data) {
|
async function addHotPoint(data) {
|
||||||
|
if (pageAct.sysMainTag == null && pageAct.sysSubTag == null) return
|
||||||
var viewer = data.target ? data.target : data;
|
var viewer = data.target ? data.target : data;
|
||||||
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
|
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
|
||||||
const DataVizCore = Autodesk.DataVisualization.Core;
|
const DataVizCore = Autodesk.DataVisualization.Core;
|
||||||
@ -922,9 +923,9 @@ async function addHotPoint(data) {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
spriteColor = new THREE.Color(0xffffff);
|
spriteColor = new THREE.Color(0xffffff);
|
||||||
spriteIcon = "/file/img/forge/hotspot.svg";
|
spriteIcon = "/file/img/forge/sensor_circle.svg";
|
||||||
if (location.href.indexOf("localhost:5966") != -1) {
|
if (location.href.indexOf("localhost:5966") != -1) {
|
||||||
spriteIcon = "/img/forge/hotspot.svg";
|
spriteIcon = "/img/forge/sensor_circle.svg";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,7 +974,7 @@ async function addHotPoint(data) {
|
|||||||
// console.log(`Sprite clicked: ${event.dbId}`);
|
// console.log(`Sprite clicked: ${event.dbId}`);
|
||||||
|
|
||||||
for (let i = dbIdStart; i <= myDataList.length + 10; i++) {
|
for (let i = dbIdStart; i <= myDataList.length + 10; i++) {
|
||||||
!alarmDbIdList.some((dbId) => dbId == i) &&
|
!alarmDbIdList.some(({ spriteDbid }) => spriteDbid == i) &&
|
||||||
pageAct.sysSubTag !== "L1" &&
|
pageAct.sysSubTag !== "L1" &&
|
||||||
changeColorForHotspot(i);
|
changeColorForHotspot(i);
|
||||||
changeScaleForHotspot(i, true);
|
changeScaleForHotspot(i, true);
|
||||||
@ -990,7 +991,7 @@ async function addHotPoint(data) {
|
|||||||
}
|
}
|
||||||
$(selector).trigger("autodesk:click:sprite", { event, myData });
|
$(selector).trigger("autodesk:click:sprite", { event, myData });
|
||||||
} else {
|
} else {
|
||||||
!alarmDbIdList.some((dbId) => dbId == i) &&
|
!alarmDbIdList.some(({ spriteDbid }) => spriteDbid == event.dbId) &&
|
||||||
pageAct.sysSubTag !== "L1" &&
|
pageAct.sysSubTag !== "L1" &&
|
||||||
changeColorForHotspot(event.dbId, null);
|
changeColorForHotspot(event.dbId, null);
|
||||||
changeScaleForHotspot(event.dbId, false);
|
changeScaleForHotspot(event.dbId, false);
|
||||||
@ -1038,25 +1039,47 @@ async function addHotPoint(data) {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//hex -> rgbsensor_circle
|
||||||
|
function hexToRgb(hex) {
|
||||||
|
return (
|
||||||
|
"rgb(" +
|
||||||
|
parseInt("0x" + hex.slice(1, 3)) +
|
||||||
|
"," +
|
||||||
|
parseInt("0x" + hex.slice(3, 5)) +
|
||||||
|
"," +
|
||||||
|
parseInt("0x" + hex.slice(5, 7)) +
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 熱點 更換顏色
|
// 熱點 更換顏色
|
||||||
async function changeColorForHotspot(dbId, type = null, lightOn = false) {
|
async function changeColorForHotspot(dbId, type = null, OnOff = false) {
|
||||||
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
|
const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
|
||||||
let spriteColorFocus = new THREE.Color(0xffffff);
|
let spriteColorFocus = new THREE.Color(0xffffff);
|
||||||
if (pageAct.sysSubTag == "L1") {
|
|
||||||
spriteColorFocus = lightOn
|
spriteColorFocus = OnOff
|
||||||
? new THREE.Color(0xffd524)
|
? pageAct.sysSubObj.device_normal_color
|
||||||
: new THREE.Color(0x40525e);
|
? new THREE.Color(hexToRgb(pageAct.sysSubObj.device_normal_color))
|
||||||
if (lightOn) {
|
: new THREE.Color(0xffffff)
|
||||||
console.log(dbId);
|
: pageAct.sysSubObj.device_close_color
|
||||||
}
|
? new THREE.Color(hexToRgb(pageAct.sysSubObj.device_close_color))
|
||||||
} else if (type == "focus" && pageAct.sysSubTag !== "M12") {
|
: new THREE.Color(0xffffff);
|
||||||
|
|
||||||
|
if (type == "focus") {
|
||||||
spriteColorFocus = new THREE.Color(0x00ffe1);
|
spriteColorFocus = new THREE.Color(0x00ffe1);
|
||||||
} else if (type == "error") {
|
} else if (type == "error") {
|
||||||
spriteColorFocus = new THREE.Color(0xff0000);
|
spriteColorFocus = new THREE.Color(
|
||||||
|
hexToRgb(pageAct.sysSubObj.device_error_color)
|
||||||
|
);
|
||||||
|
spriteErrIcon = baseForgeApiUrl + "/file/img/forge/sensor_circle.svg";
|
||||||
|
if (location.href.indexOf("localhost:5966") != -1) {
|
||||||
|
spriteErrIcon = baseForgeApiUrl + "/img/forge/sensor_circle.svg";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const viewablesToUpdate = dbId;
|
const viewablesToUpdate = dbId;
|
||||||
dataVizExtn.invalidateViewables(viewablesToUpdate, (viewable) => {
|
dataVizExtn.invalidateViewables(viewablesToUpdate, (viewable) => {
|
||||||
return {
|
return {
|
||||||
|
url: "/file/img/forge/sensor_circle.svg",
|
||||||
color: spriteColorFocus,
|
color: spriteColorFocus,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -603,7 +603,7 @@ function getOtherAlarmByBaja(startDate_millisecond, endDate_millisecond, isRecov
|
|||||||
main.ackState = record.get('ackState').$ordinal
|
main.ackState = record.get('ackState').$ordinal
|
||||||
if (_sourceTmp.includes("undefined")) {
|
if (_sourceTmp.includes("undefined")) {
|
||||||
main.buildingFloorName_zh = "無";
|
main.buildingFloorName_zh = "無";
|
||||||
main.alarmClass = "系統/設備異常";
|
main.alarmClass = "系統異常";
|
||||||
main.sourceTmp = "無";
|
main.sourceTmp = "無";
|
||||||
main.msgText = "";
|
main.msgText = "";
|
||||||
_result.data.push(main);
|
_result.data.push(main);
|
||||||
@ -667,7 +667,7 @@ function getAllDeviceAlarmByBaja(startDate_millisecond, endDate_millisecond, isR
|
|||||||
if (_sourceTmp.includes("undefined")) {
|
if (_sourceTmp.includes("undefined")) {
|
||||||
// console.log(main.ackState)
|
// console.log(main.ackState)
|
||||||
main.buildingFloorName_zh = "無";
|
main.buildingFloorName_zh = "無";
|
||||||
main.alarmClass = "系統/設備異常";
|
main.alarmClass = "系統異常";
|
||||||
main.sourceTmp = "無";
|
main.sourceTmp = "無";
|
||||||
main.msgText = "";
|
main.msgText = "";
|
||||||
}
|
}
|
||||||
|
2153
Frontend/js/site.js
2153
Frontend/js/site.js
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,8 @@ using System.IO;
|
|||||||
using System.Data.SqlTypes;
|
using System.Data.SqlTypes;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using NPOI.HSSF.Record.Chart;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FrontendWebApi.ApiControllers
|
namespace FrontendWebApi.ApiControllers
|
||||||
{
|
{
|
||||||
@ -169,13 +171,19 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ApiResult<string>> AlertList([FromBody] FindFormId alerts)
|
public async Task<ApiResult<List<FindFormId>>> AlertList([FromBody] List<FindFormId> alerts)
|
||||||
{
|
{
|
||||||
ApiResult<string> apiResult = new ApiResult<string>();
|
ApiResult<List<FindFormId>> apiResult = new ApiResult<List<FindFormId>>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sqlString = $@"select formId from operation_record where error_code = @error_code and deleted = 0 limit 1";
|
var formId = new List<FindFormId>();
|
||||||
var formId = await backendRepository.GetOneAsync<string>(sqlString, new { @error_code = alerts.uuid });
|
foreach(var fi in alerts)
|
||||||
|
{
|
||||||
|
var sqlString = $@"select error_code uuid, formId from operation_record where error_code = @error_code and deleted = 0 limit 1";
|
||||||
|
var data = await backendRepository.GetOneAsync<FindFormId>(sqlString, new { @error_code = fi.uuid });
|
||||||
|
if (data != null)
|
||||||
|
formId.Add(data);
|
||||||
|
}
|
||||||
|
|
||||||
apiResult.Code = "0000";
|
apiResult.Code = "0000";
|
||||||
apiResult.Data = formId;
|
apiResult.Data = formId;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using FrontendWebApi.Models;
|
using FrontendWebApi.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Repository.BackendRepository.Interface;
|
using Repository.BackendRepository.Interface;
|
||||||
using Repository.FrontendRepository.Interface;
|
using Repository.FrontendRepository.Interface;
|
||||||
@ -252,6 +253,18 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
}
|
}
|
||||||
buildingMenus.Add(building1);
|
buildingMenus.Add(building1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var projectName = await backendRepository.GetOneAsync<string>($"select system_value from variable where system_type = 'project_name' and deleted = 0");
|
||||||
|
if (!string.IsNullOrEmpty(projectName) && projectName.Contains("ibms_dome")) //處理安全系統 的緊急壓扣, 閃光喇叭小類
|
||||||
|
{
|
||||||
|
foreach(var bm in buildingMenus)
|
||||||
|
{
|
||||||
|
var safeSystem = bm.main_system.Where(x => x.main_system_tag == "S").FirstOrDefault();
|
||||||
|
var EmerBuckle = safeSystem.Sub_system.Where(x => x.sub_system_tag == "P").ToList();
|
||||||
|
EmerBuckle.AddRange(safeSystem.Sub_system.Where(x => x.sub_system_tag == "B").ToList());
|
||||||
|
safeSystem.Sub_system.RemoveAll(x => x.sub_system_tag == "B");
|
||||||
|
}
|
||||||
|
}
|
||||||
apiResult.Data = buildingMenus;
|
apiResult.Data = buildingMenus;
|
||||||
apiResult.Code = "0000";
|
apiResult.Code = "0000";
|
||||||
}
|
}
|
||||||
@ -318,7 +331,6 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub_System.Floors = Floors;
|
sub_System.Floors = Floors;
|
||||||
|
|
||||||
apiResult.Data = sub_System;
|
apiResult.Data = sub_System;
|
||||||
apiResult.Code = "0000";
|
apiResult.Code = "0000";
|
||||||
}
|
}
|
||||||
@ -425,6 +437,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var projectName = await backendRepository.GetOneAsync<string>($"select system_value from variable where system_type = 'project_name' and deleted = 0");
|
||||||
var main_system_guidsql = "";
|
var main_system_guidsql = "";
|
||||||
var sub_system_guidsql = "";
|
var sub_system_guidsql = "";
|
||||||
var disasterjoinsql = "";
|
var disasterjoinsql = "";
|
||||||
@ -437,7 +450,10 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
}
|
}
|
||||||
if (!String.IsNullOrEmpty(post.sub_system_tag))
|
if (!String.IsNullOrEmpty(post.sub_system_tag))
|
||||||
{
|
{
|
||||||
sub_system_guidsql = $" and d.device_name_tag = '{post.sub_system_tag}'";
|
if (!string.IsNullOrEmpty(projectName) && projectName.Contains("ibms_dome") && (post.main_system_tag == "S" && post.sub_system_tag == "P"))
|
||||||
|
sub_system_guidsql = $@" and (d.device_name_tag = '{post.sub_system_tag}' or d.device_name_tag = 'B')";
|
||||||
|
else
|
||||||
|
sub_system_guidsql = $" and d.device_name_tag = '{post.sub_system_tag}'";
|
||||||
}
|
}
|
||||||
if (!String.IsNullOrEmpty(post.device_system_category_layer3))
|
if (!String.IsNullOrEmpty(post.device_system_category_layer3))
|
||||||
{
|
{
|
||||||
|
@ -716,7 +716,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
join auth_page p on p.AuthCode = a.AuthCode
|
join auth_page p on p.AuthCode = a.AuthCode
|
||||||
where u.account = N'{role.Account}'
|
where u.account = N'{role.Account}'
|
||||||
and p.SubName = N'編輯設備名稱'
|
and p.SubName = N'編輯設備名稱'
|
||||||
and p.building_guid = N'{role.Building_guid}'";
|
and p.building_tag = N'{role.Building_tag}'";
|
||||||
var have = await backendRepository.GetOneAsync<string>(sql);
|
var have = await backendRepository.GetOneAsync<string>(sql);
|
||||||
if (have == null)
|
if (have == null)
|
||||||
{
|
{
|
||||||
|
@ -70,20 +70,6 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
|
||||||
[Route("api/df")]
|
|
||||||
public ActionResult DownloadFile(string path, string fileName, string token)
|
|
||||||
{
|
|
||||||
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(token);
|
|
||||||
if (jwt == null)
|
|
||||||
return Unauthorized(HttpStatusCode.Unauthorized);
|
|
||||||
else if (fileName == null)
|
|
||||||
return NotFound("找不到文件");
|
|
||||||
|
|
||||||
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "excel", path);
|
|
||||||
return File(System.IO.File.ReadAllBytes(Path.Combine(filePath, fileName)), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("api/Upload")]
|
[Route("api/Upload")]
|
||||||
public ActionResult DroZonUplFile()
|
public ActionResult DroZonUplFile()
|
||||||
|
@ -46,7 +46,8 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lhe"></param>
|
/// <param name="lhe"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ActionResult<ApiResult<string>> OpeExportExcel([FromBody] List<HistoryExport> lhe)
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ApiResult<string>>> OpeExportExcel([FromBody] List<HistoryExport> lhe)
|
||||||
{
|
{
|
||||||
ApiResult<string> apiResult = new ApiResult<string>();
|
ApiResult<string> apiResult = new ApiResult<string>();
|
||||||
|
|
||||||
@ -118,13 +119,16 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
sheet.SetColumnWidth(0, 4 * 160 * 12);
|
sheet.SetColumnWidth(0, 4 * 160 * 12);
|
||||||
sheet.SetColumnWidth(1, 4 * 160 * 12);
|
sheet.SetColumnWidth(1, 4 * 160 * 12);
|
||||||
sheet.SetColumnWidth(2, 4 * 160 * 12);
|
sheet.SetColumnWidth(2, 4 * 160 * 12);
|
||||||
|
sheet.SetColumnWidth(3, 4 * 160 * 12);
|
||||||
ICell cell = row.CreateCell(0);
|
ICell cell = row.CreateCell(0);
|
||||||
cell.SetCellValue("設備名稱");
|
cell.SetCellValue("類型");
|
||||||
cell.CellStyle = styleLine12;
|
cell.CellStyle = styleLine12;
|
||||||
cell = row.CreateCell(1);
|
cell = row.CreateCell(1);
|
||||||
cell.SetCellValue("數值");
|
cell.SetCellValue("設備名稱");
|
||||||
cell.CellStyle = styleLine12;
|
cell.CellStyle = styleLine12;
|
||||||
cell = row.CreateCell(2);
|
cell = row.CreateCell(2);
|
||||||
|
cell.SetCellValue("數值");
|
||||||
|
cell = row.CreateCell(3);
|
||||||
cell.SetCellValue("記錄時間");
|
cell.SetCellValue("記錄時間");
|
||||||
cell.CellStyle = styleLine12;
|
cell.CellStyle = styleLine12;
|
||||||
#endregion
|
#endregion
|
||||||
@ -135,7 +139,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
{
|
{
|
||||||
RowPosition += 1;
|
RowPosition += 1;
|
||||||
row = sheet.CreateRow(RowPosition);
|
row = sheet.CreateRow(RowPosition);
|
||||||
for (var i = 0; i < 3; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
cell = row.CreateCell(i);
|
cell = row.CreateCell(i);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@ -169,7 +173,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
apiResult.Code = "9999";
|
apiResult.Code = "9999";
|
||||||
apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
|
apiResult.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message;
|
||||||
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
|
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
|
||||||
return Ok(apiResult);
|
return Ok(apiResult);
|
||||||
}
|
}
|
||||||
@ -1156,7 +1160,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
|
var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();
|
||||||
|
|
||||||
var sql = $@"select '{device_item_info.Building_name}' as Building_name, '{device_item_info.Main_system_name}' as Main_system_name,
|
var sql = $@"select '{device_item_info.Building_name}' as Building_name, '{device_item_info.Main_system_name}' as Main_system_name,
|
||||||
'{device_item_info.Sub_system_name}' as Sub_system_name', {device_item_info.Device_number}' as Device_number,
|
'{device_item_info.Sub_system_name}' as Sub_system_name, '{device_item_info.Device_number}' as Device_number,
|
||||||
'{device_item_info.Device_name}' as Device_name, '{device_item_info.Item_name}' as Item_name, '{device_item_info.Points}' as Points,
|
'{device_item_info.Device_name}' as Device_name, '{device_item_info.Item_name}' as Item_name, '{device_item_info.Points}' as Points,
|
||||||
'{device_item_info.Unit}' as Unit, timestamp as Timestamp, round(value, 2) as Value
|
'{device_item_info.Unit}' as Unit, timestamp as Timestamp, round(value, 2) as Value
|
||||||
from FIC_CENTER_{device_number}_{point}
|
from FIC_CENTER_{device_number}_{point}
|
||||||
|
@ -74,6 +74,8 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
string sqlWhere = "";
|
string sqlWhere = "";
|
||||||
string sqlGroup = "";
|
string sqlGroup = "";
|
||||||
string sqlAvgRawData = "";
|
string sqlAvgRawData = "";
|
||||||
|
string dbDateName = startTime.Split("-")[0].ToString().PadLeft(4, '0') + startTime.Split("-")[1].ToString().PadLeft(2, '0');
|
||||||
|
|
||||||
if (input.floor_tag.Count > 0)
|
if (input.floor_tag.Count > 0)
|
||||||
sqlWhere = $@" and substring_index(substring_index(device_number, '_', 3), '_', -1) in @floor_tag ";
|
sqlWhere = $@" and substring_index(substring_index(device_number, '_', 3), '_', -1) in @floor_tag ";
|
||||||
|
|
||||||
@ -85,7 +87,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
else
|
else
|
||||||
sqlAvgRawData = " round(avg_rawdata, 2) as avg_rawdata, start_timestamp, end_timestamp ";
|
sqlAvgRawData = " round(avg_rawdata, 2) as avg_rawdata, start_timestamp, end_timestamp ";
|
||||||
|
|
||||||
var table = input.tableType == "year" ? "archive_electric_meter_day" : "archive_electric_meter_" + input.tableType;
|
var table = input.tableType == "year" ? "archive_electric_meter_month" : "archive_electric_meter_" + input.tableType + (input.tableType == "day" ? "_" + dbDateName : "");
|
||||||
var dateFormat = input.tableType == "day" || input.tableType == "week" ? "%Y-%m-%d" : input.tableType == "month" ? "%Y-%m" : input.tableType == "year" ? "%Y" : null;
|
var dateFormat = input.tableType == "day" || input.tableType == "week" ? "%Y-%m-%d" : input.tableType == "month" ? "%Y-%m" : input.tableType == "year" ? "%Y" : null;
|
||||||
var aemmEndDate = input.tableType == "year" ? $"year(DATE_ADD(fd.date, INTERVAL +1 {input.tableType}))" : $"DATE_ADD(fd.date, INTERVAL +1 {input.tableType})";
|
var aemmEndDate = input.tableType == "year" ? $"year(DATE_ADD(fd.date, INTERVAL +1 {input.tableType}))" : $"DATE_ADD(fd.date, INTERVAL +1 {input.tableType})";
|
||||||
var aemmStaDate = input.tableType == "year" ? "year(fd.date)" : "fd.date";
|
var aemmStaDate = input.tableType == "year" ? "year(fd.date)" : "fd.date";
|
||||||
@ -198,6 +200,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
: input.tableType == "month" ? (Int32.Parse(input.startTime.Split("-")[0]) + 1) + "-01-01"
|
: input.tableType == "month" ? (Int32.Parse(input.startTime.Split("-")[0]) + 1) + "-01-01"
|
||||||
: input.tableType == "year" ? (Int32.Parse(input.endTime) + 1).ToString() + "-01-01"
|
: input.tableType == "year" ? (Int32.Parse(input.endTime) + 1).ToString() + "-01-01"
|
||||||
: null;
|
: null;
|
||||||
|
string dbDateName = startTime.Split("-")[0].ToString().PadLeft(4, '0') + startTime.Split("-")[1].ToString().PadLeft(2, '0');
|
||||||
string sqlWhere = "";
|
string sqlWhere = "";
|
||||||
string sqlGroup = "";
|
string sqlGroup = "";
|
||||||
string sqlAvgRawData = "";
|
string sqlAvgRawData = "";
|
||||||
@ -212,7 +215,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
else
|
else
|
||||||
sqlAvgRawData = " round(avg_rawdata, 2) as avg_rawdata, start_timestamp, end_timestamp ";
|
sqlAvgRawData = " round(avg_rawdata, 2) as avg_rawdata, start_timestamp, end_timestamp ";
|
||||||
|
|
||||||
var table = input.tableType == "year" ? "archive_water_meter_day" : "archive_water_meter_" + input.tableType;
|
var table = input.tableType == "year" ? "archive_electric_meter_month" : "archive_electric_meter_" + input.tableType + (input.tableType == "day" ? "_" + dbDateName : "");
|
||||||
var dateFormat = input.tableType == "day" || input.tableType == "week" ? "%Y-%m-%d" : input.tableType == "month" ? "%Y-%m" : input.tableType == "year" ? "%Y" : null;
|
var dateFormat = input.tableType == "day" || input.tableType == "week" ? "%Y-%m-%d" : input.tableType == "month" ? "%Y-%m" : input.tableType == "year" ? "%Y" : null;
|
||||||
var sql = $@"set @i = -1;
|
var sql = $@"set @i = -1;
|
||||||
select fd.device_number, aemm.avg_rawdata, DATE_FORMAT(fd.date, @dateFormat) as timestamp
|
select fd.device_number, aemm.avg_rawdata, DATE_FORMAT(fd.date, @dateFormat) as timestamp
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
using FrontendWebApi.Models;
|
using FrontendWebApi.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Repository.BackendRepository.Interface;
|
using Repository.BackendRepository.Interface;
|
||||||
using Repository.FrontendRepository.Interface;
|
using Repository.FrontendRepository.Interface;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -37,8 +41,12 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
ApiResult<List<lightDevice>> apiResult = new ApiResult<List<lightDevice>>();
|
ApiResult<List<lightDevice>> apiResult = new ApiResult<List<lightDevice>>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var floor_tag = await backendRepository.GetOneAsync<string>($@"
|
||||||
|
select full_name from floor where floor_guid = @floor_guid and deleted = 0
|
||||||
|
",new { floor_guid = post.floor_guid});
|
||||||
|
|
||||||
lightDevices = await backendRepository.GetAllAsync<lightDevice>($@"
|
lightDevices = await backendRepository.GetAllAsync<lightDevice>($@"
|
||||||
select * from device where building_guid = '{post.building_guid}' and sub_system_guid = '{post.sub_system_guid}' and floor_guid = '{post.floor_guid}' and deleted = 0 and status = 0 order by priority
|
select * from device where device_building_tag = '{post.building_tag}' and device_name_tag = '{post.sub_system_tag}' and device_floor_tag = '{floor_tag}' and deleted = 0 and status = 0 order by priority
|
||||||
");
|
");
|
||||||
|
|
||||||
if(!String.IsNullOrEmpty(post.schedule_guid))
|
if(!String.IsNullOrEmpty(post.schedule_guid))
|
||||||
@ -59,7 +67,6 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
apiResult.Code = "0000";
|
apiResult.Code = "0000";
|
||||||
apiResult.Data = lightDevices;
|
apiResult.Data = lightDevices;
|
||||||
}
|
}
|
||||||
@ -79,8 +86,29 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
ApiResult<string> apiResult = new ApiResult<string>();
|
ApiResult<string> apiResult = new ApiResult<string>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(String.IsNullOrEmpty(saveSchedule.light_schedule_guid))
|
// Operation_log 輸入參數
|
||||||
|
OperationLog opeInput = new OperationLog() { operation_type = 2 };
|
||||||
|
|
||||||
|
// 取得對應樓層資料
|
||||||
|
var targetFloor = await backendRepository.GetOneAsync<Floor>($@"
|
||||||
|
select * from floor where floor_guid = @floor_guid",
|
||||||
|
new { floor_guid = saveSchedule.floor_guid});
|
||||||
|
// 取得對應燈控排程主表資料
|
||||||
|
var targetScheduleLight = await backendRepository.GetOneAsync<SaveSchedule>($@"
|
||||||
|
select * from light_schedule where light_schedule_guid = @light_schedule_guid",
|
||||||
|
new { light_schedule_guid = saveSchedule.light_schedule_guid });
|
||||||
|
// 取得對應燈控排程設備資料
|
||||||
|
var targetScheduleDevice = await backendRepository.GetAllAsync<string>($@"
|
||||||
|
select device_guid from schedule_device where light_schedule_guid = @light_schedule_guid",
|
||||||
|
new { light_schedule_guid = saveSchedule.light_schedule_guid });
|
||||||
|
|
||||||
|
|
||||||
|
opeInput.building_tag = targetFloor.building_tag;
|
||||||
|
opeInput.floor_tag = targetFloor.full_name;
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(saveSchedule.light_schedule_guid))
|
||||||
{
|
{
|
||||||
|
opeInput.action_name = "新增";
|
||||||
Dictionary<string, object> Schedule = new Dictionary<string, object>();
|
Dictionary<string, object> Schedule = new Dictionary<string, object>();
|
||||||
var newguid = Guid.NewGuid();
|
var newguid = Guid.NewGuid();
|
||||||
Schedule = new Dictionary<string, object>()
|
Schedule = new Dictionary<string, object>()
|
||||||
@ -95,6 +123,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
{ "@end_time", saveSchedule.end_time},
|
{ "@end_time", saveSchedule.end_time},
|
||||||
{ "@created_by", myUser.userinfo_guid}
|
{ "@created_by", myUser.userinfo_guid}
|
||||||
};
|
};
|
||||||
|
|
||||||
await backendRepository.AddOneByCustomTable(Schedule, "light_schedule");
|
await backendRepository.AddOneByCustomTable(Schedule, "light_schedule");
|
||||||
List<Dictionary<string, object>> ScheduleDevices = new List<Dictionary<string, object>>();
|
List<Dictionary<string, object>> ScheduleDevices = new List<Dictionary<string, object>>();
|
||||||
foreach (var a in saveSchedule.devicelist)
|
foreach (var a in saveSchedule.devicelist)
|
||||||
@ -108,9 +137,13 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
ScheduleDevices.Add(ScheduleDevice);
|
ScheduleDevices.Add(ScheduleDevice);
|
||||||
}
|
}
|
||||||
await backendRepository.AddMutiByCustomTable(ScheduleDevices, "schedule_device");
|
await backendRepository.AddMutiByCustomTable(ScheduleDevices, "schedule_device");
|
||||||
|
saveSchedule.light_schedule_guid = newguid.ToString();
|
||||||
|
opeInput.parameter = JsonConvert.SerializeObject(saveSchedule);
|
||||||
|
await InsertOperation(opeInput);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
opeInput.action_name = "修改";
|
||||||
Dictionary<string, object> Schedule = new Dictionary<string, object>();
|
Dictionary<string, object> Schedule = new Dictionary<string, object>();
|
||||||
Schedule = new Dictionary<string, object>()
|
Schedule = new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
@ -124,6 +157,37 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
{ "@updated_by", myUser.userinfo_guid},
|
{ "@updated_by", myUser.userinfo_guid},
|
||||||
{ "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
|
{ "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 比較欄位
|
||||||
|
List<string> compareTargetProps = new List<string>() { "full_name", "week", "cycle", "floor_guid", "start_time", "end_time" };
|
||||||
|
List<string> compareTargetValues = new List<string>();
|
||||||
|
|
||||||
|
Type modelType = saveSchedule.GetType();
|
||||||
|
// 根據每個欄位比較
|
||||||
|
foreach(var prop in compareTargetProps){
|
||||||
|
PropertyInfo propertyInfo = modelType.GetProperty(prop);
|
||||||
|
if (propertyInfo == null) continue;
|
||||||
|
// 比較 saveSchedule 與 targetSchedule
|
||||||
|
var value = propertyInfo.GetValue(saveSchedule,null)?.ToString();
|
||||||
|
var newValue = propertyInfo.GetValue(targetScheduleLight, null)?.ToString();
|
||||||
|
// 只要不對就是排程變更
|
||||||
|
if (value != newValue) {
|
||||||
|
saveSchedule.changeNames.Add("排程變更");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 判斷是否為狀態變更
|
||||||
|
if (targetScheduleLight.status != saveSchedule.status) {
|
||||||
|
saveSchedule.changeNames.Add("狀態變更");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兩邊設備 guid 排序後比較
|
||||||
|
saveSchedule.devicelist.Sort();
|
||||||
|
targetScheduleDevice.Sort();
|
||||||
|
if (!saveSchedule.devicelist.SequenceEqual(targetScheduleDevice)) {
|
||||||
|
saveSchedule.changeNames.Add("設備變更");
|
||||||
|
}
|
||||||
|
|
||||||
await backendRepository.UpdateOneByCustomTable(Schedule, "light_schedule", $" light_schedule_guid = '{saveSchedule.light_schedule_guid}'");
|
await backendRepository.UpdateOneByCustomTable(Schedule, "light_schedule", $" light_schedule_guid = '{saveSchedule.light_schedule_guid}'");
|
||||||
await backendRepository.PurgeOneByGuidWithCustomDBNameAndTable("schedule_device", $" light_schedule_guid = '{saveSchedule.light_schedule_guid}'");
|
await backendRepository.PurgeOneByGuidWithCustomDBNameAndTable("schedule_device", $" light_schedule_guid = '{saveSchedule.light_schedule_guid}'");
|
||||||
List<Dictionary<string, object>> ScheduleDevices = new List<Dictionary<string, object>>();
|
List<Dictionary<string, object>> ScheduleDevices = new List<Dictionary<string, object>>();
|
||||||
@ -138,6 +202,12 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
ScheduleDevices.Add(ScheduleDevice);
|
ScheduleDevices.Add(ScheduleDevice);
|
||||||
}
|
}
|
||||||
await backendRepository.AddMutiByCustomTable(ScheduleDevices, "schedule_device");
|
await backendRepository.AddMutiByCustomTable(ScheduleDevices, "schedule_device");
|
||||||
|
|
||||||
|
opeInput.parameter = JsonConvert.SerializeObject(saveSchedule);
|
||||||
|
// 若有變更才寫入 operation_log
|
||||||
|
if (saveSchedule.changeNames.Count > 0) {
|
||||||
|
await InsertOperation(opeInput);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
apiResult.Code = "0000";
|
apiResult.Code = "0000";
|
||||||
apiResult.Data = "成功";
|
apiResult.Data = "成功";
|
||||||
@ -292,5 +362,33 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
}
|
}
|
||||||
return Ok(apiResult);
|
return Ok(apiResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> InsertOperation(OperationLog input)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//記錄使用者操作紀錄
|
||||||
|
Dictionary<string, object> userOperatorLog = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "@user_guid", myUser.userinfo_guid },
|
||||||
|
{ "@operation_type", input.operation_type }, //1:名稱修改
|
||||||
|
{ "@building_tag", input.building_tag },
|
||||||
|
{ "@main_system_tag", input.main_system_tag },
|
||||||
|
{ "@sub_system_tag", input.sub_system_tag },
|
||||||
|
{ "@floor_tag", input.floor_tag },
|
||||||
|
{ "@device_guid", input.device_guid },
|
||||||
|
{ "@action_name", input.action_name },
|
||||||
|
{ "@parameter", input.parameter },
|
||||||
|
};
|
||||||
|
|
||||||
|
await backendRepository.AddOneByCustomTable(userOperatorLog, "operation_log");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,9 +132,9 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
//取得當前登入使用者資訊
|
//取得當前登入使用者資訊
|
||||||
EDFunction edFunction = new EDFunction();
|
EDFunction edFunction = new EDFunction();
|
||||||
HttpContext.Session.SetString("MyApiAccount", edFunction.AESEncrypt(myUser.account)); //將帳號透過AES加密
|
HttpContext.Session.SetString("MyApiAccount", edFunction.AESEncrypt(myUser.account)); //將帳號透過AES加密
|
||||||
//}
|
//
|
||||||
}
|
}
|
||||||
|
apiResult.Data = myUser?.exp.ToString() + "_"+ HttpContext.Session.GetString("MyApiAccount") ?? null;
|
||||||
apiResult.Code = "0000";
|
apiResult.Code = "0000";
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
@ -172,5 +172,18 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
|
|
||||||
return apiResult;
|
return apiResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("api/df")]
|
||||||
|
public ActionResult DownloadFile(string path, string fileName, string token)
|
||||||
|
{
|
||||||
|
if (fileName == null)
|
||||||
|
return NotFound("找不到文件");
|
||||||
|
|
||||||
|
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "excel", path);
|
||||||
|
return File(System.IO.File.ReadAllBytes(Path.Combine(filePath, fileName)), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
261
FrontendWebApi/ApiControllers/OperationLogController.cs
Normal file
261
FrontendWebApi/ApiControllers/OperationLogController.cs
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
using FrontendWebApi.Models;
|
||||||
|
using iTextSharp.text;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NPOI.HPSF;
|
||||||
|
using NPOI.HSSF.UserModel;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using NPOI.SS.UserModel;
|
||||||
|
using NPOI.XSSF.UserModel;
|
||||||
|
using NPOI.Util;
|
||||||
|
using Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||||
|
using Repository.BackendRepository.Interface;
|
||||||
|
using Repository.FrontendRepository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Image = System.Drawing.Image;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace FrontendWebApi.ApiControllers
|
||||||
|
{
|
||||||
|
//[Route("api/[controller]")]
|
||||||
|
//[ApiController]
|
||||||
|
public class OperationLogController : MyBaseApiController<OperationLogController>
|
||||||
|
{
|
||||||
|
private readonly IBackendRepository backendRepository;
|
||||||
|
private string operationFileSaveAsPath = "";
|
||||||
|
|
||||||
|
public OperationLogController(IBackendRepository backendRepository)
|
||||||
|
{
|
||||||
|
this.backendRepository = backendRepository;
|
||||||
|
operationFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("api/OperationLog/GetList")]
|
||||||
|
public async Task<ActionResult<ApiResult<List<OperationLogOutput>>>> GetList([FromBody] PageResult<OperationLogInput> pageResult)
|
||||||
|
{
|
||||||
|
|
||||||
|
ApiResult<List<OperationLogOutput>> apiResult = new ApiResult<List<OperationLogOutput>>(jwt_str);
|
||||||
|
if (!jwtlife)
|
||||||
|
{
|
||||||
|
apiResult.Code = "5000";
|
||||||
|
return BadRequest(apiResult);
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 設定呈現紀錄內容
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apiResult.Code = "0000";
|
||||||
|
apiResult.Data = logList;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
apiResult.Code = "9999";
|
||||||
|
Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
|
||||||
|
return Ok(apiResult);
|
||||||
|
}
|
||||||
|
return Ok(apiResult);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("api/OperationLog/ExportList")]
|
||||||
|
public async Task<FileResult> ExportList([FromBody] OperationLogExportInput input)
|
||||||
|
{
|
||||||
|
List<OperationLogOutput> result = new List<OperationLogOutput>();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
var workbook = new XSSFWorkbook();
|
||||||
|
#region excel設定
|
||||||
|
IFont font12 = workbook.CreateFont();
|
||||||
|
font12.FontName = "新細明體";
|
||||||
|
font12.FontHeightInPoints = 12;
|
||||||
|
ICellStyle style12 = workbook.CreateCellStyle();
|
||||||
|
style12.SetFont(font12);
|
||||||
|
style12.Alignment = HorizontalAlignment.Center;
|
||||||
|
style12.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
IFont font12Times = workbook.CreateFont();
|
||||||
|
font12Times.FontName = "Times New Roman";
|
||||||
|
font12Times.FontHeightInPoints = 12;
|
||||||
|
IFont font18 = workbook.CreateFont();
|
||||||
|
font18.FontName = "新細明體";
|
||||||
|
font18.FontHeightInPoints = 18;
|
||||||
|
font18.IsBold = true;
|
||||||
|
ICellStyle styleTitle18 = workbook.CreateCellStyle();
|
||||||
|
styleTitle18.SetFont(font18);
|
||||||
|
styleTitle18.Alignment = HorizontalAlignment.Center;
|
||||||
|
styleTitle18.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
ICellStyle styleLeft12 = workbook.CreateCellStyle();
|
||||||
|
styleLeft12.SetFont(font12);
|
||||||
|
styleLeft12.Alignment = HorizontalAlignment.Left;
|
||||||
|
styleLeft12.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
ICellStyle styleLine12 = workbook.CreateCellStyle();
|
||||||
|
styleLine12.SetFont(font12);
|
||||||
|
styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
|
||||||
|
styleLine12.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
ICellStyle stylein12 = workbook.CreateCellStyle();
|
||||||
|
stylein12.SetFont(font12Times);
|
||||||
|
stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;
|
||||||
|
stylein12.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
|
||||||
|
stylein12.WrapText = true;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
var sheet = workbook.CreateSheet("電表報表");
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 = stylein12;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.CellStyle = style12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -155,5 +155,7 @@ namespace FrontendWebApi.ApiControllers
|
|||||||
|
|
||||||
return apiResult;
|
return apiResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ namespace FrontendWebApi.Models
|
|||||||
public class FindFormId
|
public class FindFormId
|
||||||
{
|
{
|
||||||
public string uuid { get; set; }
|
public string uuid { get; set; }
|
||||||
|
public string formId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ namespace FrontendWebApi.Models
|
|||||||
public class ChangeNameRole
|
public class ChangeNameRole
|
||||||
{
|
{
|
||||||
public string Account { get; set; }
|
public string Account { get; set; }
|
||||||
public string Building_guid { get; set; }
|
public string Building_tag { get; set; }
|
||||||
}
|
}
|
||||||
public class SaveGrouping
|
public class SaveGrouping
|
||||||
{
|
{
|
||||||
|
@ -289,7 +289,7 @@ namespace FrontendWebApi.Models
|
|||||||
public class HistoryExport
|
public class HistoryExport
|
||||||
{
|
{
|
||||||
public string deviceName { get; set; }
|
public string deviceName { get; set; }
|
||||||
public int value { get; set; }
|
public double value { get; set; }
|
||||||
public DateTime timestamp { get; set; }
|
public DateTime timestamp { get; set; }
|
||||||
public DateTime starttime { get; set; }
|
public DateTime starttime { get; set; }
|
||||||
public DateTime? endtime { get; set; }
|
public DateTime? endtime { get; set; }
|
||||||
|
@ -7,8 +7,8 @@ namespace FrontendWebApi.Models
|
|||||||
{
|
{
|
||||||
public class GetDevicePost
|
public class GetDevicePost
|
||||||
{
|
{
|
||||||
public string building_guid { get; set; }
|
public string building_tag { get; set; }
|
||||||
public string sub_system_guid { get; set; }
|
public string sub_system_tag { get; set; }
|
||||||
public string floor_guid { get; set; }
|
public string floor_guid { get; set; }
|
||||||
public string schedule_guid { get; set; }
|
public string schedule_guid { get; set; }
|
||||||
}
|
}
|
||||||
@ -33,6 +33,7 @@ namespace FrontendWebApi.Models
|
|||||||
public class SaveSchedule : Schedule
|
public class SaveSchedule : Schedule
|
||||||
{
|
{
|
||||||
public List<string> devicelist { get; set; }
|
public List<string> devicelist { get; set; }
|
||||||
|
public List<string> changeNames { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
public class ScheduleTable : Schedule
|
public class ScheduleTable : Schedule
|
||||||
{
|
{
|
||||||
@ -44,7 +45,13 @@ namespace FrontendWebApi.Models
|
|||||||
public List<string> Floors { get; set; }
|
public List<string> Floors { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ScheduleDevice
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string light_schedule_guid { get; set; }
|
||||||
|
public string device_guid { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ namespace FrontendWebApi.Models
|
|||||||
public string notice { get; set; }
|
public string notice { get; set; }
|
||||||
public string description { get; set; }
|
public string description { get; set; }
|
||||||
public string work_type_name
|
public string work_type_name
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
Dictionary<byte, string> name = new Dictionary<byte, string>()
|
Dictionary<byte, string> name = new Dictionary<byte, string>()
|
||||||
@ -118,7 +118,7 @@ namespace FrontendWebApi.Models
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Operation_Record_File : Actor
|
public class Operation_Record_File : Actor
|
||||||
{
|
{
|
||||||
public int id { get; set; }
|
public int id { get; set; }
|
||||||
public byte deleted { get; set; }
|
public byte deleted { get; set; }
|
||||||
public int record_id { get; set; }
|
public int record_id { get; set; }
|
||||||
@ -138,4 +138,43 @@ namespace FrontendWebApi.Models
|
|||||||
public DateTime? startdate { get; set; }
|
public DateTime? startdate { get; set; }
|
||||||
public DateTime? enddate { get; set; }
|
public DateTime? enddate { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class OperationLog
|
||||||
|
{
|
||||||
|
public int id { get; set; }
|
||||||
|
public string user_guid { get; set;}
|
||||||
|
public string building_tag { get; set; }
|
||||||
|
public string main_system_tag { get; set;}
|
||||||
|
public string sub_system_tag { get; set;}
|
||||||
|
public string floor_tag { get; set;}
|
||||||
|
public string device_guid { get; set;}
|
||||||
|
public short operation_type { get; set;}
|
||||||
|
public string parameter { get; set;}
|
||||||
|
public string action_name { get; set;}
|
||||||
|
public string value { get; set;}
|
||||||
|
public DateTime? created_at { get; set;}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OperationLogOutput : OperationLog {
|
||||||
|
public string user_name { get; set; }
|
||||||
|
|
||||||
|
public string content { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OperationLogInput {
|
||||||
|
public string start_time { get; set; }
|
||||||
|
public string end_time { get; set; }
|
||||||
|
public string building_tag{ get; set; }
|
||||||
|
public short operation_type { get; set; }
|
||||||
|
}
|
||||||
|
public class OperationLogExportInput {
|
||||||
|
public bool isNiagara { get; set; }
|
||||||
|
|
||||||
|
public string exportOpeTypeName { get; set; }
|
||||||
|
|
||||||
|
public PageResult<OperationLogInput> listInput { get; set; }
|
||||||
|
public List<OperationLogOutput> exportList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -283,4 +283,18 @@ namespace FrontendWebApi.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class BasePageResult {
|
||||||
|
public int? pageSize { get; set; } = 10;
|
||||||
|
|
||||||
|
public int? totalPage { get; set; } = 0;
|
||||||
|
public int? currentPage { get; set; } = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PageResult<T> : BasePageResult
|
||||||
|
{
|
||||||
|
public T data { get; set; }
|
||||||
|
|
||||||
|
public bool isEnable { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BIN
FrontendWebApi/wwwroot/excel/history/歷史資料_2023-05-23.xlsx
Normal file
BIN
FrontendWebApi/wwwroot/excel/history/歷史資料_2023-05-23.xlsx
Normal file
Binary file not shown.
@ -589,10 +589,10 @@ namespace Repository.BackendRepository.Implement
|
|||||||
select device_building_tag, device_system_tag, device_name_tag
|
select device_building_tag, device_system_tag, device_name_tag
|
||||||
from import_niagara_tag
|
from import_niagara_tag
|
||||||
group by device_building_tag, device_system_tag, device_name_tag
|
group by device_building_tag, device_system_tag, device_name_tag
|
||||||
) AS a ON b.device_building_tag = a.device_building_tag
|
) AS a ON b.building_tag = a.device_building_tag
|
||||||
and a.device_system_tag = b.device_system_tag and a.device_name_tag = b.sub_system_tag
|
and a.device_system_tag = b.main_system_tag and a.device_name_tag = b.sub_system_tag
|
||||||
SET b.is_link = 0
|
SET b.is_link = 0
|
||||||
WHERE b.device_building_tag IS NULL");
|
WHERE b.building_tag IS NULL");
|
||||||
await conn.ExecuteAsync(sb.ToString());
|
await conn.ExecuteAsync(sb.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
|
Loading…
Reference in New Issue
Block a user