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(); 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(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 { 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 { 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 { 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 { 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, } })