diff --git a/Frontend/_operation.html b/Frontend/_operation.html index 1242fdf..0e6f5e6 100644 --- a/Frontend/_operation.html +++ b/Frontend/_operation.html @@ -1499,7 +1499,7 @@ $.each(res.data, function (i, v) { msg = v.msgText != null ? ($.trim(v.msgText.toString()).length > 0 ? v.msgText.split(':')[0] : '') : ''; - strHtml += ``; + strHtml += ``; }); if (res.count > 0) $(pageAct.work_type == '1' ? '#inpErrCode' : '#inpErrCode_2').html(strHtml); diff --git a/Frontend/_sysMonFloor.html b/Frontend/_sysMonFloor.html index f378e12..f8d7481 100644 --- a/Frontend/_sysMonFloor.html +++ b/Frontend/_sysMonFloor.html @@ -1,1252 +1,1267 @@ 
- +
-
-
-
-
- -
-
-
+
+
+
+
+ +
+
+
+
-
\ No newline at end of file diff --git a/Frontend/js/forge/forgemodel.js b/Frontend/js/forge/forgemodel.js index d422166..765f1ff 100644 --- a/Frontend/js/forge/forgemodel.js +++ b/Frontend/js/forge/forgemodel.js @@ -8,8 +8,8 @@ var myDataList; var lightDataList; var lightList = [];//燈光清單 var levels;//剖面用 -var lowerIdx;//剖面的下方樓層 -var upperIdx;//剖面的上方樓層 +var lowerIdx = 0;//剖面的下方樓層 +var upperIdx = 0;//剖面的上方樓層 function launchViewer(urn, callback, failCallback, _selector = "#forgeViewer") { selector = _selector; @@ -340,12 +340,12 @@ class elevator3D { } } + function onDocumentLoadSuccess(doc, eleOption) { var viewables = doc.getRoot().getDefaultGeometry(); viewer.loadDocumentNode(doc, viewables).then(i => { // documented loaded, any action? - }); // viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, (args) => { // var currSelection = viewer.getSelection(); @@ -559,6 +559,7 @@ class ADHeatMaps { this.roomDbIds = []; //房間 dbId this.model = null; this.dataVizExtn = null; + this.shadingData = null; this.onComplete = option.onComplete ?? null; this.init(); } @@ -571,54 +572,78 @@ class ADHeatMaps { this.model = viewer.model; this.addHeatMaps() } + async addHeatMaps() { const { SurfaceShadingData, SurfaceShadingPoint, SurfaceShadingNode, + SurfaceShadingGroup } = Autodesk.DataVisualization.Core; + // test + const shadingGroup = new SurfaceShadingGroup('iot-heatmap'); + const rooms = new Map(); + + for (const { id, roomDbId, position, sensorTypes } of this.devices) { + // console.log(id, roomDbId, position, sensorTypes) + if (!id || roomDbId == -1) { + continue; + } + if (!rooms.has(roomDbId)) { + const room = new SurfaceShadingNode(id, roomDbId); + shadingGroup.addChild(room); + rooms.set(roomDbId, room); + } + const room = rooms.get(roomDbId); + room.addPoint(new SurfaceShadingPoint(id, position, sensorTypes)); + } + this.shadingData = new SurfaceShadingData(); + this.shadingData.addChild(shadingGroup) + this.shadingData.initialize(this.model); + await this.dataVizExtn.setupSurfaceShading(this.model, this.shadingData); + this.dataVizExtn.renderSurfaceShading('iot-heatmap', "temperature", this.getSensorValue.bind(this)); //let nodeIds = await getNodeIdByDbIds(this.checkNodeString); //nodeIds = Array.from(nodeIds); //nodeIds = nodeIds.map(x => { return { room: x[0] , nodeId: x[1]} }); - this.roomDbIds = this.devices.filter(x => x.roomDbId != -1).map(x => x.roomDbId).Distinct(); + // this.roomDbIds = this.devices.filter(x => x.roomDbId != -1).map(x => x.roomDbId).Distinct(); - // 建立一個 SurfaceShadingData 物件,並將 SurfaceShadingNode 加入到該物件中 - const heatmapData = new SurfaceShadingData(); + // // 建立一個 SurfaceShadingData 物件,並將 SurfaceShadingNode 加入到該物件中 + // const heatmapData = new SurfaceShadingData(); - $.each(this.roomDbIds, (idx, rDbid) => { - // 建立一個名為 "Room Panel" 的 SurfaceShadingNode 物件,並將房間的模型給傳入,只在該房間呈現溫度 - const shadingNode = new SurfaceShadingNode("RoomPanel" + rDbid, rDbid); + // $.each(this.roomDbIds, (idx, rDbid) => { + // // 建立一個名為 "Room Panel" 的 SurfaceShadingNode 物件,並將房間的模型給傳入,只在該房間呈現溫度 + // const shadingNode = new SurfaceShadingNode("RoomPanel" + rDbid, rDbid); - // 遍歷每個設備,建立一個 SurfaceShadingPoint 物件並加入到 SurfaceShadingNode 中,透過這些設備渲染溫度 - this.devices.filter(x => x.roomDbId == rDbid).forEach((device) => { - const shadingPoint = new SurfaceShadingPoint( - device.id, - undefined, - device.sensorTypes - ); - shadingPoint.positionFromDBId(this.model, device.roomDbId) - shadingNode.addPoint(shadingPoint); - // device.temp = 0; - }); + // // 遍歷每個設備,建立一個 SurfaceShadingPoint 物件並加入到 SurfaceShadingNode 中,透過這些設備渲染溫度 + // this.devices.filter(x => x.roomDbId == rDbid).forEach((device) => { + // const shadingPoint = new SurfaceShadingPoint( + // device.id, + // undefined, + // device.sensorTypes + // ); + // shadingPoint.positionFromDBId(this.model, device.roomDbId) + // shadingNode.addPoint(shadingPoint); + // // device.temp = 0; + // }); - heatmapData.addChild(shadingNode); - }) + // heatmapData.addChild(shadingNode); + // }) - // 將資料初始化並顯示在模型上 - heatmapData.initialize(this.model); + // // 將資料初始化並顯示在模型上 + // heatmapData.initialize(this.model); - // 對模型做表面顏色的渲染 - await this.dataVizExtn.setupSurfaceShading(this.model, heatmapData); + // // 對模型做表面顏色的渲染 + // await this.dataVizExtn.setupSurfaceShading(this.model, heatmapData); - // 對 "temperature" 的溫度設定兩種顏色:紅色和藍色 - this.dataVizExtn.registerSurfaceShadingColors("temperature", [0x0000ff, 0x00ff00, 0xffff00, 0xff0000]); + // // 對 "temperature" 的溫度設定兩種顏色:紅色和藍色 + // this.dataVizExtn.registerSurfaceShadingColors("temperature", [0x0000ff, 0x00ff00, 0xffff00, 0xff0000]); - $.each(this.roomDbIds, (idx, rDbid) => { - this.dataVizExtn.renderSurfaceShading("RoomPanel" + rDbid, "temperature", this.getSensorValue.bind(this)); - }) + // $.each(this.roomDbIds, (idx, rDbid) => { + // this.dataVizExtn.renderSurfaceShading("RoomPanel" + rDbid, "temperature", this.getSensorValue.bind(this)); + // }) - /*this.changeTemp(this.tempVal);*/ + // /*this.changeTemp(this.tempVal);*/ this.onComplete ? this.onComplete() : ""; } @@ -629,7 +654,7 @@ class ADHeatMaps { } // 改變溫度 - changeTemp = function (devId, temp) { + changeTemp = async function (devId, temp) { this.tempVal = temp; // 透過 device id 取得 roomDbId this.devices.forEach((dev) => { @@ -637,9 +662,18 @@ class ADHeatMaps { dev.temp = temp; } }) - $.each(this.roomDbIds, async (idx, rDbid) => { - this.dataVizExtn.renderSurfaceShading("RoomPanel" + rDbid, "temperature", this.getSensorValue.bind(this)); - }) + + if (!this.shadingData) { + await this.addHeatMaps(); + this.dataVizExtn.renderSurfaceShading('iot-heatmap', "temperature", this.getSensorValue.bind(this)); + } + else { + this.dataVizExtn.updateSurfaceShading(this.getSensorValue.bind(this)); + } + // $.each(this.roomDbIds, async (idx, rDbid) => { + // this.dataVizExtn.renderSurfaceShading("RoomPanel" + rDbid, "temperature", this.getSensorValue.bind(this)); + // }) + //if (rDbid != null) { // // 取得新的溫度值 // let getSensorValue = (device, sensorType) => { @@ -740,10 +774,11 @@ async function getLightData(data) { } async function testNewLight(dataList) { + console.log("dataList", dataList) dataList.forEach((myData, index) => { const position = JSON.parse(myData.device_coordinate_3d); if (lightList.findIndex(x => x.device_guid == myData.device_guid) == -1) { - lightList.push({ dbid: myData.forge_dbid, device_guid: myData.device_guid, lightObject: new THREE.SpotLight(0xe1cf18, 0, 20, 0.6, 0.5, 10) }); + lightList.push({ dbid: myData.forge_dbid, device_guid: myData.device_guid, lightObject: new THREE.SpotLight(0xe1cf18, 10, 200, 1, 1, 2) }); } lightList[index].lightObject.position.set(position.x, position.y, position.z); @@ -917,6 +952,7 @@ async function changeScaleForHotspot(dbId, type = true) { //------------------ 熱圖 ------------------------------- async function loadHeatmaps(model) { + //console.log("熱圖 loadHeat") const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization"); //取三個空調設備的位置打點 @@ -1082,28 +1118,73 @@ async function loadHeatmapForFloor() { } //------------ 剖面 ---------------------- -async function getRemoteLevels() { - const aecData = await Autodesk.Viewing.Document.getAecModelData(this.viewer.model.getDocumentNode()); - if (!aecData || !aecData.levels) return null; - const levels2 = aecData.levels; - levels2.sort((a, b) => b.elevation - a.elevation); - return levels2; +function findLevels(model) { + return new Promise((resolve, reject) => { + model.search("layer", (nodeIds) => { + let levels = [] + const tree = viewer.model.getInstanceTree(); + for (let i = 0; i < nodeIds.length; i++) { + const dbId = nodeIds[i]; + const name = tree.getNodeName(dbId); + if (!name || name.includes('<沒有層級>')) continue; + levels.push({ + guid: dbId, + name, + dbId, + extension: { + buildingStory: true, + structure: false, + computationHeight: 0, + groundPlane: false, + hasAssociatedViewPlans: false, + } + }); + } + resolve(levels) + }, (e) => { reject(e) }) + }); +} + + +async function getRemoteLevels() { + + let aecData = await Autodesk.Viewing.Document.getAecModelData(this.viewer.model.getDocumentNode()); + + let levels; + if (!aecData || !aecData.levels) { + const levelExt = await viewer.loadExtension('Autodesk.AEC.LevelsExtension'); + levelExt.setAecModelData(undefined, viewer.model); //!<<< Clear before reset + levels = await findLevels(viewer.model) + aecdata = Autodesk.AEC.AecModelData.computeLevels(levels, viewer.model); //!<<< Rebuild aec model data + } else { + levels = aecData.levels; + } + levels.sort((a, b) => b.elevation - a.elevation); + return levels; } async function getLevelsData(lowerFloor, upperFloor, callback = null) { + console.log(lowerFloor, upperFloor) // 樓層正規化 取得樓層 const floorRegex = /[\d|\w]+F/gmi; + const floorRegex2 = /^FL[\d|\w]+/gmi; const data = await this.getRemoteLevels(); + console.log(data) for (var i = 0; i < data.length; i++) { - let name = data[i].name?.match(floorRegex); - if (name && name[0] == lowerFloor) { + let name = data[i].name?.match(floorRegex) || data[i].name?.match(floorRegex2)[0].split("L")[1] + "F"; + if (name && name[0] == lowerFloor || name == lowerFloor) { lowerIdx = i; } - if (name && name[0] == upperFloor) { - upperIdx = i; + if (name && name[0] == upperFloor || name == upperFloor) { + if (i > upperIdx && lowerFloor == upperFloor) { + + } else { + upperIdx = i; + } } } + this.levels = data; profile(callback); } @@ -1118,7 +1199,7 @@ function getCutPlaneParam(idx, n) { const globalOffset = model.getData().globalOffset; const units = model.getUnitString(); const elevRaw = Autodesk.Viewing.Private.convertUnits('ft', units, 1, level.elevation); - + console.log(globalOffset, units, elevRaw) let d = elevRaw - globalOffset.z - 0.5; if (n == 1) d = -1 * d; diff --git a/Frontend/js/init.js b/Frontend/js/init.js index fff4e71..c456b23 100644 --- a/Frontend/js/init.js +++ b/Frontend/js/init.js @@ -7,8 +7,8 @@ var baseImgUrl = "https://localhost:44376"; // 本地開發用 //var baseImgUrl = "http://220.132.206.5:8848"; // production 用 // WSP -//var baseApiUrl = "http://220.132.206.5"; // production 用 -//var baseImgUrl = "http://220.132.206.5:8849"; // production 用 +// var baseApiUrl = "http://220.132.206.5:8001"; // production 用 +// var baseImgUrl = "http://220.132.206.5:8849"; // production 用 //var baseApiUrl = "http://localhost"; //var baseImgUrl = "http://localhost:8848"; @@ -31,11 +31,17 @@ var common = { } var objSendData = { Data: null }; // Mitsubishi +var elevatorShow = true +var port = ""; var initAreaTag = "TPE"; var n4Sup = "Mitsubishi_JACE8000"; + // WSP -//var initAreaTag = "NTPC"; -//var n4Sup = "Banqiao"; +// var elevatorShow = false +// var port = "4912"; +// var initAreaTag = "NTPC"; +// var n4Sup = "WSP_Supervisor"; + var forgeTokenBase = { url: baseApiUrl + '/api/forge/oauth/token', res_access_token: ["dictionary", "access_token"],