diff --git a/Backend/Controllers/NiagaraDataSynchronizeController.cs b/Backend/Controllers/NiagaraDataSynchronizeController.cs index a8d1c0b..957dfcb 100644 --- a/Backend/Controllers/NiagaraDataSynchronizeController.cs +++ b/Backend/Controllers/NiagaraDataSynchronizeController.cs @@ -51,19 +51,23 @@ namespace Backend.Controllers var obixApiConfig = new Backend.Models.ObixApiConfig(); EDFunction ed = new EDFunction(); obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault() + "obix/config/Program/ObixQuery/query/"; - obixApiConfig.UrlSlot =variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); + //obixApiConfig.UrlSlot =variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); obixApiConfig.TagQuantity = variableObix.Where(x => x.Name == "tag_quantity").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(); - List ds; + var ds = new List(); string top100 = "";//" top 100 "; webRequestService svc = new webRequestService(); - string bql = obixApiConfig.UrlSlot + "bql:select " + top100 + " * from baja:Folder "; - //ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Arena/Program/ObixQuery/query/", bql); - //ds = svc.obixQuery("http://localhost:8080/obix/config/Program/ObixQuery/query/", bql); - ds = svc.obixQuery(obixApiConfig.ApiBase, bql, obixApiConfig.TagQuantity, obixApiConfig.UserName, obixApiConfig.Password);//三菱 + var urlSlots = backendRepository.GetAllAsync("select obixSlot from building where deleted = 0").Result; + foreach(var us in urlSlots) + { + string bql = us + "bql:select " + top100 + " * from baja:Folder "; + //ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Arena/Program/ObixQuery/query/", bql); + //ds = svc.obixQuery("http://localhost:8080/obix/config/Program/ObixQuery/query/", bql); + ds.AddRange(svc.obixQuery(obixApiConfig.ApiBase, bql, obixApiConfig.TagQuantity, obixApiConfig.UserName, obixApiConfig.Password));//三菱 + } apiResult.Code = "0000"; apiResult.Data = ds; @@ -93,14 +97,17 @@ namespace Backend.Controllers try { string ss = ds.Where(x => x.tag_name != "").FirstOrDefault().tag_name; - var building = ""; + var data = ds.Where(x => x.tag_name != ""); + List building = null; if (tag_quantity == "5") { - building = ss.Split("_")[0]; + //building.Add(ss.Split("_")[0]); + building = data.GroupBy(x => x.tag_name.Split("_")[0]).Select(x => x.Key).ToList(); } else { - building = ss.Split("_")[1]; + //building.Add(ss.Split("_")[1]); + building = data.GroupBy(x => x.tag_name.Split("_")[1]).Select(x => x.Key).ToList(); } string LightSwitchLevel = await niagaraDataSynchronizeRepository.getLightSwitchLevel(); //獲取照明開關 是否在 device or device_node @@ -135,7 +142,7 @@ namespace Backend.Controllers try { - List ds; + var ds = new List(); webRequestService svc = new webRequestService(); @@ -146,12 +153,19 @@ namespace Backend.Controllers 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(); - obixApiConfig.UrlSlot = variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); - ds = svc.obixHisQuery(obixApiConfig.ApiBase + "obix/config/Program/ObixQuery/query/", obixApiConfig.ApiBase + "obix/histories",obixApiConfig.UrlSlot, obixApiConfig.UserName, - obixApiConfig.Password); + //obixApiConfig.UrlSlot = variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); + + var urlSlots = backendRepository.GetAllAsync("select obixSlot from building where deleted = 0").Result; + foreach(var us in urlSlots) + { + var data = svc.obixHisQuery(obixApiConfig.ApiBase + "obix/config/Program/ObixQuery/query/", obixApiConfig.ApiBase + "obix/histories", us, + obixApiConfig.UserName, obixApiConfig.Password); + ds.AddRange(data); + } + var buildings = backendRepository.GetAllAsync("select building_tag from building where deleted = 0").Result; apiResult.Code = "0000"; - apiResult.Data = ds.Where(x => x.device_building_tag == building.building).ToList(); ; + apiResult.Data = ds.Where(x => buildings.Contains(x.device_building_tag)).ToList(); } catch (Exception exception) { @@ -180,7 +194,7 @@ namespace Backend.Controllers //string ss = ds.Where(x => x.tag_name != "").FirstOrDefault().tag_name; //var building = ss.Split("_")[0]; - var building = ds.FirstOrDefault().device_building_tag; + var building = ds.GroupBy(x => x.device_building_tag).Select(x => x.Key).ToList(); await niagaraDataSynchronizeRepository.InsertItemFromNiagara(ds, building); // insert 暫存table import_niagara_item await niagaraDataSynchronizeRepository.DeviceItemComparison(); //insert device_item await niagaraDataSynchronizeRepository.CheckItemDiffFullNameAndCover(); // update device_item.fullname diff --git a/Backend/Views/BuildInfo/Index.cshtml b/Backend/Views/BuildInfo/Index.cshtml index 54aa34e..e4ad6fb 100644 --- a/Backend/Views/BuildInfo/Index.cshtml +++ b/Backend/Views/BuildInfo/Index.cshtml @@ -262,11 +262,11 @@ maxlength: 50, filterspace: true }, - build_file_3d_modal: { - required: true, extension: "nwc|nwd" - } + //build_file_3d_modal: { + // required: true, extension: "nwc|nwd" + //} }, - messages: { build_file_3d_modal: "File must be nwc, nwd" } + //messages: { build_file_3d_modal: "File must be nwc, nwd" } }); //#region 儲存區域基本資料 diff --git a/Backend/appsettings.Development.json b/Backend/appsettings.Development.json index 88518dc..d9b4695 100644 --- a/Backend/appsettings.Development.json +++ b/Backend/appsettings.Development.json @@ -17,8 +17,8 @@ "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201 "Port": "js2LutKe+rdjzdxMPQUrvQ==", //"Database": "VJB2XC+lAtzuHObDGMVOAA==", //30 - "Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp - //"Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome + //"Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp + "Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome //"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel "Root": "SzdxEgaJJ7tcTCrUl2zKsA==", "Password": "FVAPxztxpY4gJJKQ/se4bQ==" diff --git a/FrontendWebApi/ApiControllers/HistoryController.cs b/FrontendWebApi/ApiControllers/HistoryController.cs index 708f0b5..813e179 100644 --- a/FrontendWebApi/ApiControllers/HistoryController.cs +++ b/FrontendWebApi/ApiControllers/HistoryController.cs @@ -445,29 +445,29 @@ namespace FrontendWebApi.ApiControllers { var sql = $@" SELECT - rc.combination_guid, - rc.full_name AS combination_full_name, - rcd.device_guid, - d.device_number, - d.full_name AS Device_full_name, - b.full_name AS Building_full_name, - ms.full_name AS Main_system_full_name, - ss.full_name AS Sub_system_full_name - FROM realtime_combination_detail rcd - LEFT JOIN - (SELECT - rc.* - FROM realtime_combination rc - WHERE building_guid = @building_guid - AND userinfo_guid = @userinfo_guid - ) rc ON rcd.combination_guid = rc.combination_guid - JOIN device d ON d.deleted = 0 AND d.device_guid = rcd.device_guid - JOIN building b ON b.deleted = 0 AND b.building_guid = d.building_guid - JOIN main_system ms ON ms.deleted = 0 AND ms.main_system_guid = d.main_system_guid - JOIN sub_system ss ON ss.deleted = 0 AND ss.sub_system_guid = d.sub_system_guid - WHERE rc.deleted = 0"; + rc.combination_guid, + rc.full_name AS combination_full_name, + rcd.device_guid, + d.device_number, + d.full_name AS Device_full_name, + b.full_name AS Building_full_name, + v1.system_key AS Main_system_full_name, + v2.system_key AS Sub_system_full_name + FROM realtime_combination_detail rcd + LEFT JOIN + (SELECT + rc.* + FROM realtime_combination rc + WHERE building_tag = @building_tag + AND userinfo_guid = @userinfo_guid + ) rc ON rcd.combination_guid = rc.combination_guid + JOIN device d ON d.deleted = 0 AND d.device_guid = rcd.device_guid + JOIN building b ON b.deleted = 0 AND b.building_tag = d.device_building_tag + JOIN variable v1 ON v1.deleted = 0 AND v1.system_value = d.device_system_tag and v1.system_type = 'device_system_category_layer2' + JOIN variable v2 ON v2.deleted = 0 AND v2.system_value = d.device_name_tag and v2.system_type = 'device_system_category_layer3' + WHERE rc.deleted = 0"; - var rawDatas = await frontendRepository.GetAllAsync(sql, new { building_guid = post.building_guid, userinfo_guid = myUser.userinfo_guid }); + var rawDatas = await frontendRepository.GetAllAsync(sql, new { building_tag = post.building_tag, userinfo_guid = myUser.userinfo_guid }); var rawDatas_groups = rawDatas.GroupBy(x => x.Combination_guid).ToList(); @@ -536,7 +536,7 @@ namespace FrontendWebApi.ApiControllers combination = new Dictionary() { { "@combination_guid", guid}, - { "@building_guid", post.Building_guid}, + { "@building_tag", post.Building_tag}, { "@userinfo_guid", myUser.userinfo_guid}, { "@full_name", post.Full_name}, { "@created_by", myUser.userinfo_guid} diff --git a/FrontendWebApi/ApiControllers/MyBaseApiController.cs b/FrontendWebApi/ApiControllers/MyBaseApiController.cs index 2611d2a..b85fe89 100644 --- a/FrontendWebApi/ApiControllers/MyBaseApiController.cs +++ b/FrontendWebApi/ApiControllers/MyBaseApiController.cs @@ -48,37 +48,37 @@ namespace FrontendWebApi.ApiControllers ctx.Response.Headers.Add("Access-Control-Allow-Headers", "*"); ctx.Response.Headers.Add("Access-Control-Allow-Credentials", "true"); EDFunction edFunction = new EDFunction(); - myUser = new JwtGet() - { - account = User.Claims.Where(a => a.Type == "account").Select(e => e.Value).FirstOrDefault(), - email = User.Claims.Where(a => a.Type == "email").Select(e => e.Value).FirstOrDefault(), - full_name = User.Claims.Where(a => a.Type == "full_name").Select(e => e.Value).FirstOrDefault(), - exp = User.Claims.Where(a => a.Type == "exp").Select(e => Convert.ToInt32(e.Value)).FirstOrDefault(), - nbf = User.Claims.Where(a => a.Type == "nbf").Select(e => Convert.ToInt32(e.Value)).FirstOrDefault(), - userinfo_guid = User.Claims.Where(a => a.Type == "userinfo_guid").Select(e => e.Value).FirstOrDefault(), - }; + //myUser = new JwtGet() + //{ + // account = User.Claims.Where(a => a.Type == "account").Select(e => e.Value).FirstOrDefault(), + // email = User.Claims.Where(a => a.Type == "email").Select(e => e.Value).FirstOrDefault(), + // full_name = User.Claims.Where(a => a.Type == "full_name").Select(e => e.Value).FirstOrDefault(), + // exp = User.Claims.Where(a => a.Type == "exp").Select(e => Convert.ToInt32(e.Value)).FirstOrDefault(), + // nbf = User.Claims.Where(a => a.Type == "nbf").Select(e => Convert.ToInt32(e.Value)).FirstOrDefault(), + // userinfo_guid = User.Claims.Where(a => a.Type == "userinfo_guid").Select(e => e.Value).FirstOrDefault(), + //}; - if (myUser.exp == 0) - { - jwt_str = "Jwt Token不合法"; - jwtlife = false; - filterContext.Result = new JsonResult(new { HttpStatusCode.Unauthorized }); - } - else - { - if (myUser.exp <= DateTime.Now.AddHours(-8).AddMinutes(10).Subtract(new DateTime(1970, 1, 1)).TotalSeconds) - { - jwtlife = true; - JwtLogin jwtLoing = new JwtLogin() - { - account = myUser.account, - email = myUser.email, - full_name = myUser.full_name, - userinfo_guid = myUser.userinfo_guid - }; - jwt_str = jwt.GenerateToken(jwtLoing).token; - } - } + //if (myUser.exp == 0) + //{ + // jwt_str = "Jwt Token不合法"; + // jwtlife = false; + // filterContext.Result = new JsonResult(new { HttpStatusCode.Unauthorized }); + //} + //else + //{ + // if (myUser.exp <= DateTime.Now.AddHours(-8).AddMinutes(10).Subtract(new DateTime(1970, 1, 1)).TotalSeconds) + // { + // jwtlife = true; + // JwtLogin jwtLoing = new JwtLogin() + // { + // account = myUser.account, + // email = myUser.email, + // full_name = myUser.full_name, + // userinfo_guid = myUser.userinfo_guid + // }; + // jwt_str = jwt.GenerateToken(jwtLoing).token; + // } + //} //if (myUser.exp <= DateTime.Now.AddHours(-8).AddMinutes(10).Subtract(new DateTime(1970, 1, 1)).TotalSeconds) //{ // jwtlife = true; diff --git a/FrontendWebApi/Models/HistoryClass.cs b/FrontendWebApi/Models/HistoryClass.cs index 8a9ffe9..3bd20f8 100644 --- a/FrontendWebApi/Models/HistoryClass.cs +++ b/FrontendWebApi/Models/HistoryClass.cs @@ -195,7 +195,7 @@ namespace FrontendWebApi.Models public class PostRealTimeCombination { public string account { get; set; } - public string building_guid { get; set; } + public string building_tag { get; set; } } public class RealTimeCombinationRawData @@ -238,7 +238,7 @@ namespace FrontendWebApi.Models public class PostSaveRealTimeCombination { - public string Building_guid { get; set; } + public string Building_tag { get; set; } public string Combination_guid { get; set; } public byte Save_type { get; set; } public string Full_name { get; set; } diff --git a/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs b/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs index cd34f0f..193cf9e 100644 --- a/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs +++ b/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs @@ -27,7 +27,7 @@ namespace Repository.BackendRepository.Implement /// /// /// - public async Task InsertNiagaraTagList(List ds, string building, string tag_quantity) + public async Task InsertNiagaraTagList(List ds, List building, string tag_quantity) { using (IDbConnection conn = GetDbConnection()) { @@ -36,25 +36,28 @@ namespace Repository.BackendRepository.Implement { try { - string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_tag` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `db_tags` varchar(50) DEFAULT NULL, - `niagara_tags` varchar(50) DEFAULT NULL, - `device_area_tag` varchar(50) DEFAULT NULL, - `device_building_tag` varchar(50) DEFAULT NULL, - `device_system_tag` varchar(50) DEFAULT NULL, - `device_name_tag` varchar(50) DEFAULT NULL, - `device_floor_tag` varchar(50) DEFAULT NULL, - `device_master_tag` varchar(50) DEFAULT NULL, - `device_last_name_tag` varchar(50) DEFAULT NULL, - `device_serial_tag` varchar(50) DEFAULT NULL, - `atDateTime` datetime(1) DEFAULT NULL, - `is_used` smallint(1) DEFAULT 0, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; - await conn.ExecuteAsync(sql); - sql = "delete from import_niagara_tag where device_building_tag = '" + building + "'"; - await conn.ExecuteAsync(sql); + foreach(var b in building) + { + string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_tag` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `db_tags` varchar(50) DEFAULT NULL, + `niagara_tags` varchar(50) DEFAULT NULL, + `device_area_tag` varchar(50) DEFAULT NULL, + `device_building_tag` varchar(50) DEFAULT NULL, + `device_system_tag` varchar(50) DEFAULT NULL, + `device_name_tag` varchar(50) DEFAULT NULL, + `device_floor_tag` varchar(50) DEFAULT NULL, + `device_master_tag` varchar(50) DEFAULT NULL, + `device_last_name_tag` varchar(50) DEFAULT NULL, + `device_serial_tag` varchar(50) DEFAULT NULL, + `atDateTime` datetime(1) DEFAULT NULL, + `is_used` smallint(1) DEFAULT 0, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; + await conn.ExecuteAsync(sql); + sql = "delete from import_niagara_tag where device_building_tag = '" + b + "'"; + await conn.ExecuteAsync(sql); + } //N4資料groupBy後放入import_niagara_tag資料表 var ds2 = ds.GroupBy(x => new @@ -170,7 +173,7 @@ namespace Repository.BackendRepository.Implement /// /// - public async Task InsertItemFromNiagara(List ds, string building) + public async Task InsertItemFromNiagara(List ds, List building) { using (IDbConnection conn = GetDbConnection()) { @@ -180,21 +183,24 @@ namespace Repository.BackendRepository.Implement try { #region 刪除 import_niagara_item資料表中選取的棟別 - string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `device_area_tag` varchar(50) DEFAULT NULL, - `device_building_tag` varchar(50) DEFAULT NULL, - `device_system_tag` varchar(50) DEFAULT NULL, - `device_name_tag` varchar(50) DEFAULT NULL, - `device_point_name` varchar(50) DEFAULT NULL, - `check_status` varchar(50) DEFAULT NULL, - `parent_path` varchar(50) DEFAULT NULL, - `full_name` varchar(50) DEFAULT NULL, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; - await conn.ExecuteAsync(sql); - sql = "delete from import_niagara_item where device_building_tag = '" + building + "'"; - await conn.ExecuteAsync(sql); + foreach(var b in building) + { + string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `device_area_tag` varchar(50) DEFAULT NULL, + `device_building_tag` varchar(50) DEFAULT NULL, + `device_system_tag` varchar(50) DEFAULT NULL, + `device_name_tag` varchar(50) DEFAULT NULL, + `device_point_name` varchar(50) DEFAULT NULL, + `check_status` varchar(50) DEFAULT NULL, + `parent_path` varchar(50) DEFAULT NULL, + `full_name` varchar(50) DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; + await conn.ExecuteAsync(sql); + sql = "delete from import_niagara_item where device_building_tag = '" + b + "'"; + await conn.ExecuteAsync(sql); + } #endregion ds = ds.GroupBy(x => new { device_area_tag = x.device_area_tag, @@ -270,7 +276,7 @@ namespace Repository.BackendRepository.Implement using (IDbConnection conn = GetDbConnection()) { conn.Open(); - using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) + using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled, new TimeSpan(0, 0, 200))) { try { @@ -398,19 +404,21 @@ namespace Repository.BackendRepository.Implement } #endregion - //device有,niagara沒有,is_link 更新成 0 - sb.Append($@" SET SQL_SAFE_UPDATES = 0; - UPDATE device d LEFT JOIN import_niagara_tag m ON d.device_number = m.niagara_tags - SET d.is_link = 0 - WHERE m.niagara_tags IS NULL;"); - await conn.ExecuteAsync(sb.ToString()); + //device有,niagara沒有,is_link 更新成 0 + sb.Append($@" SET SQL_SAFE_UPDATES = 0; + UPDATE device d + SET d.is_link = 0 + WHERE d.is_link = 1 and not exists (select niagara_tags from import_niagara_tag where niagara_tags = d.device_number);"); + await conn.ExecuteAsync(sb.ToString(), commandTimeout: 100); + + sb.Clear(); // device_node 有, niagara沒有, is_link 更新成 0 sb.Append($@" SET SQL_SAFE_UPDATES = 0; - UPDATE device_node d LEFT JOIN import_niagara_tag m ON d.device_number = m.niagara_tags + UPDATE device_node d SET d.is_link = 0 - WHERE m.niagara_tags IS NULL;"); - await conn.ExecuteAsync(sb.ToString()); + WHERE d.is_link = 1 and not exists (select niagara_tags from import_niagara_tag where niagara_tags = d.device_number);"); + await conn.ExecuteAsync(sb.ToString(), commandTimeout: 100); } catch (Exception exception) { @@ -738,7 +746,7 @@ namespace Repository.BackendRepository.Implement using (IDbConnection conn = GetDbConnection()) { conn.Open(); - using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) + using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled, new TimeSpan (0, 0, 200))) { try { @@ -746,7 +754,7 @@ namespace Repository.BackendRepository.Implement sb.Append("update device d inner JOIN import_niagara_tag m ON m.niagara_tags = d.device_number " + "set d.full_name=m.device_full_name " + "where m.device_full_name<>d.full_name;"); - await conn.ExecuteAsync(sb.ToString()); + await conn.ExecuteAsync(sb.ToString(), commandTimeout: 200); } catch (Exception exception) { diff --git a/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs b/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs index 078c92f..ef2688a 100644 --- a/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs +++ b/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs @@ -12,7 +12,7 @@ namespace Repository.BackendRepository.Interface /// /// /// - Task InsertNiagaraTagList(List ds, string building, string tag_quantity); + Task InsertNiagaraTagList(List ds, List building, string tag_quantity); /// @@ -27,7 +27,7 @@ namespace Repository.BackendRepository.Interface /// /// /// - Task InsertItemFromNiagara(List ds, string building); + Task InsertItemFromNiagara(List ds, List building); /// /// 比對 device ///