FPGA_WebLab/src/stores/equipments.ts

272 lines
6.9 KiB
TypeScript

import { ref, reactive, watchPostEffect } from 'vue'
import { defineStore } from 'pinia'
import { isString, toNumber } from 'lodash';
import { Common } from '@/Common';
import z from "zod"
import { isNumber } from 'mathjs';
import { JtagClient, MatrixKeyClient, PowerClient } from "@/APIClient";
import { Mutex, withTimeout } from 'async-mutex';
import { useConstraintsStore } from "@/stores/constraints";
import { useDialogStore } from './dialog';
export const useEquipments = defineStore('equipments', () => {
// Global Stores
const constrainsts = useConstraintsStore();
const dialog = useDialogStore();
// Basic Info
const boardAddr = ref("127.0.0.1");
const boardPort = ref(1234);
// Jtag
const jtagBitstream = ref<File>();
const jtagBoundaryScanFreq = ref(100);
const jtagClientMutex = withTimeout(new Mutex(), 1000, new Error("JtagClient Mutex Timeout!"))
const jtagClient = new JtagClient();
// Matrix Key
const matrixKeyStates = reactive(new Array<boolean>(16).fill(false))
const matrixKeypadClientMutex = withTimeout(new Mutex(), 1000, new Error("Matrixkeyclient Mutex Timeout!"));
const matrixKeypadClient = new MatrixKeyClient();
// Power
const powerClientMutex = withTimeout(new Mutex(), 1000, new Error("Matrixkeyclient Mutex Timeout!"));
const powerClient = new PowerClient();
// Enable Setting
const enableJtagBoundaryScan = ref(false);
const enableMatrixKey = ref(false);
const enablePower = ref(false)
// Watch
watchPostEffect(async () => {
if (true === enableJtagBoundaryScan.value) jtagBoundaryScan();
});
// Parse and Set
function setAddr(address: string | undefined): boolean {
if (isString(address) && z.string().ip("4").safeParse(address).success) {
boardAddr.value = address;
return true;
}
return false;
}
function setPort(port: string | number | undefined): boolean {
if (isString(port) && port.length != 0) {
const portNumber = toNumber(port);
if (z.number().nonnegative().max(65535).safeParse(portNumber).success) {
boardPort.value = portNumber;
return true;
}
}
else if (isNumber(port)) {
if (z.number().nonnegative().max(65535).safeParse(port).success) {
boardPort.value = port;
return true;
}
}
return 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 jtagBoundaryScan() {
const release = await jtagClientMutex.acquire();
try {
const portStates = await jtagClient.boundaryScanLogicalPorts(
boardAddr.value,
boardPort.value,
);
constrainsts.batchSetConstraintStates(portStates);
} catch (error) {
dialog.error("边界扫描发生错误");
console.error(error);
enableJtagBoundaryScan.value = false;
} finally {
release();
if (enableJtagBoundaryScan.value)
setTimeout(jtagBoundaryScan, 1000 / jtagBoundaryScanFreq.value);
}
}
async function jtagUploadBitstream(bitstream: File): Promise<boolean> {
try {
const resp = await jtagClient.uploadBitstream(
boardAddr.value,
Common.toFileParameterOrNull(bitstream),
);
return resp;
} catch (e) {
dialog.error("上传错误");
console.error(e);
return false;
}
}
async function jtagDownloadBitstream(): Promise<boolean> {
const release = await jtagClientMutex.acquire();
try {
const resp = await jtagClient.downloadBitstream(
boardAddr.value,
boardPort.value
);
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 {
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 {
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 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 resp = await matrixKeypadClient.enabelMatrixKey(
boardAddr.value,
boardPort.value,
);
enableMatrixKey.value = resp;
return resp;
} else {
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 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,
setAddr,
setPort,
setMatrixKey,
// Jtag
enableJtagBoundaryScan,
jtagBitstream,
jtagBoundaryScanFreq,
jtagClientMutex,
jtagClient,
jtagUploadBitstream,
jtagDownloadBitstream,
jtagGetIDCode,
jtagSetSpeed,
// Matrix Key
enableMatrixKey,
matrixKeyStates,
matrixKeypadClientMutex,
matrixKeypadClient,
matrixKeypadEnable,
matrixKeypadSetKeyStates,
// Power
enablePower,
powerClient,
powerClientMutex,
powerSetOnOff,
}
})