389 lines
12 KiB
JavaScript
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,
|
|
};
|
|
}
|