From 79e0ec3e7667444a3f873c0a939bc9b1b5e7fa93 Mon Sep 17 00:00:00 2001 From: Celeste6666 Date: Mon, 6 Feb 2023 00:06:41 +0800 Subject: [PATCH] =?UTF-8?q?[React]=20forge=20=E6=8C=87=E5=AE=9A=E8=A8=AD?= =?UTF-8?q?=E5=82=99=E9=A1=AF=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ibms_react/ibms_react.esproj | 9 +- ibms_react/src/App.css | 38 ------- ibms_react/src/App.js | 12 +- ibms_react/src/App.test.js | 8 -- .../src/components/forges/ForgeModel.js | 103 ++++++++++++++++-- ibms_react/src/index.css | 13 --- ibms_react/src/logo.svg | 1 - ibms_react/src/pages/Monitor.js | 47 ++++++-- ibms_react/src/reportWebVitals.js | 13 --- ibms_react/src/routes/routes.js | 2 +- ibms_react/src/setupTests.js | 5 - ibms_react/src/stores/buildingSlice.js | 2 +- ibms_react/src/stores/deviceListSlice.js | 23 +++- ibms_react/src/stores/forgeSlice.js | 14 ++- ibms_react/src/stores/index.js | 13 ++- ibms_react/src/utils/baja/alarmBaja.js | 3 +- ibms_react/src/utils/baja/bajaUtil.js | 12 ++ ibms_react/src/utils/baja/deviceBaja.js | 45 +++++--- ibms_react/src/utils/baja/electricityBaja.js | 40 ++++--- ibms_react/src/utils/baja/index.js | 8 +- ibms_react/src/utils/forge.js | 27 ++--- ibms_react/src/utils/index.js | 12 +- 22 files changed, 282 insertions(+), 168 deletions(-) delete mode 100644 ibms_react/src/App.css delete mode 100644 ibms_react/src/App.test.js delete mode 100644 ibms_react/src/index.css delete mode 100644 ibms_react/src/logo.svg delete mode 100644 ibms_react/src/reportWebVitals.js delete mode 100644 ibms_react/src/setupTests.js create mode 100644 ibms_react/src/utils/baja/bajaUtil.js diff --git a/ibms_react/ibms_react.esproj b/ibms_react/ibms_react.esproj index ff0c898..9e5face 100644 --- a/ibms_react/ibms_react.esproj +++ b/ibms_react/ibms_react.esproj @@ -4,10 +4,17 @@ src\ Jest - + + npm run build $(MSBuildProjectDirectory)\build + + + + + + \ No newline at end of file diff --git a/ibms_react/src/App.css b/ibms_react/src/App.css deleted file mode 100644 index 74b5e05..0000000 --- a/ibms_react/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/ibms_react/src/App.js b/ibms_react/src/App.js index d9a7b47..77b3539 100644 --- a/ibms_react/src/App.js +++ b/ibms_react/src/App.js @@ -1,4 +1,4 @@ -import { useMemo, useEffect, useState } from "react"; +import { useMemo, useEffect, useState, useCallback } from "react"; import { Outlet, NavLink } from "react-router-dom"; import { useSelector, useDispatch } from "react-redux"; import { Container, Nav, Navbar, NavDropdown } from "react-bootstrap"; @@ -49,6 +49,16 @@ function App() { dispatch(fetchSysMainSub(selectedBuiTag)); } }, [selectedBuiTag]); + + // 離開頁面就清除所有 cookie + //const removeAllCookie = useCallback(() => { + // console.log("關閉分頁時,清除所有 cookie") + // window.addEventListener("beforeunload",() => { + // document.cookie.match(/[^ =;]+(?=\=)/g).forEach(key => { + // document.cookie = `${key}=""; max-age=0`; + // }) }) + //}, []) + return (
{/* 主選單 */} diff --git a/ibms_react/src/App.test.js b/ibms_react/src/App.test.js deleted file mode 100644 index 1f03afe..0000000 --- a/ibms_react/src/App.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/ibms_react/src/components/forges/ForgeModel.js b/ibms_react/src/components/forges/ForgeModel.js index 60478bc..56236ee 100644 --- a/ibms_react/src/components/forges/ForgeModel.js +++ b/ibms_react/src/components/forges/ForgeModel.js @@ -1,17 +1,29 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import * as THREE from "three"; import { fetchForge, shutdownForge } from "@STORE/forgeSlice"; +import { SubscribeDeviceTempByBaja } from "@UTIL" import hotspot from "@ASSET/img/hotspot.svg"; -function ForgeModel({ forgeHeight, sprites = [] }) { +function ForgeModel({ forgeHeight, deviceList = [] }) { const dispatch = useDispatch(); const viewerEl = useRef(null); const { buildingInfo: { urn_3D }, - forgeViewer: { viewer, dataVizExtn, DataVizCore }, + forgeViewer: { viewer, model,dataVizExtn, DataVizCore, structureInfo }, + device: { selectedDeviceSysTag,selectedDeviceNameTag,tempsensorDevList } } = useSelector((store) => store); + const deviceArray = useMemo(()=> deviceList.map(({ device_number, device_coordinate_3d, room_dbid }) => { + return { + id: device_number, // An ID to identify this device + position: JSON.parse(device_coordinate_3d), // World coordinates of this device + roomId: room_dbid, + sensorTypes: ["temperature", "humidity"], // The types/properties this device exposes + temp: 0, + } + }), [selectedDeviceNameTag]) + // 載入 Forge Viewer useEffect(() => { if (urn_3D) { @@ -21,9 +33,9 @@ function ForgeModel({ forgeHeight, sprites = [] }) { urn: urn_3D, }), ); + }; return () => { dispatch(shutdownForge()); - }; } }, [urn_3D]); @@ -38,7 +50,7 @@ function ForgeModel({ forgeHeight, sprites = [] }) { // 熱點點擊事件 const onSpriteClicked = (event) => { const targetDbIds = [event.dbId]; - spriteUpdate(event, targetDbIds, { scale: 1.3, color: { r: 1, g: 0, b: 0 } }); + spriteUpdate(event, targetDbIds, { scale: 1.3, color: { r: 1.0, g: 0, b: 0 } }); console.log(`Sprite clicked:${targetDbIds}`); }; @@ -51,10 +63,9 @@ function ForgeModel({ forgeHeight, sprites = [] }) { // 進入系統監控頁面,出現熱點 useEffect(() => { - if (sprites.length !== 0 && viewer && dataVizExtn) { - // const filterSprites = sprites.map; + if (deviceList.length !== 0 && viewer && dataVizExtn) { dataVizExtn.removeAllViewables(); - sprites.forEach(async ({ device_coordinate_3d, forge_dbid }, index) => { + deviceList.forEach(async ({ device_coordinate_3d, forge_dbid }, index) => { const viewableType = DataVizCore.ViewableType.SPRITE; const spriteColor = new THREE.Color(0xffffff); const spriteIconUrl = hotspot; @@ -78,12 +89,84 @@ function ForgeModel({ forgeHeight, sprites = [] }) { } return () => { - if (sprites.length !== 0 && viewer && dataVizExtn) { + if (deviceList.length !== 0 && viewer && dataVizExtn) { viewer.removeEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked); viewer.removeEventListener(DataVizCore.MOUSE_CLICK_OUT, onSpriteClickedOut); } }; - }, [sprites, dataVizExtn, viewer]); + }, [deviceList, dataVizExtn]); + + // 熱圖 + const getSensorValue = (surfaceShadingPoint) => { + // The `SurfaceShadingPoint.id` property matches one of the identifiers passed to `generateSurfaceShadingData` + const { temp } = surfaceShadingPoint; + return temp / 40; + } + + // 構建熱圖 + const establishHeatMaps = async (deviceList, dataVizExtn) => { + // 不重複的房間值 + const uniqueRoomIds = [...new Set(deviceArray.map(r => r.roomId))]; // 房間唯一值 + const { + SurfaceShadingData, + SurfaceShadingPoint, + SurfaceShadingNode, + } = DataVizCore; + const heatmapData = new SurfaceShadingData(); + uniqueRoomIds.forEach(room_Id => { + // 為每個房間都建立一個 Node + const shadingNode = new SurfaceShadingNode("TemperatureSensor", room_Id); + deviceArray.forEach(({ id, position, roomId, sensorTypes }) => { + // 設備對應的 roomId 用來判斷要加入哪個 Node + if (room_Id === roomId) { + const pt = new SurfaceShadingPoint(id, position, sensorTypes); + shadingNode.addPoint(pt); + } + + }) + heatmapData.addChild(shadingNode); + heatmapData.initialize(viewer.model); + }) + await dataVizExtn.setupSurfaceShading(viewer.model, heatmapData, { + type: "PlanarHeatmap", + slicingPosition: 0.5, // Slicing happens at the vertical mid-point of the geometry + placementPosition: 1.0, // The sliced planar heatmap placed at the base of geometry + minOpacity: 0.0, // The default value if this option is omitted + maxOpacity: 0.5, // The default value if this option is omitted + }); + // 對 "temperature" 的溫度設定兩種顏色:紅色和藍色 + dataVizExtn.registerSurfaceShadingColors("temperature", [0x0000ff, 0x00ff00, 0xffff00, 0xff0000]); + + if (deviceArray.length !== 0) { + const sensorType = "temperature"; + deviceArray.forEach(({ id }) => { + dataVizExtn.renderSurfaceShading(id, sensorType, getSensorValue); + }) + } + } + + useEffect(() => { + if (deviceList && structureInfo && dataVizExtn && selectedDeviceSysTag == "ME") { + // 訂閱有 Temp 的設備 + deviceList.forEach(({ device_number }) => { + SubscribeDeviceTempByBaja(device_number, dispatch) + }) + establishHeatMaps(deviceList, dataVizExtn, structureInfo); + } + return () => { } +}, [selectedDeviceNameTag]); + + useEffect(() => { + if (tempsensorDevList.length !== 0) { + deviceArray.forEach((device) => { + if (tempsensorDevList.findIndex(({ device_number }) => device_number === device.id) !== -1) { + const newTempObj = tempsensorDevList.find(({ device_number }) => device_number === device.id) + device.temp = newTempObj.temp; + dataVizExtn.updateSurfaceShading(getSensorValue); + } + }) + } + }, [tempsensorDevList]) return
; } diff --git a/ibms_react/src/index.css b/ibms_react/src/index.css deleted file mode 100644 index ec2585e..0000000 --- a/ibms_react/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/ibms_react/src/logo.svg b/ibms_react/src/logo.svg deleted file mode 100644 index 9dfc1c0..0000000 --- a/ibms_react/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ibms_react/src/pages/Monitor.js b/ibms_react/src/pages/Monitor.js index 09f6f00..b58f3be 100644 --- a/ibms_react/src/pages/Monitor.js +++ b/ibms_react/src/pages/Monitor.js @@ -3,26 +3,49 @@ import { useParams } from "react-router-dom"; import { useSelector, useDispatch } from "react-redux"; import { Container, Row, Col, Card, ButtonGroup, Button } from "react-bootstrap"; import ForgeModel from "@COM/forges/ForgeModel"; -import { fetchSelectedDeviceMenu, fetchSelectedDeviceList, fetchSelectedDevFlTags } from "@STORE"; +import { fetchSelectedDeviceMenu, fetchSelectedDeviceList, fetchSelectedDevFlTags, changeMainSubSys } from "@STORE"; import defdev from "@ASSET/img/defdev.png"; function Monitor() { const params = useParams().systemId; // main_sub const [main_system_tag, sub_system_tag] = params.split("_"); const dispatch = useDispatch(); const { - buildingInfo: { selectedBuiTag }, device: { selectedDeviceMenu, selectedDeviceList, selectedDeviceFloorTags }, system: { mainSub }, + forgeViewer: { viewer, model }, } = useSelector((state) => state); useEffect(() => { - if (selectedBuiTag && main_system_tag && sub_system_tag) { + if (main_system_tag && sub_system_tag) { + dispatch(changeMainSubSys({ main_system_tag, sub_system_tag })) dispatch(fetchSelectedDeviceMenu({ main_system_tag, sub_system_tag })); dispatch(fetchSelectedDeviceList({ sub_system_tag })); dispatch(fetchSelectedDevFlTags({ sub_system_tag })); } // 載入資料 - }, [main_system_tag, sub_system_tag, selectedBuiTag]); + }, [main_system_tag, sub_system_tag]); + + // 只顯示指定的設備 + // 取得所有 forge dbid + const getAllDbIds = (model) => { + const instanceTree = model.getInstanceTree(); + const allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex); + return allDbIdsStr.map(id => parseInt(id)); + } + useEffect(() => { + if (model && selectedDeviceList.length !== 0) { + console.log(model) + const allDbIds = getAllDbIds(model) + viewer.hide(allDbIds) + const showDbIds = selectedDeviceList.map((d) => parseInt(d.forge_dbid)) + let showNodeDbId = []; + selectedDeviceList.forEach(({ device_nodes }) => { + showNodeDbId = [...showNodeDbId, ...device_nodes.map(({ forge_dbid }) => forge_dbid)] + }) + viewer.show([...showDbIds, ...showNodeDbId]) + } + }, [model, selectedDeviceList]) + return ( <> - - {selectedDeviceList.map(({ device_guid, full_name, forge_dbid }) => ( - + {selectedDeviceList.map(({ device_guid, full_name, forge_dbid, device_floor }) => ( + device_floor === floor_tag ? + @@ -77,13 +101,14 @@ function Monitor() { 功率 kW 詳細內容 - + : + <> ))} @@ -91,7 +116,7 @@ function Monitor() { )} - + diff --git a/ibms_react/src/reportWebVitals.js b/ibms_react/src/reportWebVitals.js deleted file mode 100644 index 5253d3a..0000000 --- a/ibms_react/src/reportWebVitals.js +++ /dev/null @@ -1,13 +0,0 @@ -const reportWebVitals = onPerfEntry => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals; diff --git a/ibms_react/src/routes/routes.js b/ibms_react/src/routes/routes.js index d93b271..74b28df 100644 --- a/ibms_react/src/routes/routes.js +++ b/ibms_react/src/routes/routes.js @@ -20,8 +20,8 @@ const routes = [ /(?:(?:^|.*;\s*)JWT-Authorization\s*\=\s*([^;]*).*$)|^.*$/, "$1", ); - if (window.location.href.includes("localhost:3000") && !JWT_Authorization) { console.log(JWT_Authorization); + if (window.location.href.includes("localhost:3000") && !JWT_Authorization) { return redirect("/login"); } else if (window.location.href.includes("http://220.132.206.5") && !JWT_Authorization) { const account = await setUserAccountByBaja(); diff --git a/ibms_react/src/setupTests.js b/ibms_react/src/setupTests.js deleted file mode 100644 index 8f2609b..0000000 --- a/ibms_react/src/setupTests.js +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; diff --git a/ibms_react/src/stores/buildingSlice.js b/ibms_react/src/stores/buildingSlice.js index 73bb081..272f5d6 100644 --- a/ibms_react/src/stores/buildingSlice.js +++ b/ibms_react/src/stores/buildingSlice.js @@ -16,7 +16,7 @@ const buildingSlice = createSlice({ buildingList: ["中凌大樓"], urn_3D: "", selectedBuiArea: "TPE", - selectedBuiTag: "", + selectedBuiTag: "B1", selectedBuiFullName: "", errMsg: "", }, diff --git a/ibms_react/src/stores/deviceListSlice.js b/ibms_react/src/stores/deviceListSlice.js index 3ea2027..7571781 100644 --- a/ibms_react/src/stores/deviceListSlice.js +++ b/ibms_react/src/stores/deviceListSlice.js @@ -3,6 +3,7 @@ import axios from "axios"; import { deviceBuiMenuBaseUrl, deviceListBaseUrl, deviceFloorBaseUrl } from "@CON"; import { ajaxRes } from "@UTIL"; +// 獲取小類中總覽資料 export const fetchSelectedDeviceMenu = createAsyncThunk( "deviceList/fetchSelectedDeviceMenu", async ({ main_system_tag, sub_system_tag }, thunkAPI) => { @@ -29,14 +30,12 @@ export const fetchSelectedDeviceList = createAsyncThunk( if (code !== "0000" || !data) { return rejectWithValue(msg); } else { - console.log(data) let results=[]; data.forEach((p) => { p.device_list.forEach((d) => { results.push({ ...d, device_floor: p.full_name }); }); }); - console.log("v", [...results]); return fulfillWithValue([...results]); } }, @@ -66,16 +65,30 @@ const deviceListSlice = createSlice({ selectedDeviceMaster: "", // BANK1 selectedDeviceLastName: "", // ELEV selectedDeviceSerialTag: "", // N1 + tempsensorDevList: [], }, reducers: { - getAllDevice: (state, action) => {}, + getAllDevice: (state, action) => { }, + getCurDeviceTemp: (state, { payload }) => { + const { device_number, temp } = payload; + state.tempsensorDevList = state.tempsensorDevList.map((sensor) => { + if (sensor.some(s => s.device_number == device_number)) { + return { ...sensor, temp } + } + return sensor + }) + }, + changeMainSubSys: (state, { payload }) => { + const { main_system_tag, sub_system_tag } = payload; + state.selectedDeviceSysTag = main_system_tag; + state.selectedDeviceNameTag = sub_system_tag; + } }, extraReducers: (builder) => { builder.addCase(fetchSelectedDeviceMenu.fulfilled, (state, { payload }) => { state.selectedDeviceMenu = payload; }); builder.addCase(fetchSelectedDeviceList.fulfilled, (state, { payload }) => { - console.log("de", payload); state.selectedDeviceList = payload; }); @@ -88,5 +101,5 @@ const deviceListSlice = createSlice({ }); const { reducer, actions } = deviceListSlice; -export const { getAllDevice } = actions; +export const { getCurDeviceTemp, changeMainSubSys } = actions; export default reducer; diff --git a/ibms_react/src/stores/forgeSlice.js b/ibms_react/src/stores/forgeSlice.js index d7afdfc..2ce9870 100644 --- a/ibms_react/src/stores/forgeSlice.js +++ b/ibms_react/src/stores/forgeSlice.js @@ -6,7 +6,7 @@ export const fetchForge = createAsyncThunk( async ({ viewerEl, urn }, { dispatch, fulfillWithValue, rejectWithValue }) => { const res = await forgeInit(viewerEl); if (res.ok) { - modelLoad(res.viewer, urn, dispatch); + await modelLoad(res.viewer, urn, dispatch); return fulfillWithValue(res.viewer); } else { return rejectWithValue(res.errCode); @@ -18,8 +18,10 @@ const forgeSlice = createSlice({ name: "forge", initialState: { viewer: null, + model: null, dataVizExtn: null, DataVizCore: null, + structureInfo: null, errCode: 0, urn_3D: "", }, @@ -27,6 +29,14 @@ const forgeSlice = createSlice({ loadDataVizExtn: (state, { payload }) => { state.dataVizExtn = payload; state.DataVizCore = window.Autodesk.DataVisualization.Core; + // heatmap + state.structureInfo = new window.Autodesk.DataVisualization.Core.ModelStructureInfo(state.model); + }, + loadStructureInfo: (state, { payload }) => { + state.structureInfo = payload + }, + loadModel: (state, { payload }) => { + state.model = payload }, shutdownForge: (state, action) => { state.viewer?.finish(); @@ -46,5 +56,5 @@ const forgeSlice = createSlice({ }); const { reducer, actions } = forgeSlice; -export const { shutdownForge, loadDataVizExtn } = actions; +export const { shutdownForge, loadDataVizExtn, loadModel } = actions; export default reducer; diff --git a/ibms_react/src/stores/index.js b/ibms_react/src/stores/index.js index fbf58e2..218f28a 100644 --- a/ibms_react/src/stores/index.js +++ b/ibms_react/src/stores/index.js @@ -5,8 +5,10 @@ import device, { fetchSelectedDeviceList, fetchSelectedDeviceMenu, fetchSelectedDevFlTags, + getCurDeviceTemp, + changeMainSubSys, } from "./deviceListSlice"; -import forgeViewer, { fetchForge, loadDataVizExtn, shutdownForge } from "./forgeSlice"; +import forgeViewer, { fetchForge, loadDataVizExtn, loadModel, shutdownForge } from "./forgeSlice"; import system, { fetchSysMainSub } from "./systemSlice"; import user, { fetchUserInfo, fetchUserAuthPages } from "./userSlice"; import alarm, { fetchBuiAlarmStateByBaja } from "./alarmSlice"; @@ -40,16 +42,25 @@ export default store; export { fetchBuiList, changeBuilding, + fetchSelectedDeviceList, fetchSelectedDeviceMenu, fetchSelectedDevFlTags, + getCurDeviceTemp, + changeMainSubSys, + fetchForge, loadDataVizExtn, + loadModel, shutdownForge, + fetchSysMainSub, + fetchUserInfo, fetchUserAuthPages, + fetchBuiAlarmStateByBaja, + fetchInitElecMeterByBaja, getElectricMeter, getHourElectricMeter, diff --git a/ibms_react/src/utils/baja/alarmBaja.js b/ibms_react/src/utils/baja/alarmBaja.js index e50c395..5bd672c 100644 --- a/ibms_react/src/utils/baja/alarmBaja.js +++ b/ibms_react/src/utils/baja/alarmBaja.js @@ -14,7 +14,8 @@ export async function getBuiAlarmStateByBaja(area_tag, building_tag) { const { msgText, sourceName } = this.get("alarmData").$map.$map; const { $enc: ackState } = this.get("ackState").getType(); const { $enc: sourceState } = this.get("sourceState").getType(); - if (ackState !== "acked" && sourceState !== "normal") { + // 在選單上的顯示警告,只須出現在緊急的 offnormal 設備 + if (sourceState !== "normal") { result.push({ msgText, sourceName, diff --git a/ibms_react/src/utils/baja/bajaUtil.js b/ibms_react/src/utils/baja/bajaUtil.js new file mode 100644 index 0000000..c3c1d30 --- /dev/null +++ b/ibms_react/src/utils/baja/bajaUtil.js @@ -0,0 +1,12 @@ +export function PointSubscribe(baja, sub, ordPath, pointName) { + // ord nq\I + baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}`) + .get() + .then(folder => { + folder.getSlots().is("control:NumericWritable").eachValue((point) => { + if (point.getDisplayName() === pointName) { + baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}/${pointName}`).get({ subscriber: sub }) + } + }) + }) +} \ No newline at end of file diff --git a/ibms_react/src/utils/baja/deviceBaja.js b/ibms_react/src/utils/baja/deviceBaja.js index 9a6bfde..022a513 100644 --- a/ibms_react/src/utils/baja/deviceBaja.js +++ b/ibms_react/src/utils/baja/deviceBaja.js @@ -1,26 +1,35 @@ +import { getCurDeviceTemp } from "@STORE" +import { roundDecimal } from "@UTIL"; // 訂閱設備 // 針對數值的點位 -export function SubscribeDeviceByBaja(ord) { +export function SubscribeDeviceTempByBaja(ordPath, dispatch) { window.require && window.requirejs(["baja!"], (baja) => { console.log("進入 bajaSubscriber 準備執行BQL訂閱"); - const sub = new baja.subscriber(); - sub.attach("changed", (prop, cx) => { - console.log(prop, cx); - }); + const sub = new baja.Subscriber(); + function passValueToFront(temp) { + dispatch(getCurDeviceTemp({ device_number: ordPath, temp })) + } + sub.attach("changed", (prop) => { + if (prop && prop.$displayName === "Out") { + passValueToFront(prop.$getValue().getValueDisplay()) + } + }) + sub.attach("subscribed", (prop) => { + if (prop && prop.$displayName === "Out") { + passValueToFront(prop.$getValue().getValueDisplay()) + } + }) // ord 為要訂閱的點位 - baja.Ord.make(ord) - .get({ - subscriber: sub, - // cursor 對返回的數據做處理 - cursor: { - before: function () {}, - each: function () {}, - after: function () {}, - }, + // ord 為要訂閱的點位 + baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}`) + .get() + .then(folder => { + folder.getSlots().is("control:NumericWritable").eachValue((point) => { + if (point.getDisplayName() === "Temp" || point.getDisplayName() === "TEMP") { + baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}/${point.getDisplayName()}`).get({ subscriber: sub }) + } + }) }) - .then((point) => { - console.log(point); - }); - }); + }) } diff --git a/ibms_react/src/utils/baja/electricityBaja.js b/ibms_react/src/utils/baja/electricityBaja.js index 0169525..d39604f 100644 --- a/ibms_react/src/utils/baja/electricityBaja.js +++ b/ibms_react/src/utils/baja/electricityBaja.js @@ -89,30 +89,34 @@ export async function getCurPower(ordPath, dispatch) { window.require && window.require(["baja!"], function (baja) { const sub = new baja.Subscriber(); - sub.attach("changed", function (prop) { - const value = roundDecimal(this.get("out").getValue()); + function passValueToFront(value) { + const newValue = roundDecimal(value); dispatch( getCurElectricity([ - { data: value, text: "即時功率 " }, - { data: roundDecimal(value / 4), text: "即時契約容量占比 " }, + { data: newValue, text: "即時功率 " }, + { data: roundDecimal(newValue / 4), text: "即時契約容量占比 " }, ]), ); + } + sub.attach("changed", function (prop) { + if (prop && prop.$displayName === "Out") { + passValueToFront(prop.$getValue().getValueDisplay()) + } + }) + sub.attach("subscribed", function (prop) { + if (prop && prop.$displayName === "Out") { + passValueToFront(prop.$getValue().getValueDisplay()) + } }); + // ord 為要訂閱的點位 baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}`) .get() - .then((folder) => { - folder - .getSlots() - .is("control:NumericWritable") - .eachValue((point) => { - if (point.getDisplayName() === "P") { - baja.Ord.make( - `local:|foxs:|station:|slot:/TPE/B1/EE/E4/R2F/NA/WHT/N1/${point.getDisplayName()}`, - ).get({ - subscriber: sub, - }); - } - }); - }); + .then(folder => { + folder.getSlots().is("control:NumericWritable").eachValue((point) => { + if (point.getDisplayName() === "P") { + baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}/${point.getDisplayName() }`).get({ subscriber: sub }) + } + }) + }) }); } diff --git a/ibms_react/src/utils/baja/index.js b/ibms_react/src/utils/baja/index.js index e587455..d14d4f5 100644 --- a/ibms_react/src/utils/baja/index.js +++ b/ibms_react/src/utils/baja/index.js @@ -1,5 +1,5 @@ import { getBuiAlarmStateByBaja, getDeviceAlarmByBaja } from "./alarmBaja"; -import { SubscribeDeviceByBaja } from "./deviceBaja"; +import { SubscribeDeviceTempByBaja } from "./deviceBaja"; import { getTotalElectricByBaja, getCurPower } from "./electricityBaja"; // 下載 N4 內置requireJS function loadRequireJS() { @@ -25,10 +25,14 @@ function setUserAccountByBaja(callBackFunc = null) { export { loadRequireJS, + // 使用者 setUserAccountByBaja, + // alarm getBuiAlarmStateByBaja, getDeviceAlarmByBaja, - SubscribeDeviceByBaja, + // device + SubscribeDeviceTempByBaja, + // eletricity getTotalElectricByBaja, getCurPower, }; diff --git a/ibms_react/src/utils/forge.js b/ibms_react/src/utils/forge.js index c9ae377..f476416 100644 --- a/ibms_react/src/utils/forge.js +++ b/ibms_react/src/utils/forge.js @@ -1,5 +1,5 @@ import { forgeTokenBaseUrl } from "@CON"; -import { loadDataVizExtn } from "@STORE"; +import { loadDataVizExtn, loadModel } from "@STORE"; // 載入 forgeCss 樣式 function loadForgeCss(src) { const link = document.createElement("link"); @@ -72,15 +72,19 @@ export function modelLoad(viewer, urn, dispatch) { const documentId = `urn:${urn}`; window.Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure); - function onDocumentLoadSuccess(viewerDocument) { + async function onDocumentLoadSuccess(viewerDocument) { var defaultModel = viewerDocument.getRoot().getDefaultGeometry(); viewer.loadDocumentNode(viewerDocument, defaultModel); - viewer.addEventListener(window.Autodesk.Viewing.GEOMETRY_LOADED_EVENT, async function () { - // 取得所有 forge dbid - const allDbIds = getAllDbIds(this); - const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization"); - dispatch(loadDataVizExtn(dataVizExtn)); + viewer.addEventListener(window.Autodesk.Viewing.GEOMETRY_LOADED_EVENT, async ()=> { + console.log(viewer.model) + dispatch(loadModel(viewer.model)) + // sprites + const dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization"); + dispatch(loadDataVizExtn(dataVizExtn)); + // heatmap + //const structureInfo = new window.Autodesk.DataVisualization.Core.ModelStructureInfo(viewer.model); + //dispatch(loadStructureInfo(structureInfo)); }); } @@ -89,13 +93,4 @@ export function modelLoad(viewer, urn, dispatch) { } } -// 取得 forge dbid -function getAllDbIds(viewer) { - var instanceTree = viewer.model?.getData().instanceTree; - var allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex); - - return allDbIdsStr.map(function (id) { - return parseInt(id); - }); -} diff --git a/ibms_react/src/utils/index.js b/ibms_react/src/utils/index.js index 5a408e8..f5fb894 100644 --- a/ibms_react/src/utils/index.js +++ b/ibms_react/src/utils/index.js @@ -1,9 +1,13 @@ import { loadRequireJS, + // ϥΪ setUserAccountByBaja, + // alarm getBuiAlarmStateByBaja, getDeviceAlarmByBaja, - SubscribeDeviceByBaja, + // device + SubscribeDeviceTempByBaja, + // eletricity getTotalElectricByBaja, getCurPower, } from "./baja/index"; @@ -14,10 +18,14 @@ import { userLogin } from "./login"; import { roundDecimal } from "./math"; export { loadRequireJS, + // ϥΪ setUserAccountByBaja, + // alarm getBuiAlarmStateByBaja, getDeviceAlarmByBaja, - SubscribeDeviceByBaja, + // device + SubscribeDeviceTempByBaja, + // eletricity getTotalElectricByBaja, getCurPower, forgeInit,