[後端] 修改排程部分更改回原先專案, 使用windows service執行
[前端] 修改alert.html 建立維修單錯誤
This commit is contained in:
		
							parent
							
								
									dd244589c5
								
							
						
					
					
						commit
						0571ebd7ac
					
				@ -1,198 +0,0 @@
 | 
				
			|||||||
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);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,335 +0,0 @@
 | 
				
			|||||||
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());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,269 +0,0 @@
 | 
				
			|||||||
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");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,113 +0,0 @@
 | 
				
			|||||||
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); ;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,163 +0,0 @@
 | 
				
			|||||||
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");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,324 +0,0 @@
 | 
				
			|||||||
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());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,77 +0,0 @@
 | 
				
			|||||||
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());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,559 +0,0 @@
 | 
				
			|||||||
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;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,69 +0,0 @@
 | 
				
			|||||||
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();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,26 +0,0 @@
 | 
				
			|||||||
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)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,935 +0,0 @@
 | 
				
			|||||||
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;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,640 +0,0 @@
 | 
				
			|||||||
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();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,213 +0,0 @@
 | 
				
			|||||||
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();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,81 +0,0 @@
 | 
				
			|||||||
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;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,54 +0,0 @@
 | 
				
			|||||||
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;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,84 +0,0 @@
 | 
				
			|||||||
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;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,213 +0,0 @@
 | 
				
			|||||||
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();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,12 +0,0 @@
 | 
				
			|||||||
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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,11 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace BackendWorkerService.Services.Interface
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public interface ISendLineNotifyService
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        bool Send(int id, string lineToken, string message);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,11 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace BackendWorkerService.Services.Interface
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public interface ISendSMSService
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        bool Send(int id, string phone, string message);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -107,8 +107,6 @@ namespace Backend
 | 
				
			|||||||
            services.AddTransient<IBackEndConfigHelper, BackEndConfigHelper>();
 | 
					            services.AddTransient<IBackEndConfigHelper, BackEndConfigHelper>();
 | 
				
			||||||
            #endregion DBHelper ª`¤J
 | 
					            #endregion DBHelper ª`¤J
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            #region Repository ª`¤J
 | 
					            #region Repository ª`¤J
 | 
				
			||||||
            services.AddTransient<IBackendRepository, BackendRepository>();
 | 
					            services.AddTransient<IBackendRepository, BackendRepository>();
 | 
				
			||||||
            services.AddTransient<IFrontendRepository, FrontendRepository>();
 | 
					            services.AddTransient<IFrontendRepository, FrontendRepository>();
 | 
				
			||||||
@ -121,12 +119,6 @@ namespace Backend
 | 
				
			|||||||
            services.AddTransient<IBackgroundServiceMsSqlRepository, BackgroundServiceMsSqlRepository>();
 | 
					            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
 | 
				
			||||||
@ -163,20 +155,6 @@ 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 =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,17 +12,6 @@
 | 
				
			|||||||
    "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
 | 
				
			||||||
@ -32,6 +21,7 @@
 | 
				
			|||||||
      "Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome
 | 
					      "Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome
 | 
				
			||||||
      //"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel
 | 
					      //"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel
 | 
				
			||||||
      //"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
 | 
					      //"Database": "iuaY0h0+TWkir44/eZLDqw==", //tpe_dome_office
 | 
				
			||||||
 | 
					      //"Database": "Rq7Gn4x6LwBvVtl7GY8LbA==", //mcut
 | 
				
			||||||
      "Root": "SzdxEgaJJ7tcTCrUl2zKsA==",
 | 
					      "Root": "SzdxEgaJJ7tcTCrUl2zKsA==",
 | 
				
			||||||
      "Password": "FVAPxztxpY4gJJKQ/se4bQ=="
 | 
					      "Password": "FVAPxztxpY4gJJKQ/se4bQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -39,7 +29,7 @@
 | 
				
			|||||||
      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
					      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
				
			||||||
      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
					      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
				
			||||||
      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
					      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
				
			||||||
      "Root": "sD8GZ9UPiIQGU6dU011/4A==",
 | 
					      "Root": "4GCCJGAXzLa8ecdmPAkYKg==",
 | 
				
			||||||
      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
					      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    //"MSSqlDBConfig": {
 | 
					    //"MSSqlDBConfig": {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,6 @@
 | 
				
			|||||||
    "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
 | 
				
			||||||
