fix: frontend upload bitstream failed
This commit is contained in:
		@@ -3,6 +3,8 @@ import { isNull, isUndefined } from "lodash";
 | 
			
		||||
 | 
			
		||||
export namespace Common {
 | 
			
		||||
  export function toFileParameter(object: File): FileParameter {
 | 
			
		||||
    if (isNull(object) || isUndefined(object))
 | 
			
		||||
      throw new Error("File is Null or Undefined");
 | 
			
		||||
    return {
 | 
			
		||||
      data: object,
 | 
			
		||||
      fileName: object.name
 | 
			
		||||
 
 | 
			
		||||
@@ -31,10 +31,9 @@ import { useDialogStore } from "@/stores/dialog";
 | 
			
		||||
import { isNull, isUndefined } from "lodash";
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
  uploadEvent?: Function;
 | 
			
		||||
  downloadEvent?: Function;
 | 
			
		||||
  uploadEvent?: (file: File) => Promise<boolean>;
 | 
			
		||||
  downloadEvent?: () => Promise<boolean>;
 | 
			
		||||
  maxMemory?: number;
 | 
			
		||||
  defaultFile?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<Props>(), {
 | 
			
		||||
@@ -53,7 +52,10 @@ const buttonText = computed(() => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const fileInput = useTemplateRef("fileInput");
 | 
			
		||||
const bitstream = defineModel<File | undefined>();
 | 
			
		||||
const bitstream = defineModel("bitstreamFile", {
 | 
			
		||||
  type: File,
 | 
			
		||||
  default: undefined,
 | 
			
		||||
});
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  if (!isUndefined(bitstream.value) && !isNull(fileInput.value)) {
 | 
			
		||||
    let fileList = new DataTransfer();
 | 
			
		||||
@@ -94,10 +96,10 @@ async function handleClick(event: Event): Promise<void> {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Upload - 修改这里,传递bitstream.value而不是bitstream
 | 
			
		||||
  isUploading.value = true;
 | 
			
		||||
  try {
 | 
			
		||||
    const ret = await props.uploadEvent(event, bitstream.value);
 | 
			
		||||
    const ret = await props.uploadEvent(bitstream.value);
 | 
			
		||||
    console.debug(`After upload bistream: ${bitstream.value}, result: ${ret}`);
 | 
			
		||||
    if (isUndefined(props.downloadEvent)) {
 | 
			
		||||
      if (ret) {
 | 
			
		||||
        dialog.info("上传成功");
 | 
			
		||||
@@ -105,6 +107,10 @@ async function handleClick(event: Event): Promise<void> {
 | 
			
		||||
      } else dialog.error("上传失败");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!ret) {
 | 
			
		||||
      isUploading.value = false;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("上传失败");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,15 +10,15 @@
 | 
			
		||||
    </svg>
 | 
			
		||||
  </div>
 | 
			
		||||
  <Teleport to="#ComponentCapabilities" v-if="selectecComponentID === props.componentId">
 | 
			
		||||
    <MotherBoardCaps :jtagAddr="eqps.boardAddr" :jtagPort="eqps.boardPort.toString()" />
 | 
			
		||||
    <MotherBoardCaps :jtagAddr="props.boardAddr" :jtagPort="toNumber(props.boardPort)" />
 | 
			
		||||
  </Teleport>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="tsx">
 | 
			
		||||
import MotherBoardCaps from "./MotherBoardCaps.vue";
 | 
			
		||||
import { useEquipments } from "@/stores/equipments";
 | 
			
		||||
import { ref, computed, watchEffect, inject } from "vue";
 | 
			
		||||
import { CanvasCurrentSelectedComponentID } from "../InjectKeys";
 | 
			
		||||
import { toNumber } from "lodash";
 | 
			
		||||
 | 
			
		||||
// 主板特有属性
 | 
			
		||||
export interface MotherBoardProps {
 | 
			
		||||
@@ -39,16 +39,6 @@ const selectecComponentID = inject(CanvasCurrentSelectedComponentID, ref(null));
 | 
			
		||||
const width = computed(() => 800 * props.size);
 | 
			
		||||
const height = computed(() => 600 * props.size);
 | 
			
		||||
 | 
			
		||||
// Global store
 | 
			
		||||
const eqps = useEquipments();
 | 
			
		||||
 | 
			
		||||
const bitstreamFile = ref<File | null>();
 | 
			
		||||
 | 
			
		||||
watchEffect(() => {
 | 
			
		||||
  eqps.setAddr(props.boardAddr);
 | 
			
		||||
  eqps.setPort(props.boardPort);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 向外暴露方法
 | 
			
		||||
defineExpose({
 | 
			
		||||
  getInfo: () => ({
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
    <h1 class="font-bold text-center text-2xl">Jtag</h1>
 | 
			
		||||
    <div class="flex flex-col">
 | 
			
		||||
      <p class="grow">Jtag Addr: {{ props.jtagAddr }}</p>
 | 
			
		||||
      <p class="grow">Jtag Port: {{ props.jtagPort }}</p>
 | 
			
		||||
      <p class="grow">Jtag Port: {{ props.jtagPort?.toString() }}</p>
 | 
			
		||||
      <div class="flex justify-between grow">
 | 
			
		||||
        <p>IDCode: 0x{{ jtagIDCode.toString(16).padStart(8, "0") }}</p>
 | 
			
		||||
        <button class="btn btn-circle w-6 h-6" :onclick="getIDCode">
 | 
			
		||||
@@ -17,7 +17,8 @@
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="divider"></div>
 | 
			
		||||
    <UploadCard class="bg-base-200" :upload-event="uploadBitstream" :download-event="downloadBitstream">
 | 
			
		||||
    <UploadCard class="bg-base-200" :upload-event="uploadBitstream" :download-event="downloadBitstream"
 | 
			
		||||
      :bitstream-file="eqps.jtagBitstream" @update:bitstream-file="handleBitstreamChange">
 | 
			
		||||
    </UploadCard>
 | 
			
		||||
    <div class="divider"></div>
 | 
			
		||||
    <button class="btn w-full btn-primary" :class="isEnableJtagBoundaryScan ? '' : 'btn-soft'"
 | 
			
		||||
@@ -32,16 +33,15 @@ import { JtagClient } from "@/APIClient";
 | 
			
		||||
import z from "zod";
 | 
			
		||||
import UploadCard from "@/components/UploadCard.vue";
 | 
			
		||||
import { useDialogStore } from "@/stores/dialog";
 | 
			
		||||
import {
 | 
			
		||||
  useConstraintsStore,
 | 
			
		||||
  type ConstraintLevel,
 | 
			
		||||
} from "@/stores/constraints";
 | 
			
		||||
import { isUndefined, toNumber } from "lodash";
 | 
			
		||||
import { ref, computed, watch } from "vue";
 | 
			
		||||
import { Common } from "@/Common";
 | 
			
		||||
import { useEquipments } from "@/stores/equipments";
 | 
			
		||||
import { useConstraintsStore } from "@/stores/constraints";
 | 
			
		||||
import { isUndefined } from "lodash";
 | 
			
		||||
import { ref, watchEffect } from "vue";
 | 
			
		||||
 | 
			
		||||
interface CapsProps {
 | 
			
		||||
  jtagAddr?: string;
 | 
			
		||||
  jtagPort?: string;
 | 
			
		||||
  jtagPort?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<CapsProps>(), {});
 | 
			
		||||
@@ -49,16 +49,17 @@ const props = withDefaults(defineProps<CapsProps>(), {});
 | 
			
		||||
// Global Stores
 | 
			
		||||
const dialog = useDialogStore();
 | 
			
		||||
const constrainsts = useConstraintsStore();
 | 
			
		||||
const eqps = useEquipments();
 | 
			
		||||
 | 
			
		||||
const jtagController = new JtagClient();
 | 
			
		||||
const isEnableJtagBoundaryScan = ref(false);
 | 
			
		||||
 | 
			
		||||
// 使用传入的属性或默认值
 | 
			
		||||
const jtagIDCode = ref(0);
 | 
			
		||||
const boardAddress = computed(() => props.jtagAddr);
 | 
			
		||||
const boardPort = computed(() =>
 | 
			
		||||
  isUndefined(props.jtagPort) ? undefined : toNumber(props.jtagPort),
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
function handleBitstreamChange(file: File | undefined) {
 | 
			
		||||
  eqps.jtagBitstream = file;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function toggleJtagBoundaryScan() {
 | 
			
		||||
  isEnableJtagBoundaryScan.value = !isEnableJtagBoundaryScan.value;
 | 
			
		||||
@@ -68,8 +69,8 @@ async function toggleJtagBoundaryScan() {
 | 
			
		||||
async function jtagBoundaryScan() {
 | 
			
		||||
  try {
 | 
			
		||||
    const portStates = await jtagController.boundaryScanLogicalPorts(
 | 
			
		||||
      boardAddress.value,
 | 
			
		||||
      boardPort.value,
 | 
			
		||||
      props.jtagAddr,
 | 
			
		||||
      props.jtagPort,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    constrainsts.batchSetConstraintStates(portStates);
 | 
			
		||||
@@ -78,75 +79,78 @@ async function jtagBoundaryScan() {
 | 
			
		||||
    console.error(error);
 | 
			
		||||
    isEnableJtagBoundaryScan.value = false;
 | 
			
		||||
  } finally {
 | 
			
		||||
    if (isEnableJtagBoundaryScan.value) setTimeout(jtagBoundaryScan, 100);
 | 
			
		||||
    if (isEnableJtagBoundaryScan.value) setTimeout(jtagBoundaryScan, 50);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function uploadBitstream(event: Event, bitstream: File) {
 | 
			
		||||
  if (!isUndefined(boardAddress.value) || !isUndefined(boardPort.value)) {
 | 
			
		||||
async function uploadBitstream(bitstream: File): Promise<boolean> {
 | 
			
		||||
  if (isUndefined(props.jtagAddr) || isUndefined(props.jtagPort)) {
 | 
			
		||||
    dialog.error("开发板地址或端口空缺");
 | 
			
		||||
    return;
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const fileParam = {
 | 
			
		||||
    data: bitstream,
 | 
			
		||||
    fileName: bitstream.name,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    console.debug(`Before upload bistream: ${bitstream}`);
 | 
			
		||||
    const resp = await jtagController.uploadBitstream(
 | 
			
		||||
      boardAddress.value,
 | 
			
		||||
      fileParam,
 | 
			
		||||
    );
 | 
			
		||||
    return resp;
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("上传错误");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function downloadBitstream() {
 | 
			
		||||
  if (!boardAddress.value || !boardPort.value) {
 | 
			
		||||
    dialog.error("开发板地址或端口空缺");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const resp = await jtagController.downloadBitstream(
 | 
			
		||||
      boardAddress.value,
 | 
			
		||||
      boardPort.value,
 | 
			
		||||
      props.jtagAddr,
 | 
			
		||||
      Common.toFileParameterOrNull(bitstream),
 | 
			
		||||
    );
 | 
			
		||||
    return resp;
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("上传错误");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
watch([boardAddress, boardPort], () => {
 | 
			
		||||
  if (
 | 
			
		||||
    z.string().ip().safeParse(boardAddress).success &&
 | 
			
		||||
    z.number().positive().safeParse(boardPort).success
 | 
			
		||||
  )
 | 
			
		||||
    getIDCode();
 | 
			
		||||
});
 | 
			
		||||
async function downloadBitstream(): Promise<boolean> {
 | 
			
		||||
  if (isUndefined(props.jtagAddr) || isUndefined(props.jtagPort)) {
 | 
			
		||||
    dialog.error("开发板地址或端口空缺");
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
async function getIDCode() {
 | 
			
		||||
  if (!boardAddress.value || !boardPort.value) {
 | 
			
		||||
  try {
 | 
			
		||||
    const resp = await jtagController.downloadBitstream(
 | 
			
		||||
      props.jtagAddr,
 | 
			
		||||
      props.jtagPort,
 | 
			
		||||
    );
 | 
			
		||||
    return resp;
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("上传错误");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getIDCode(isQuiet: boolean = false) {
 | 
			
		||||
  if (isUndefined(props.jtagAddr) || isUndefined(props.jtagPort)) {
 | 
			
		||||
    dialog.error("开发板地址或端口空缺");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    const resp = await jtagController.getDeviceIDCode(
 | 
			
		||||
      boardAddress.value,
 | 
			
		||||
      boardPort.value,
 | 
			
		||||
      props.jtagAddr,
 | 
			
		||||
      props.jtagPort,
 | 
			
		||||
    );
 | 
			
		||||
    jtagIDCode.value = resp;
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("获取IDCode错误");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
    if (!isQuiet) dialog.error("获取IDCode错误");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
watchEffect(() => {
 | 
			
		||||
  eqps.setAddr(props.jtagAddr);
 | 
			
		||||
  eqps.setPort(props.jtagPort);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
watchEffect(() => {
 | 
			
		||||
  if (
 | 
			
		||||
    z.string().ip().safeParse(props.jtagAddr).success &&
 | 
			
		||||
    z.number().positive().safeParse(props.jtagPort).success
 | 
			
		||||
  )
 | 
			
		||||
    getIDCode(true);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="postcss">
 | 
			
		||||
 
 | 
			
		||||
@@ -7,11 +7,16 @@ import { isNumber } from 'mathjs';
 | 
			
		||||
export const useEquipments = defineStore('equipments', () => {
 | 
			
		||||
  const boardAddr = ref("127.0.0.1")
 | 
			
		||||
  const boardPort = ref(1234)
 | 
			
		||||
  function setAddr(address: string) {
 | 
			
		||||
  const jtagBitstream = ref<File>()
 | 
			
		||||
 | 
			
		||||
  function setAddr(address: string | undefined) {
 | 
			
		||||
    if (isUndefined(address)) return;
 | 
			
		||||
    if (z.string().ip("4").safeParse(address).success)
 | 
			
		||||
      boardAddr.value = address;
 | 
			
		||||
  }
 | 
			
		||||
  function setPort(port: string | number) {
 | 
			
		||||
 | 
			
		||||
  function setPort(port: string | number | undefined) {
 | 
			
		||||
    if (isUndefined(port)) return;
 | 
			
		||||
 | 
			
		||||
    if (isString(port) && port.length != 0) {
 | 
			
		||||
      const portNumber = toNumber(port);
 | 
			
		||||
@@ -23,8 +28,6 @@ export const useEquipments = defineStore('equipments', () => {
 | 
			
		||||
        boardPort.value = port;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  const jtagBitstream = ref<File | undefined>()
 | 
			
		||||
  const remoteUpdateBitstream = ref<File | undefined>()
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    boardAddr,
 | 
			
		||||
@@ -32,7 +35,6 @@ export const useEquipments = defineStore('equipments', () => {
 | 
			
		||||
    setAddr,
 | 
			
		||||
    setPort,
 | 
			
		||||
    jtagBitstream,
 | 
			
		||||
    remoteUpdateBitstream,
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,8 @@
 | 
			
		||||
import { JtagClient, type FileParameter } from "@/APIClient";
 | 
			
		||||
import UploadCard from "@/components/UploadCard.vue";
 | 
			
		||||
import { useDialogStore } from "@/stores/dialog";
 | 
			
		||||
import { toNumber } from "lodash";
 | 
			
		||||
import { Common } from "@/Common";
 | 
			
		||||
import { toNumber, isUndefined } from "lodash";
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
 | 
			
		||||
const jtagController = new JtagClient();
 | 
			
		||||
@@ -54,39 +55,30 @@ const dialog = useDialogStore();
 | 
			
		||||
const boardAddress = ref("127.0.0.1"); // 默认IP地址
 | 
			
		||||
const boardPort = ref("1234"); // 默认端口号
 | 
			
		||||
 | 
			
		||||
async function uploadBitstream(event: Event, bitstream: File) {
 | 
			
		||||
  if (boardAddress.value.length == 0) {
 | 
			
		||||
    dialog.error("开发板地址空缺");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (boardPort.value.length == 0) {
 | 
			
		||||
    dialog.error("开发板端口空缺");
 | 
			
		||||
    return;
 | 
			
		||||
async function uploadBitstream(bitstream: File): Promise<boolean> {
 | 
			
		||||
  if (isUndefined(boardAddress.value) || isUndefined(boardPort.value)) {
 | 
			
		||||
    dialog.error("开发板地址或端口空缺");
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const fileParam: FileParameter = {
 | 
			
		||||
    data: bitstream,
 | 
			
		||||
    fileName: bitstream.name,
 | 
			
		||||
  };
 | 
			
		||||
  try {
 | 
			
		||||
    console.debug(`Before upload bistream: ${bitstream}`);
 | 
			
		||||
    const resp = await jtagController.uploadBitstream(
 | 
			
		||||
      boardAddress.value,
 | 
			
		||||
      fileParam,
 | 
			
		||||
      Common.toFileParameterOrNull(bitstream),
 | 
			
		||||
    );
 | 
			
		||||
    return resp
 | 
			
		||||
    return resp;
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("上传错误");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function downloadBitstream() {
 | 
			
		||||
  if (boardAddress.value.length == 0) {
 | 
			
		||||
    dialog.error("开发板地址空缺");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (boardPort.value.length == 0) {
 | 
			
		||||
    dialog.error("开发板端口空缺");
 | 
			
		||||
    return;
 | 
			
		||||
async function downloadBitstream(): Promise<boolean> {
 | 
			
		||||
  if (isUndefined(boardAddress.value) || isUndefined(boardPort.value)) {
 | 
			
		||||
    dialog.error("开发板地址或端口空缺");
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
@@ -98,6 +90,7 @@ async function downloadBitstream() {
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("上传错误");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user