319 lines
8.6 KiB
TypeScript
319 lines
8.6 KiB
TypeScript
import { ref, reactive, watchPostEffect, onMounted, onUnmounted } from "vue";
|
|
import { defineStore } from "pinia";
|
|
import { useLocalStorage } from "@vueuse/core";
|
|
import { isString, toNumber, isUndefined, type Dictionary } from "lodash";
|
|
import z from "zod";
|
|
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 { AuthManager } from "@/utils/AuthManager";
|
|
import { HubConnection, HubConnectionBuilder } from "@microsoft/signalr";
|
|
import { getHubProxyFactory, getReceiverRegister } from "@/TypedSignalR.Client";
|
|
import type { ResourceInfo } from "@/APIClient";
|
|
import type { IJtagHub } from "@/TypedSignalR.Client/server.Hubs.JtagHub";
|
|
|
|
export const useEquipments = defineStore("equipments", () => {
|
|
// Global Stores
|
|
const constrainsts = useConstraintsStore();
|
|
const dialog = useDialogStore();
|
|
|
|
const boardAddr = useLocalStorage("fpga-board-addr", "127.0.0.1");
|
|
const boardPort = useLocalStorage("fpga-board-port", 1234);
|
|
|
|
// Jtag
|
|
const jtagBitstream = ref<File>();
|
|
const jtagBoundaryScanFreq = ref(100);
|
|
const jtagUserBitstreams = ref<ResourceInfo[]>([]);
|
|
const jtagClientMutex = withTimeout(
|
|
new Mutex(),
|
|
1000,
|
|
new Error("JtagClient Mutex Timeout!"),
|
|
);
|
|
const jtagHubConnection = ref<HubConnection>();
|
|
const jtagHubProxy = ref<IJtagHub>();
|
|
|
|
onMounted(async () => {
|
|
// 每次挂载都重新创建连接
|
|
jtagHubConnection.value =
|
|
AuthManager.createAuthenticatedJtagHubConnection();
|
|
jtagHubProxy.value = getHubProxyFactory("IJtagHub").createHubProxy(
|
|
jtagHubConnection.value,
|
|
);
|
|
|
|
getReceiverRegister("IJtagReceiver").register(jtagHubConnection.value, {
|
|
onReceiveBoundaryScanData: async (msg) => {
|
|
constrainsts.batchSetConstraintStates(msg);
|
|
},
|
|
});
|
|
await jtagHubConnection.value.start();
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
// 断开连接,清理资源
|
|
if (jtagHubConnection.value) {
|
|
jtagHubConnection.value.stop();
|
|
jtagHubConnection.value = undefined;
|
|
jtagHubProxy.value = undefined;
|
|
}
|
|
});
|
|
|
|
// 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...");
|
|
return;
|
|
}
|
|
|
|
if (enable) {
|
|
const ret = await jtagHubProxy.value.startBoundaryScan(
|
|
jtagBoundaryScanFreq.value,
|
|
);
|
|
if (!ret) {
|
|
console.error("Failed to start boundary scan");
|
|
return;
|
|
}
|
|
} else {
|
|
const ret = await jtagHubProxy.value.stopBoundaryScan();
|
|
if (!ret) {
|
|
console.error("Failed to stop boundary scan");
|
|
return;
|
|
}
|
|
}
|
|
enableJtagBoundaryScan.value = enable;
|
|
}
|
|
|
|
async function jtagUploadBitstream(bitstream: File, examId?: string): Promise<number | null> {
|
|
try {
|
|
// 自动开启电源
|
|
await powerSetOnOff(true);
|
|
|
|
const resourceClient = AuthManager.createAuthenticatedResourceClient();
|
|
const resp = await resourceClient.addResource(
|
|
'bitstream',
|
|
'user',
|
|
examId || null,
|
|
toFileParameterOrUndefined(bitstream),
|
|
);
|
|
|
|
// 如果上传成功,设置为当前选中的比特流
|
|
if (resp && resp.id !== undefined && resp.id !== null) {
|
|
return resp.id;
|
|
}
|
|
|
|
return null;
|
|
} catch (e) {
|
|
dialog.error("上传错误");
|
|
console.error(e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function jtagDownloadBitstream(bitstreamId?: number): Promise<boolean> {
|
|
if (bitstreamId === null || bitstreamId === undefined) {
|
|
dialog.error("请先选择要下载的比特流");
|
|
return false;
|
|
}
|
|
|
|
const release = await jtagClientMutex.acquire();
|
|
try {
|
|
// 自动开启电源
|
|
await powerSetOnOff(true);
|
|
|
|
const jtagClient = AuthManager.createAuthenticatedJtagClient();
|
|
const resp = await jtagClient.downloadBitstream(
|
|
boardAddr.value,
|
|
boardPort.value,
|
|
bitstreamId,
|
|
);
|
|
return resp;
|
|
} catch (e) {
|
|
dialog.error("下载错误");
|
|
console.error(e);
|
|
return false;
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
|
|
async function jtagGetIDCode(isQuiet: boolean = false): Promise<number> {
|
|
const release = await jtagClientMutex.acquire();
|
|
try {
|
|
// 自动开启电源
|
|
await powerSetOnOff(true);
|
|
|
|
const jtagClient = AuthManager.createAuthenticatedJtagClient();
|
|
const resp = await jtagClient.getDeviceIDCode(
|
|
boardAddr.value,
|
|
boardPort.value,
|
|
);
|
|
return resp;
|
|
} catch (e) {
|
|
if (!isQuiet) dialog.error("获取IDCode错误");
|
|
return 0xffff_ffff;
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
|
|
async function jtagSetSpeed(speed: number): Promise<boolean> {
|
|
const release = await jtagClientMutex.acquire();
|
|
try {
|
|
// 自动开启电源
|
|
await powerSetOnOff(true);
|
|
|
|
const jtagClient = AuthManager.createAuthenticatedJtagClient();
|
|
const resp = await jtagClient.setSpeed(
|
|
boardAddr.value,
|
|
boardPort.value,
|
|
speed,
|
|
);
|
|
return resp;
|
|
} catch (e) {
|
|
dialog.error("设置Jtag速度失败");
|
|
return false;
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
|
|
async function matrixKeypadSetKeyStates(keyStates: boolean[]) {
|
|
const release = await matrixKeypadClientMutex.acquire();
|
|
console.log("set Key !!!!!!!!!!!!");
|
|
try {
|
|
const matrixKeypadClient =
|
|
AuthManager.createAuthenticatedMatrixKeyClient();
|
|
const resp = await matrixKeypadClient.setMatrixKeyStatus(
|
|
boardAddr.value,
|
|
boardPort.value,
|
|
keyStates,
|
|
);
|
|
return resp;
|
|
} catch (e) {
|
|
dialog.error("设置矩阵键盘时,服务器发生错误");
|
|
return false;
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
|
|
async function matrixKeypadEnable(enable: boolean) {
|
|
const release = await matrixKeypadClientMutex.acquire();
|
|
try {
|
|
if (enable) {
|
|
const matrixKeypadClient =
|
|
AuthManager.createAuthenticatedMatrixKeyClient();
|
|
const resp = await matrixKeypadClient.enabelMatrixKey(
|
|
boardAddr.value,
|
|
boardPort.value,
|
|
);
|
|
enableMatrixKey.value = resp;
|
|
return resp;
|
|
} else {
|
|
const matrixKeypadClient =
|
|
AuthManager.createAuthenticatedMatrixKeyClient();
|
|
const resp = await matrixKeypadClient.disableMatrixKey(
|
|
boardAddr.value,
|
|
boardPort.value,
|
|
);
|
|
enableMatrixKey.value = !resp;
|
|
return resp;
|
|
}
|
|
} catch (e) {
|
|
enableMatrixKey.value = false;
|
|
dialog.error("设置矩阵键盘是否启用时,服务器发生错误");
|
|
return false;
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
|
|
async function powerSetOnOff(enable: boolean) {
|
|
const release = await powerClientMutex.acquire();
|
|
try {
|
|
const powerClient = AuthManager.createAuthenticatedPowerClient();
|
|
const resp = await powerClient.setPowerOnOff(
|
|
boardAddr.value,
|
|
boardPort.value,
|
|
enable,
|
|
);
|
|
return resp;
|
|
} catch (e) {
|
|
dialog.error("无法开关电源");
|
|
console.error(e);
|
|
return false;
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
|
|
return {
|
|
boardAddr,
|
|
boardPort,
|
|
setMatrixKey,
|
|
|
|
// Jtag
|
|
enableJtagBoundaryScan,
|
|
jtagBoundaryScanSetOnOff,
|
|
jtagBitstream,
|
|
jtagBoundaryScanFreq,
|
|
jtagUserBitstreams,
|
|
jtagUploadBitstream,
|
|
jtagDownloadBitstream,
|
|
jtagGetIDCode,
|
|
jtagSetSpeed,
|
|
|
|
// Matrix Key
|
|
enableMatrixKey,
|
|
matrixKeyStates,
|
|
matrixKeypadClientMutex,
|
|
matrixKeypadEnable,
|
|
matrixKeypadSetKeyStates,
|
|
|
|
// Power
|
|
enablePower,
|
|
powerClientMutex,
|
|
powerSetOnOff,
|
|
};
|
|
});
|