@ -28,7 +27,7 @@
 | 
				
			|||||||
      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
					      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
				
			||||||
      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
					      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
				
			||||||
      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
					      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
				
			||||||
      "Root": "sD8GZ9UPiIQGU6dU011/4A==",
 | 
					      "Root": "4GCCJGAXzLa8ecdmPAkYKg==",
 | 
				
			||||||
      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
					      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    //"MSSqlDBConfig": {
 | 
					    //"MSSqlDBConfig": {
 | 
				
			||||||
 | 
				
			|||||||
@ -50,23 +50,23 @@ namespace BackendWorkerService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    //services.AddHostedService<Worker>();
 | 
					                    //services.AddHostedService<Worker>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    #region 訊息通知
 | 
					                    //#region 訊息通知
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    #region SMPT配置
 | 
					                    //#region SMPT配置
 | 
				
			||||||
                    services.AddTransient<ISendEmailService, SendEmailService>();
 | 
					                    //services.AddTransient<ISendEmailService, SendEmailService>();
 | 
				
			||||||
                    services.Configure<SMTPConfig>(configuration.GetSection("SMTPConfig"));
 | 
					                    //services.Configure<SMTPConfig>(configuration.GetSection("SMTPConfig"));
 | 
				
			||||||
                    #endregion
 | 
					                    //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    #region SMS配置
 | 
					                    //#region SMS配置
 | 
				
			||||||
                    services.AddTransient<ISendSMSService, SendSMSService>();
 | 
					                    //services.AddTransient<ISendSMSService, SendSMSService>();
 | 
				
			||||||
                    services.Configure<SMSConfig>(configuration.GetSection("SMSConfig"));
 | 
					                    //services.Configure<SMSConfig>(configuration.GetSection("SMSConfig"));
 | 
				
			||||||
                    #endregion
 | 
					                    //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    #region Line Notify配置
 | 
					                    //#region Line Notify配置
 | 
				
			||||||
                    services.AddTransient<ISendLineNotifyService, SendLineNotifyService>();
 | 
					                    //services.AddTransient<ISendLineNotifyService, SendLineNotifyService>();
 | 
				
			||||||
                    #endregion
 | 
					                    //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    #endregion 訊息通知
 | 
					                    //#endregion 訊息通知
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    #region DBHelper 注入
 | 
					                    #region DBHelper 注入
 | 
				
			||||||
                    services.Configure<DBConfig>(configuration.GetSection("DBConfig"));
 | 
					                    services.Configure<DBConfig>(configuration.GetSection("DBConfig"));
 | 
				
			||||||
@ -93,10 +93,6 @@ namespace BackendWorkerService
 | 
				
			|||||||
                    services.AddTransient<ISchedulerFactory, StdSchedulerFactory>();
 | 
					                    services.AddTransient<ISchedulerFactory, StdSchedulerFactory>();
 | 
				
			||||||
                    services.AddHostedService<QuartzHostedService>();
 | 
					                    services.AddHostedService<QuartzHostedService>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    //#region 背景執行計畫(設定1min執行一次)
 | 
					                    //#region 背景執行計畫(設定1min執行一次)
 | 
				
			||||||
                    //services.AddSingleton<ExecutionBackgroundServicePlanJob>();
 | 
					                    //services.AddSingleton<ExecutionBackgroundServicePlanJob>();
 | 
				
			||||||
                    //services.AddSingleton(
 | 
					                    //services.AddSingleton(
 | 
				
			||||||
@ -138,6 +134,7 @@ namespace BackendWorkerService
 | 
				
			|||||||
                    //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(
 | 
				
			||||||
