CviLux_fe/src/hooks/baja/useSystemStatusByBaja.js
2024-10-15 22:17:35 -04:00

389 lines
12 KiB
JavaScript

import { onMounted, ref, computed, watch, markRaw, inject } from "vue";
import { getDashboardDevice } from "@/apis/dashboard";
import useSearchParams from "@/hooks/useSearchParam";
import useSystemHeatmap from "./useSystemHeatmap";
export default function useSystemStatusByBaja(updateHeatBarIsShow) {
const rawData = ref([]);
const forgeViewer = ref(null);
const urn = ref("");
const { searchParams } = useSearchParams();
const initialData = ref(null);
const updateInitialData = (data = false) => {
initialData.value = data;
};
const { updateHeatMapData, updateTemp, initHeatMap } =
useSystemHeatmap(updateHeatBarIsShow);
const updateForgeViewer = (viewer) => {
if (!viewer) {
forgeViewer.value = null;
return;
}
forgeViewer.value = markRaw(viewer);
initHeatMap(viewer);
};
const getSubPoint = (normal, close, error, sub_points) => {
let points = {
...Object.fromEntries(sub_points.map((p) => [p, ""])),
};
if (normal) points[normal] = "";
if (close) points[close] = "";
if (error) points[error] = "";
return points;
};
const subscribeData = ref({});
watch(rawData, () => {
let sub_data = {};
rawData.value.forEach((d) => {
sub_data = {
...sub_data,
...Object.fromEntries(
d.device.map((dev) => [
dev.device_number,
{
...dev,
labelText: d.labelText,
show_value: d.labelText,
device_normal_point_name: d.device_normal_point_name,
device_close_point_name: d.device_close_point_name,
device_error_point_name: d.device_error_point_name,
device_normal_point_value: d.device_normal_point_value,
device_close_point_value: d.device_close_point_value,
device_error_point_value: d.device_error_point_value,
device_normal_color: d.device_normal_color,
device_close_color: d.device_close_color,
device_error_color: d.device_error_color,
forge_dbid: parseInt(dev.forge_dbid),
device_coordinate_3d: dev.device_coordinate_3d
? JSON.parse(dev.device_coordinate_3d)
: { x: 0, y: 0 },
points: getSubPoint(
d.device_normal_point_name,
d.device_close_point_name,
d.device_error_point_name,
d.points
),
is_show: true,
currentColor: d.device_normal_color,
},
])
),
};
});
subscribeData.value = sub_data;
updateHeatMapData(sub_data);
updateSubscribeDataFromBaja(sub_data);
});
const visibleDbid = computed(() => {
let visible = [];
rawData.value.forEach((d) => {
visible = [
...visible,
...d.device.map((dev) => parseInt(dev.forge_dbid)),
];
});
return visible;
});
const getDevice = async (option = 1) => {
const res = await getDashboardDevice({
option: parseInt(option),
});
rawData.value = res.data.map((d) => ({
...d,
key: d.subSys,
}));
};
// subscribe from baja
const booleanPointFacets = ref({});
const updateFacets = (point, facets) => {
booleanPointFacets.value = {
...booleanPointFacets,
[point]: facets,
};
};
const updateDeviceData = (device_number, point, value) => {
const correspondPoint = initialData.value.points.find(
({ name }) => name === point
);
// console.log("sub 回傳值 ", typeof value)
const text = correspondPoint
? correspondPoint.values.find(
({ value: pValue }) => pValue === parseInt(value)
)?.text || ""
: value;
// console.log("sub", correspondPoint, device_number, point, value);
subscribeData.value[device_number].points[point] = text;
if (
point.toLowerCase() === "temp" &&
parseInt(searchParams.value.option) > 1
) {
updateTemp(device_number, value);
}
if (point === subscribeData.value[device_number].device_error_point_name) {
subscribeData.value[device_number].currentColor =
value === subscribeData.value[device_number].device_error_point_value
? subscribeData.value[device_number].device_error_color
: subscribeData.value[device_number].device_normal_color;
}
updateLabelText(device_number, point, text);
};
const transformDeviceNumber = (device_number) => {
return device_number.replaceAll("_", "/");
};
const updateLabelText = (key, point, value) => {
let text = subscribeData.value[key].labelText.replace(`%${point}`, value);
Object.keys(subscribeData.value[key].points)
.filter((p) => p !== point)
.forEach((p) => {
text = text.replace(`%${p}`, subscribeData.value[key].points[p]);
});
subscribeData.value[key].show_value = text;
};
const subComponents = ref(null);
const updateSubscribeDataFromBaja = (data) => {
for (let [key, value] of Object.entries(data)) {
window.require &&
window.requirejs(["baja!"], (baja) => {
console.log("進入 bajaSubscriber 準備執行BQL訂閱");
const ordPath = transformDeviceNumber(key);
baja.Ord.make(`local:|foxs:|station:|slot:/${ordPath}`)
.get()
.then((folder) => {
const batch = new baja.comm.Batch();
const sub = new baja.Subscriber();
sub.attach({
changed: function (prop, cx) {
if (prop.$getDisplayName() !== "Out") return;
if (
Object.hasOwn(
booleanPointFacets.value,
prop.$complex.$propInParent.$slotName
)
) {
const facets =
booleanPointFacets.value[
prop.$complex.$propInParent.$slotName
];
for (let [facetKey, facetValue] of Object.entries(facets)) {
if (facetValue === prop.$getValue().getValueDisplay()) {
updateDeviceData(
key,
prop.$complex.$propInParent.$slotName,
facetKey
);
}
}
} else {
updateDeviceData(
key,
prop.$complex.$propInParent.$slotName,
prop.$getValue().getValueDisplay()
);
}
},
});
folder
.getSlots()
.is("control:ControlPoint")
.eachValue((point) => {
if (
Object.keys(value.points).includes(point.getDisplayName())
) {
baja.Ord.make(
`local:|foxs:|station:|slot:/${ordPath}/${point.getDisplayName()}`
)
.get()
.then((component) => {
if (
point.getType().getTypeSpec() ===
"control:BooleanWritable"
) {
const facets = component.getFacets1().toObject();
updateFacets(point.getDisplayName(), facets);
for (let [facetKey, facetValue] of Object.entries(
facets
)) {
if (
facetValue ===
component.getOut().getValue().toString()
) {
updateDeviceData(
key,
point.getDisplayName(),
facetKey
);
}
}
} else {
updateDeviceData(
key,
point.getDisplayName(),
component.getOut().getValue()
);
}
sub
.subscribe({
comps: component, // Can also just be an singular Component instance
batch, // if defined, any network calls will be batched into this object (optional)
})
.then(() => {
console.log("subscribed successfully");
subComponents.value = sub;
})
.catch(function (err) {
baja.error(
"some components failed to subscribe: " + err
);
});
});
}
});
});
});
}
};
const updateDbidPosition = (viewer, data) => {
if (!viewer) return;
if (!forgeViewer.value) forgeViewer.value = markRaw(viewer);
const tree = viewer.model.getData().instanceTree;
const fragList = viewer.model.getFragmentList();
for (let [key, value] of Object.entries(data)) {
const nodebBox = new window.THREE.Box3();
// for each fragId on the list, get the bounding box
tree.enumNodeFragments(
value.forge_dbid,
(fragId) => {
const fragbBox = new window.THREE.Box3();
fragList.getWorldBounds(fragId, fragbBox);
nodebBox.union(fragbBox); // create a unifed bounding box
},
true
);
subscribeData.value[key].device_coordinate_3d = viewer.worldToClient(
nodebBox.getCenter()
);
subscribeData.value[key].is_show = viewer.isNodeVisible(value.forge_dbid);
}
};
const fitToView = () => {
if(!searchParams.value.camera_position) return
const { x, y, z } = JSON.parse(searchParams.value.camera_position);
const newPosition = new THREE.Vector3(x, y, z); //!<<< 相机的新位置
const {
x: x1,
y: y1,
z: z1,
} = JSON.parse(searchParams.value.target_position); //!<<< 计算新焦点位置
const newTarget = new THREE.Vector3(x1, y1, z1); //!<<< 焦點的新位置
forgeViewer.value.navigation.getCamera().setView({
position: newPosition.clone(),
target: newTarget.clone(),
});
setTimeout(() => {
updateDbidPosition(forgeViewer.value, subscribeData.value);
}, 700);
};
const hideAllObjects = (instanceTree, filDbids = []) => {
const tree = instanceTree || forgeViewer.value.model?.getInstanceTree();
const allDbIdsStr = Object.keys(tree.nodeAccess.dbIdToIndex);
for (var i = 0; i < allDbIdsStr.length; i++) {
forgeViewer.value.hide(parseInt(allDbIdsStr[i]));
}
for (var i = 0; i < filDbids.length; i++) {
forgeViewer.value.show(parseInt(filDbids[i]));
}
fitToView();
forgeViewer.value.impl.invalidate(true);
};
const loadModel = (viewer, urn) => {
return new Promise(function (resolve, reject) {
async function onDocumentLoadSuccess(doc) {
viewer.setGroundShadow(false);
viewer.impl.renderer().setClearAlpha(0); //clear alpha channel
viewer.impl.glrenderer().setClearColor(0xffffff, 0); //set transparent background, color code does not matter
viewer.impl.invalidate(true); //trigger rendering
const documentNode = await viewer.loadDocumentNode(
doc,
doc.getRoot().getDefaultGeometry()
);
resolve(documentNode);
}
function onDocumentLoadFailure(code, message, errors) {
reject({ code, message, errors });
}
Autodesk.Viewing.Document.load(
"urn:" + urn,
onDocumentLoadSuccess,
onDocumentLoadFailure
);
});
};
const reloadModal = () => {};
watch(visibleDbid, (newValue) => {
forgeViewer.value &&
hideAllObjects(forgeViewer.value.model.getData().instanceTree, newValue);
});
watch(initialData, (newValue) => {
if (newValue) {
getDevice(searchParams.value.option);
}
});
watch(
searchParams,
(newValue) => {
getDevice(newValue.option);
},
{
deep: true,
}
);
return {
subscribeData,
visibleDbid,
updateDbidPosition,
hideAllObjects,
updateForgeViewer,
loadModel,
urn,
updateInitialData,
subComponents,
};
}