<template>
  <div class="active">
    <div>
      <el-button @click="selectPort" :disabled="beeperStore.opened">选择串口</el-button>
      <el-divider direction="vertical"></el-divider>
      <el-tag v-if="beeperStore.selected">串口已选择</el-tag>
      <el-tag v-else="!beeperStore.selected">请选择串口</el-tag>
    </div>
    <el-divider></el-divider>
    <div>
      <el-button @click="openPort" :disabled="!beeperStore.selected" v-if="!beeperStore.opened">打开串口</el-button>
      <el-button @click="closePort" :disabled="!beeperStore.selected" v-if="beeperStore.opened">关闭串口</el-button>

      <el-divider direction="vertical"></el-divider>
      <el-tag v-if="beeperStore.opened">串口已打开</el-tag>
      <el-tag v-else="!beeperStore.opened">串口未打开</el-tag>
    </div>
    <el-divider></el-divider>
    <div>
      <el-button @click="activeDevice" :disabled="!beeperStore.selected || !beeperStore.opened">激活设备</el-button>
      <el-button @click="inactiveDevice" :disabled="!beeperStore.selected || !beeperStore.opened">取消激活设备</el-button>
    </div>
  </div>
</template>

<script setup>
import useBeeperStore from '@/store/modules/beeper'
import {beeperActive} from '@/api/beeper/info';

const beeperStore = useBeeperStore()
const router = useRouter();
const {proxy} = getCurrentInstance();

let port = beeperStore.port;
let reader = beeperStore.reader;

async function initPort() {
  if (!('serial' in navigator)) {
    proxy.$modal.msgError("当前浏览器不支持串口访问");
    return
  }

  navigator.serial.addEventListener("connect", (event) => {
    proxy.$modal.msgSuccess("设备已连接");
  });

  navigator.serial.addEventListener("disconnect", (event) => {
    proxy.$modal.msgError("设备已断开");
    closePort()
  });
}

async function selectPort() {
  if (!('serial' in navigator)) {
    proxy.$modal.msgError("当前浏览器不支持串口访问");
    return
  }
  try {
    port = await navigator.serial.requestPort()
    beeperStore.setPort(port)
    beeperStore.setSelected(true)
  } catch (e) {
    console.error(e)
    proxy.$modal.msgError("没有选择串口");
  }
}

async function openPort() {
  if (!port) {
    return
  }
  try {
    await port.open({baudRate: 115200});
    readPort(onData)
    beeperStore.setOpened(true)
  } catch (e) {
    proxy.$modal.msgError("串口打开失败");
  }
}

async function onData(intArr) {
  let hex = intArr.map(item => item.toString(16).padStart(2, '0')).join('')
  if (hex.indexOf('aa19') === -1) {
    return
  }
  let {code, data} = await beeperActive({data: hex})
  if (code !== 200) {
    proxy.$modal.msgError("激活失败");
    return
  }
  data = new Uint8Array(data.match(/[\da-f]{2}/gi).map(item => parseInt(item, 16)))
  writePort(data)
  proxy.$modal.msgSuccess("激活成功");
}

async function closePort() {
  if (!port) {
    return
  }
  try {
    if (reader) {
      await reader.cancel()
      reader = null
      beeperStore.setReader(reader)
    }
    if (port) {
      await port.close()
    }
  } catch (e) {
  }
  beeperStore.setOpened(false)
}

const readUidCmd = new Uint8Array([0xAA, 0x18, 0x00, 0x00, 0xFB, 0xA1])
const inactiveCmd = new Uint8Array([0xAA, 0x1A, 0x00, 0x00, 0x3B, 0x00])

async function inactiveDevice() {
  writePort(inactiveCmd)
  proxy.$modal.msgSuccess('取消激活成功')
}

async function activeDevice() {
  writePort(readUidCmd)
}

async function writePort(data) {
  if (!port || !port.writable) {
    return
  }
  const writer = port.writable.getWriter();
  await writer.write(data);
  writer.releaseLock();
}

async function readPort(onData) {
  if (!port || !port.readable) {
    return
  }
  reader = port.readable.getReader();
  beeperStore.setReader(reader)

  let data = [];
  try {
    while (true) {
      const {value, done} = await reader.read();
      if (done) {
        reader.releaseLock();
        break;
      }

      if (data.length === 0) {
        setTimeout(() => {
          onData(data)
          data = []
        }, 100)
      }
      if (value) {
        data.push(...value)
      }
    }
  } catch (error) {
    proxy.$modal.msgError("串口读取错误");
  }
}

initPort()
</script>

<style lang='scss' scoped>
.active {
  padding: 20px;
}
</style>