@ -145,12 +142,12 @@ namespace BackendWorkerService
 | 
				
			|||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    #endregion
 | 
					                    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    #region 定時取得氣象API
 | 
					                    //#region 定時取得氣象API
 | 
				
			||||||
                    services.AddSingleton<Quartz.Jobs.WeatherAPIJob>();
 | 
					                    //services.AddSingleton<Quartz.Jobs.WeatherAPIJob>();
 | 
				
			||||||
                    services.AddSingleton(
 | 
					                    //services.AddSingleton(
 | 
				
			||||||
                    new JobSchedule(jobType: typeof(Quartz.Jobs.WeatherAPIJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:WeatherAPIJob"))
 | 
					                    //new JobSchedule(jobType: typeof(Quartz.Jobs.WeatherAPIJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:WeatherAPIJob"))
 | 
				
			||||||
                    );
 | 
					                    //);
 | 
				
			||||||
                    #endregion
 | 
					                    //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                }).ConfigureLogging((hostContext, logFactory) => {
 | 
					                }).ConfigureLogging((hostContext, logFactory) => {
 | 
				
			||||||
                    IConfiguration configuration = hostContext.Configuration;
 | 
					                    IConfiguration configuration = hostContext.Configuration;
 | 
				
			||||||
 | 
				
			|||||||
@ -125,7 +125,7 @@ namespace BackendWorkerService.Quartz.Jobs
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        try
 | 
					                        try
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            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 dbDateName = preDay.Year.ToString().PadLeft(4, '0') + preDay.Month.ToString().PadLeft(2, '0');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -581,7 +581,7 @@ namespace BackendWorkerService.Quartz.Jobs
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        try
 | 
					                        try
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Week", "任務開始");
 | 
					                            await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Week", "水電表周任務開始");
 | 
				
			||||||
                            int week = Convert.ToInt32(now.DayOfWeek);
 | 
					                            int week = Convert.ToInt32(now.DayOfWeek);
 | 
				
			||||||
                            week = week == 0 ? 7 : week;
 | 
					                            week = week == 0 ? 7 : week;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -931,7 +931,7 @@ namespace BackendWorkerService.Quartz.Jobs
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        try
 | 
					                        try
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Month", "任務開始");
 | 
					                            await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Month", "水電表月任務開始");
 | 
				
			||||||
                            var FirstDay = now.AddDays(-now.Day + 1);
 | 
					                            var FirstDay = now.AddDays(-now.Day + 1);
 | 
				
			||||||
                            var LastDay = now.AddMonths(1).AddDays(-now.AddMonths(1).Day);
 | 
					                            var LastDay = now.AddMonths(1).AddDays(-now.AddMonths(1).Day);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,10 @@
 | 
				
			|||||||
using Microsoft.Extensions.Hosting;
 | 
					using Microsoft.Extensions.Hosting;
 | 
				
			||||||
using Microsoft.Extensions.Logging;
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using Serilog;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Threading;
 | 
					using System.Threading;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@
 | 
				
			|||||||
      "Microsoft.Hosting.Lifetime": "Information"
 | 
					      "Microsoft.Hosting.Lifetime": "Information"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  "LoggerPath": "C:\\inetpub\\Taipei_dome_background_service\\Logs",
 | 
				
			||||||
  "BackgroundServiceCron": {
 | 
					  "BackgroundServiceCron": {
 | 
				
			||||||
    "ExecutionBackgroundServicePlanJob": "0 0 2 * * ?",
 | 
					    "ExecutionBackgroundServicePlanJob": "0 0 2 * * ?",
 | 
				
			||||||
    "MessageNotificationJob": "0 0 2 * * ?",
 | 
					    "MessageNotificationJob": "0 0 2 * * ?",
 | 
				
			||||||
@ -13,17 +14,10 @@
 | 
				
			|||||||
    "RegularUpdateDBTableJob": "0 0 2 * * ?",
 | 
					    "RegularUpdateDBTableJob": "0 0 2 * * ?",
 | 
				
			||||||
    "ParkingJob": "0 0 2 * * ?",
 | 
					    "ParkingJob": "0 0 2 * * ?",
 | 
				
			||||||
    "ArchiveElectricMeterHourJob": "0 0 2 * * ?",
 | 
					    "ArchiveElectricMeterHourJob": "0 0 2 * * ?",
 | 
				
			||||||
    "ArchiveElectricMeterDayJob": "0 0 2 * * ?",
 | 
					    "ArchiveElectricMeterDayJob": "0/5 * * * * ?",
 | 
				
			||||||
    "WeatherAPIJob": "0/5 * * * * ?"
 | 
					    "WeatherAPIJob": "0 0 2 * * ?"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "DBConfig": {
 | 
					  "DBConfig": {
 | 
				
			||||||
    //"MySqlDBConfig": {
 | 
					 | 
				
			||||||
    //  "Server": "TNi6aupYHPZT8ZU177KTKw==", //172.16.220.251
 | 
					 | 
				
			||||||
    //  "Port": "mkF51jVbg40V5K5eTh2Ckw==",
 | 
					 | 
				
			||||||
    //  "Database": "VvfWH/59gQguY2eA2xBCug==",
 | 
					 | 
				
			||||||
    //  "Root": "IV8Ec1Ng2AWAnkBafXy2kg==",
 | 
					 | 
				
			||||||
    //  "Password": "Jue6jMFRi11meN6xbdKwDA=="
 | 
					 | 
				
			||||||
    //},
 | 
					 | 
				
			||||||
    "MySqlDBConfig": {
 | 
					    "MySqlDBConfig": {
 | 
				
			||||||
      "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
 | 
					      "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
 | 
				
			||||||
      "Port": "js2LutKe+rdjzdxMPQUrvQ==",
 | 
					      "Port": "js2LutKe+rdjzdxMPQUrvQ==",
 | 
				
			||||||
@ -38,24 +32,9 @@
 | 
				
			|||||||
      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
					      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
				
			||||||
      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
					      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
				
			||||||
      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
					      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
				
			||||||
      "Root": "sD8GZ9UPiIQGU6dU011/4A==",
 | 
					      "Root": "4GCCJGAXzLa8ecdmPAkYKg==",
 | 
				
			||||||
      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
					      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    //"MSSqlDBConfig": {   //greencloud.fic.com.tw,1433
 | 
					 | 
				
			||||||
    //  "Server": "ueFp+VFb200lhh1Uctc97WH0/tX6tfXYU2v1oxCWuuM=",
 | 
					 | 
				
			||||||
    //  "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
					 | 
				
			||||||
    //  "Database": "VvfWH/59gQguY2eA2xBCug==",
 | 
					 | 
				
			||||||
    //  "Root": "+plVKQ+enAqt7BYV2uMQng==",
 | 
					 | 
				
			||||||
    //  "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
					 | 
				
			||||||
    //}
 | 
					 | 
				
			||||||
    //"MSSqlDBConfig": {
 | 
					 | 
				
			||||||
    //  "Server": "zp3Nilx0PISEEC4caZWqCg==", //172.16.220.250
 | 
					 | 
				
			||||||
    //  "Port": "7puf4kd9qJ/q0fq2QASWeQ==",
 | 
					 | 
				
			||||||
    //  "Database": "VvfWH/59gQguY2eA2xBCug==",
 | 
					 | 
				
			||||||
    //  "Root": "sD8GZ9UPiIQGU6dU011/4A==",
 | 
					 | 
				
			||||||
    //  "Password": "Jue6jMFRi11meN6xbdKwDA=="
 | 
					 | 
				
			||||||
    //}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "SMTPConfig": {
 | 
					  "SMTPConfig": {
 | 
				
			||||||
    "Host": "smtp.gmail.com",
 | 
					    "Host": "smtp.gmail.com",
 | 
				
			||||||
 | 
				
			|||||||
@ -8,19 +8,16 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "LoggerPath": "C:\\inetpub\\Taipei_dome_background_service\\Logs",
 | 
					  "LoggerPath": "C:\\inetpub\\Taipei_dome_background_service\\Logs",
 | 
				
			||||||
  "BackgroundServiceCron": {
 | 
					  "BackgroundServiceCron": {
 | 
				
			||||||
    "ExecutionBackgroundServicePlanJob": "0/5 * * * * ?",
 | 
					    "ExecutionBackgroundServicePlanJob": "0 0 2 * * ?",
 | 
				
			||||||
    "MessageNotificationJob": "0 0/30 * * * ?",
 | 
					    "MessageNotificationJob": "0 0 2 * * ?",
 | 
				
			||||||
    "DataDeliveryJob": "0 0/5 * * * ?",
 | 
					    "DataDeliveryJob": "0 0 2 * * ?",
 | 
				
			||||||
    "RegularUpdateDBTableJob": "0 0 2 * * ?"
 | 
					    "RegularUpdateDBTableJob": "0 0 2 * * ?",
 | 
				
			||||||
 | 
					    "ParkingJob": "0 0 2 * * ?",
 | 
				
			||||||
 | 
					    "ArchiveElectricMeterHourJob": "0 0 2 * * ?",
 | 
				
			||||||
 | 
					    "ArchiveElectricMeterDayJob": "0/5 * * * * ?",
 | 
				
			||||||
 | 
					    "WeatherAPIJob": "0 0 2 * * ?"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "DBConfig": {
 | 
					  "DBConfig": {
 | 
				
			||||||
    //"MySqlDBConfig": {
 | 
					 | 
				
			||||||
    //  "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
 | 
					 | 
				
			||||||
    //  "Port": "js2LutKe+rdjzdxMPQUrvQ==",
 | 
					 | 
				
			||||||
    //  "Database": "VJB2XC+lAtzuHObDGMVOAA==", //30
 | 
					 | 
				
			||||||
    //  "Root": "SzdxEgaJJ7tcTCrUl2zKsA==",
 | 
					 | 
				
			||||||
    //  "Password": "FVAPxztxpY4gJJKQ/se4bQ=="
 | 
					 | 
				
			||||||
    //},
 | 
					 | 
				
			||||||
    "MySqlDBConfig": {
 | 
					    "MySqlDBConfig": {
 | 
				
			||||||
      "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
 | 
					      "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201
 | 
				
			||||||
      "Port": "js2LutKe+rdjzdxMPQUrvQ==",
 | 
					      "Port": "js2LutKe+rdjzdxMPQUrvQ==",
 | 
				
			||||||
@ -35,16 +32,9 @@
 | 
				
			|||||||
      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
					      "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130
 | 
				
			||||||
      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
					      "Port": "S5cUXKnKOacFtFy9+0dtpw==",
 | 
				
			||||||
      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
					      "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome 
 | 
				
			||||||
      "Root": "sD8GZ9UPiIQGU6dU011/4A==",
 | 
					      "Root": "4GCCJGAXzLa8ecdmPAkYKg==",
 | 
				
			||||||
      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
					      "Password": "0O24es2ZRF5uoJ4aU+YCdg=="
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    //"MSSqlDBConfig": {
 | 
					 | 
				
			||||||
    //  "Server": "avZg8PA8C9GVgYZBgEKzCg==",
 | 
					 | 
				
			||||||
    //  "Port": "lJA0KPkG6RvFfTgWiXFyUw==",
 | 
					 | 
				
			||||||
    //  "Database": "VvfWH/59gQguY2eA2xBCug==",
 | 
					 | 
				
			||||||
    //  "Root": "sD8GZ9UPiIQGU6dU011/4A==",
 | 
					 | 
				
			||||||
    //  "Password": "2gi7rOmGha2VdXC5vtHxhg=="
 | 
					 | 
				
			||||||
    //} 
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "SMTPConfig": {
 | 
					  "SMTPConfig": {
 | 
				
			||||||
    "Host": "smtp.gmail.com",
 | 
					    "Host": "smtp.gmail.com",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,526 +1,192 @@
 | 
				
			|||||||
<?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_202306010655001</identifier>
 | 
					    <identifier>CWB-Weather_extremely-rain_202306060340001</identifier>
 | 
				
			||||||
    <sender>weather@cwb.gov.tw</sender>
 | 
					    <sender>weather@cwb.gov.tw</sender>
 | 
				
			||||||
    <sent>2023-06-01T07:02:17+08:00</sent>
 | 
					    <sent>2023-06-06T03:45:20+08:00</sent>
 | 
				
			||||||
    <status>Actual</status>
 | 
					    <status>Actual</status>
 | 
				
			||||||
    <msgType>Update</msgType>
 | 
					    <msgType>Cancel</msgType>
 | 
				
			||||||
    <scope>Public</scope>
 | 
					    <scope>Public</scope>
 | 
				
			||||||
    <references>weather@cwb.gov.tw,CWB-Weather_extremely-rain_202306010345001,2023-06-01T03:56:19+08:00</references>
 | 
					    <references>weather@cwb.gov.tw,CWB-Weather_extremely-rain_202306060045001,2023-06-06T00:50:36+08:00 weather@cwb.gov.tw,CWB-Weather_extremely-rain_202306052245001,2023-06-05T22:54:54+08:00 weather@cwb.gov.tw,CWB-Weather_extremely-rain_202306052220001,2023-06-05T22:25:45+08:00</references>
 | 
				
			||||||
    <info>
 | 
					    <info>
 | 
				
			||||||
        <language>zh-TW</language>
 | 
					        <language>zh-TW</language>
 | 
				
			||||||
        <category>Met</category>
 | 
					        <category>Met</category>
 | 
				
			||||||
        <event>降雨</event>
 | 
					        <event>降雨</event>
 | 
				
			||||||
        <responseType>Monitor</responseType>
 | 
					        <urgency>Past</urgency>
 | 
				
			||||||
        <urgency>Future</urgency>
 | 
					        <severity>Minor</severity>
 | 
				
			||||||
        <severity>Moderate</severity>
 | 
					        <certainty>Observed</certainty>
 | 
				
			||||||
        <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-06-01T06:55:00+08:00</effective>
 | 
					        <effective>2023-06-06T03:40:00+08:00</effective>
 | 
				
			||||||
        <onset>2023-06-01T06:59:00+08:00</onset>
 | 
					        <onset>2023-06-06T03:40:00+08:00</onset>
 | 
				
			||||||
        <expires>2023-06-01T11:00:00+08:00</expires>
 | 
					        <expires>2023-06-06T03:55:20+08:00</expires>
 | 
				
			||||||
        <senderName>中央氣象局</senderName>
 | 
					        <senderName>中央氣象局</senderName>
 | 
				
			||||||
        <headline>大雨特報</headline>
 | 
					        <headline>解除豪雨特報</headline>
 | 
				
			||||||
        <description>
 | 
					        <description>
 | 
				
			||||||
颱風外圍環流影響,今(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>
 | 
					 | 
				
			||||||
            <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>
 | 
					        </parameter>
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        <area>
 | 
					        <area>
 | 
				
			||||||
            <areaDesc>新竹縣橫山鄉</areaDesc>
 | 
					            <areaDesc>基隆市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000408</value>
 | 
					                <value>10017</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>新竹縣北埔鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>臺北市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000409</value>
 | 
					                <value>63</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>桃園市觀音區</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>新北市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>6801200</value>
 | 
					                <value>65</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>桃園市復興區</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>桃園市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>6801300</value>
 | 
					                <value>68</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>臺北市信義區</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>新竹市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>6300200</value>
 | 
					                <value>10018</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>桃園市新屋區</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>新竹縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>6801100</value>
 | 
					                <value>10004</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>新竹縣竹東鎮</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>苗栗縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000402</value>
 | 
					                <value>10005</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>臺北市文山區</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>臺中市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>6300800</value>
 | 
					                <value>66</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>新竹縣竹北市</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>彰化縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000401</value>
 | 
					                <value>10007</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>新竹縣新豐鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>雲林縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000406</value>
 | 
					                <value>10009</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>臺北市松山區</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>南投縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>6300100</value>
 | 
					                <value>10008</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>新竹縣關西鎮</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>嘉義縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000404</value>
 | 
					                <value>10010</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>新竹縣湖口鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>嘉義市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000405</value>
 | 
					                <value>10020</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣冬山鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>臺南市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000208</value>
 | 
					                <value>67</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣五結鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>高雄市</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000209</value>
 | 
					                <value>64</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣頭城鎮</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>屏東縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000204</value>
 | 
					                <value>10013</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣礁溪鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>宜蘭縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000205</value>
 | 
					                <value>10002</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣壯圍鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>花蓮縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000206</value>
 | 
					                <value>10015</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣員山鄉</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>臺東縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000207</value>
 | 
					                <value>10014</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣宜蘭市</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>澎湖縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000201</value>
 | 
					                <value>10016</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>宜蘭縣羅東鎮</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>金門縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>1000202</value>
 | 
					                <value>09020</value>
 | 
				
			||||||
            </geocode>
 | 
					            </geocode>
 | 
				
			||||||
        </area><area>
 | 
					        </area>
 | 
				
			||||||
            <areaDesc>臺北市大安區</areaDesc>
 | 
					        <area>
 | 
				
			||||||
 | 
					            <areaDesc>連江縣</areaDesc>
 | 
				
			||||||
            <geocode>
 | 
					            <geocode>
 | 
				
			||||||
                <valueName>Taiwan_Geocode_103</valueName>
 | 
					                <valueName>Taiwan_Geocode_103</valueName>
 | 
				
			||||||
                <value>6300300</value>
 | 
					                <value>09007</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>
 | 
				
			||||||
@ -217,6 +217,8 @@
 | 
				
			|||||||
	pageAct.alrSelSysMain = []
 | 
						pageAct.alrSelSysMain = []
 | 
				
			||||||
	pageAct.alrSelSysSub = [];
 | 
						pageAct.alrSelSysSub = [];
 | 
				
			||||||
	pageAct.selAllSysSub = false;
 | 
						pageAct.selAllSysSub = false;
 | 
				
			||||||
 | 
						pageAct.addSelMain = null;
 | 
				
			||||||
 | 
						pageAct.addSelSub = null;
 | 
				
			||||||
	first = true;
 | 
						first = true;
 | 
				
			||||||
	// let dataAlarm = [];
 | 
						// let dataAlarm = [];
 | 
				
			||||||
	var historyTable = null;
 | 
						var historyTable = null;
 | 
				
			||||||
@ -368,7 +370,10 @@
 | 
				
			|||||||
			let alr_tableData = alr_table.row(alr_elem).data();
 | 
								let alr_tableData = alr_table.row(alr_elem).data();
 | 
				
			||||||
			$('#inpErrCode').html(`<option value = ${alr_tableData.uuid}>${alr_tableData.msgText}</option>`);
 | 
								$('#inpErrCode').html(`<option value = ${alr_tableData.uuid}>${alr_tableData.msgText}</option>`);
 | 
				
			||||||
			$('#inpStaTime').val(displayDate(new Date(Date.now()), "date").replaceAll('/', '-'));
 | 
								$('#inpStaTime').val(displayDate(new Date(Date.now()), "date").replaceAll('/', '-'));
 | 
				
			||||||
			let deviceNumber = null
 | 
								let deviceNumber = null;
 | 
				
			||||||
 | 
								let system = $(this).data("system");
 | 
				
			||||||
 | 
								pageAct.addSelMain = system.split("-")[0];
 | 
				
			||||||
 | 
								pageAct.addSelSub = system.split("-")[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			deviceNumber = pageAct.AreaTag + "_" + alr_tableData.buildingFloorName_zh.toString().split('-')[0] + "_" + alr_tableData.alarmClass.toString().split('_')[0] + "_"
 | 
								deviceNumber = pageAct.AreaTag + "_" + alr_tableData.buildingFloorName_zh.toString().split('-')[0] + "_" + alr_tableData.alarmClass.toString().split('_')[0] + "_"
 | 
				
			||||||
				+ alr_tableData.alarmClass.toString().split('_')[1] + "_" + alr_tableData.buildingFloorName_zh.toString().split('-')[1] + "_" + alr_tableData.sourceName_zh.toString().split('-')[0] + "_"
 | 
									+ alr_tableData.alarmClass.toString().split('_')[1] + "_" + alr_tableData.buildingFloorName_zh.toString().split('-')[1] + "_" + alr_tableData.sourceName_zh.toString().split('-')[0] + "_"
 | 
				
			||||||
@ -387,6 +392,7 @@
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onEvent('click', '#alr_OpeRecSendBtn', function () {
 | 
							onEvent('click', '#alr_OpeRecSendBtn', function () {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			let form = $("#alr_opeRecForm");
 | 
								let form = $("#alr_opeRecForm");
 | 
				
			||||||
			$(form).validate({
 | 
								$(form).validate({
 | 
				
			||||||
				rules: {
 | 
									rules: {
 | 
				
			||||||
@ -413,8 +419,8 @@
 | 
				
			|||||||
				fd.append("error_code", $('#inpErrCode').val());
 | 
									fd.append("error_code", $('#inpErrCode').val());
 | 
				
			||||||
				fd.append("location", "台北" + $('#buiActDrop').text() + pageAct.floor);
 | 
									fd.append("location", "台北" + $('#buiActDrop').text() + pageAct.floor);
 | 
				
			||||||
				fd.append("location_code", pageAct.AreaTag + pageAct.buiTag + pageAct.floor);
 | 
									fd.append("location_code", pageAct.AreaTag + pageAct.buiTag + pageAct.floor);
 | 
				
			||||||
				fd.append("device_system_category_layer2", pageAct.selSysMain);
 | 
									fd.append("device_system_category_layer2", pageAct.addSelMain);
 | 
				
			||||||
				fd.append("device_system_category_layer3", pageAct.selSysSub);
 | 
									fd.append("device_system_category_layer3", pageAct.addSelSub);
 | 
				
			||||||
				fd.append("work_type", parseInt($('#inpWorTyp').val()));
 | 
									fd.append("work_type", parseInt($('#inpWorTyp').val()));
 | 
				
			||||||
				fd.append("fix_do", $('#inpFixDo').val());
 | 
									fd.append("fix_do", $('#inpFixDo').val());
 | 
				
			||||||
				fd.append("fix_do_code", $('#inpFixDoCode').val());
 | 
									fd.append("fix_do_code", $('#inpFixDoCode').val());
 | 
				
			||||||
@ -771,8 +777,8 @@
 | 
				
			|||||||
			{
 | 
								{
 | 
				
			||||||
				"title": "派工/維運單號",
 | 
									"title": "派工/維運單號",
 | 
				
			||||||
				"data": "formId",
 | 
									"data": "formId",
 | 
				
			||||||
				"render": function (data) {
 | 
									"render": function (data, type, row, meta) {
 | 
				
			||||||
					return data ?? `<td><a href="#" id="alr_recModal" class="btn btn-info" data-toggle="modal" data-target="#alr_opeRecModal">+ 維修單</a></td>`;
 | 
										return data ?? `<td><a href="#" id="alr_recModal" class="btn btn-info" data-toggle="modal" data-target="#alr_opeRecModal" data-system='${row.alarmClass.includes("_") ? row.alarmClass.split('_')[0] + "-" + row.alarmClass.split('_')[1] : row.alarmClass}'>+ 維修單</a></td>`;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		];
 | 
							];
 | 
				
			||||||
@ -781,6 +787,7 @@
 | 
				
			|||||||
		$(loadEle).Loading("close");
 | 
							$(loadEle).Loading("close");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function AlertList(data) {
 | 
						function AlertList(data) {
 | 
				
			||||||
		objSendData.Data = [];
 | 
							objSendData.Data = [];
 | 
				
			||||||
		$.each(data, function (i, v) {
 | 
							$.each(data, function (i, v) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user