feat: 前端七段数码管添加数字孪生功能

This commit is contained in:
2025-08-16 11:56:27 +08:00
parent 3644c75304
commit 0a1e0982c2
12 changed files with 775 additions and 199 deletions

View File

@@ -7,15 +7,21 @@ import { isNumber } from "mathjs";
import { Mutex, withTimeout } from "async-mutex";
import { useConstraintsStore } from "@/stores/constraints";
import { useDialogStore } from "./dialog";
import { toFileParameterOrUndefined } from "@/utils/Common";
import {
base64ToArrayBuffer,
toFileParameterOrUndefined,
} from "@/utils/Common";
import { AuthManager } from "@/utils/AuthManager";
import { HubConnection, HubConnectionBuilder } from "@microsoft/signalr";
import { HubConnection } from "@microsoft/signalr";
import {
getHubProxyFactory,
getReceiverRegister,
} from "@/utils/signalR/TypedSignalR.Client";
import { ResourcePurpose, type ResourceInfo } from "@/APIClient";
import type { IJtagHub } from "@/utils/signalR/TypedSignalR.Client/server.Hubs";
import type {
IDigitalTubesHub,
IJtagHub,
} from "@/utils/signalR/TypedSignalR.Client/server.Hubs";
export const useEquipments = defineStore("equipments", () => {
// Global Stores
@@ -26,6 +32,7 @@ export const useEquipments = defineStore("equipments", () => {
const boardPort = useLocalStorage("fpga-board-port", 1234);
// Jtag
const enableJtagBoundaryScan = ref(false);
const jtagBitstream = ref<File>();
const jtagBoundaryScanFreq = ref(100);
const jtagUserBitstreams = ref<ResourceInfo[]>([]);
@@ -62,46 +69,6 @@ export const useEquipments = defineStore("equipments", () => {
}
});
// Matrix Key
const matrixKeyStates = reactive(new Array<boolean>(16).fill(false));
const matrixKeypadClientMutex = withTimeout(
new Mutex(),
1000,
new Error("Matrixkeyclient Mutex Timeout!"),
);
// Power
const powerClientMutex = withTimeout(
new Mutex(),
1000,
new Error("Matrixkeyclient Mutex Timeout!"),
);
// Enable Setting
const enableJtagBoundaryScan = ref(false);
const enableMatrixKey = ref(false);
const enablePower = ref(false);
function setMatrixKey(
keyNum: number | string | undefined,
keyValue: boolean,
): boolean {
let _keyNum: number;
if (isString(keyNum)) {
_keyNum = toNumber(keyNum);
} else if (isNumber(keyNum)) {
_keyNum = keyNum;
} else {
return false;
}
if (z.number().nonnegative().max(16).safeParse(_keyNum).success) {
matrixKeyStates[_keyNum] = keyValue;
return true;
}
return false;
}
async function jtagBoundaryScanSetOnOff(enable: boolean) {
if (isUndefined(jtagHubProxy.value)) {
console.error("JtagHub Not Initialize...");
@@ -223,6 +190,34 @@ export const useEquipments = defineStore("equipments", () => {
}
}
// Matrix Key
const enableMatrixKey = ref(false);
const matrixKeyStates = reactive(new Array<boolean>(16).fill(false));
const matrixKeypadClientMutex = withTimeout(
new Mutex(),
1000,
new Error("Matrixkeyclient Mutex Timeout!"),
);
function setMatrixKey(
keyNum: number | string | undefined,
keyValue: boolean,
): boolean {
let _keyNum: number;
if (isString(keyNum)) {
_keyNum = toNumber(keyNum);
} else if (isNumber(keyNum)) {
_keyNum = keyNum;
} else {
return false;
}
if (z.number().nonnegative().max(16).safeParse(_keyNum).success) {
matrixKeyStates[_keyNum] = keyValue;
return true;
}
return false;
}
async function matrixKeypadSetKeyStates(keyStates: boolean[]) {
const release = await matrixKeypadClientMutex.acquire();
console.log("set Key !!!!!!!!!!!!");
@@ -274,6 +269,13 @@ export const useEquipments = defineStore("equipments", () => {
}
}
// Power
const powerClientMutex = withTimeout(
new Mutex(),
1000,
new Error("Matrixkeyclient Mutex Timeout!"),
);
const enablePower = ref(false);
async function powerSetOnOff(enable: boolean) {
const release = await powerClientMutex.acquire();
try {
@@ -293,6 +295,71 @@ export const useEquipments = defineStore("equipments", () => {
}
}
// Seven Segment Display
const enableSevenSegmentDisplay = ref(false);
const sevenSegmentDisplayFrequency = ref(100);
const sevenSegmentDisplayData = ref<Uint8Array>();
const sevenSegmentDisplayHub = ref<HubConnection>();
const sevenSegmentDisplayHubProxy = ref<IDigitalTubesHub>();
async function sevenSegmentDisplaySetOnOff(enable: boolean) {
if (!sevenSegmentDisplayHub.value || !sevenSegmentDisplayHubProxy.value)
return;
await sevenSegmentDisplayHub.value.start();
if (enable) {
await sevenSegmentDisplayHubProxy.value.startScan();
} else {
await sevenSegmentDisplayHubProxy.value.stopScan();
}
}
async function sevenSegmentDisplaySetFrequency(frequency: number) {
if (!sevenSegmentDisplayHub.value || !sevenSegmentDisplayHubProxy.value)
return;
await sevenSegmentDisplayHub.value.start();
await sevenSegmentDisplayHubProxy.value.setFrequency(frequency);
}
async function sevenSegmentDisplayGetStatus() {
if (!sevenSegmentDisplayHub.value || !sevenSegmentDisplayHubProxy.value)
return;
await sevenSegmentDisplayHub.value.start();
return await sevenSegmentDisplayHubProxy.value.getStatus();
}
async function handleSevenSegmentDisplayOnReceive(msg: string) {
const bytes = base64ToArrayBuffer(msg);
sevenSegmentDisplayData.value = new Uint8Array(bytes);
}
onMounted(async () => {
// 每次挂载都重新创建连接
sevenSegmentDisplayHub.value =
AuthManager.createAuthenticatedJtagHubConnection();
sevenSegmentDisplayHubProxy.value = getHubProxyFactory(
"IDigitalTubesHub",
).createHubProxy(sevenSegmentDisplayHub.value);
getReceiverRegister("IDigitalTubesReceiver").register(
sevenSegmentDisplayHub.value,
{
onReceive: handleSevenSegmentDisplayOnReceive,
},
);
});
onUnmounted(() => {
// 断开连接,清理资源
if (sevenSegmentDisplayHub.value) {
sevenSegmentDisplayHub.value.stop();
sevenSegmentDisplayHub.value = undefined;
sevenSegmentDisplayHubProxy.value = undefined;
}
});
return {
boardAddr,
boardPort,
@@ -320,5 +387,13 @@ export const useEquipments = defineStore("equipments", () => {
enablePower,
powerClientMutex,
powerSetOnOff,
// Seven Segment Display
enableSevenSegmentDisplay,
sevenSegmentDisplayData,
sevenSegmentDisplayFrequency,
sevenSegmentDisplaySetOnOff,
sevenSegmentDisplaySetFrequency,
sevenSegmentDisplayGetStatus,
};
});