2026-09-02 16:10:57 +08:00

322 lines
6.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<!-- 消息列表(可上下滑动) -->
<scroll-view class="msgList" scroll-y="true" :scroll-top="scrollTop">
<view v-for="(it, idx) in msgList" :key="idx" class="msgCard" :class="it.dir">
<view class="msgHeader">
<text v-if="it.dir == 'tx'" class="msgTag">{{ 'TX' }}</text>
<text v-else-if="it.dir == 'rx'" class="msgTag">{{ 'RX' }}</text>
<text v-else class="msgTag">{{ '' }}</text>
<text class="msgTime">{{ it.time }}</text>
</view>
<text class="msgBody">{{ it.text }}</text>
</view>
<view style="height: 20px;"></view>
</scroll-view>
<!-- 底部:命令输入 + 按钮 -->
<view class="bottomPanel">
<view class="cmdRow">
<input class="cmdInput" v-model="cmdText" placeholder="输入 CLI 命令,如 help / sysinfo" :disabled="!bleIsConnect" />
<button type="primary" size="mini" class="sendBtn" :disabled="!bleIsConnect || sending" @tap="onSendCmd">{{ sending ? '...' : 'send' }}</button>
</view>
<view class="btnRow">
<button
type="warn"
@click="onConnect"
:disabled="bleIsConnect"
class="btnType"
>connect</button>
<button
type="warn"
@click="onDisConnect"
:disabled="!bleIsConnect"
class="btnType"
>disconnect</button>
<button
type="primary"
@click="onGetStatus"
:disabled="!bleIsConnect"
class="btnType"
>rssi</button>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { MyApiResult } from "@/uni_modules/android-ble"
import * as Ble from "../../../src/BluetoothManager"
import * as McmChannel from "../../../src/mcm/McmChannel.uts"
import * as McmCmd from "../../../src/mcm/McmCommands.uts"
import { CliResult } from "../../../src/mcm/McmChannel.uts"
const bleAddress = ref('')
const bleIsConnect = ref(false) // 蓝牙连接标志 true-已连接 false-未连接
const cmdText = ref("")
const sending = ref(false)
type MsgItem = {
dir: string
text: string
time: string
}
const msgList = ref<Array<MsgItem>>([] as Array<MsgItem>)
const scrollTop = ref(0)
// ===========================功能函数
function nowStr(): string {
const d = new Date()
const hh = d.getHours().toString().padStart(2, '0')
const mm = d.getMinutes().toString().padStart(2, '0')
const ss = d.getSeconds().toString().padStart(2, '0')
return `${hh}:${mm}:${ss}`
}
function pushMsg(dir: string, text: string) {
const item: MsgItem = {
dir: dir,
text: text,
time: nowStr()
}
msgList.value.push(item)
scrollTop.value = scrollTop.value + 9999
}
// ==============================蓝牙事件
function onBleDataListener(res: MyApiResult) {
if (res.type == 1000) {
// notify 订阅成功:协商 MTU 247
Ble.setMtu(247, (mtuRes: MyApiResult) => {
if (mtuRes.type == 0) {
McmChannel.setMtuSize(247)
pushMsg("message", "set MTU 247")
}
})
bleIsConnect.value = true
pushMsg("message", "notify subscribed, ready")
uni.hideLoading()
}
}
function onBleStatueListener(state: number) {
if (state == 10000) {
pushMsg("message", "connect failed")
bleIsConnect.value = false
uni.hideLoading()
} else if (state == 10001) {
pushMsg("message", "disconnected")
bleIsConnect.value = false
}
}
// ==============================蓝牙操作
function onDisConnect() {
if (Ble.isConnected()) {
Ble.disConnect()
}
bleIsConnect.value = false
McmChannel.resetChannel()
}
// 连接蓝牙(走全局 ConnectBle:connect → scanServices → 选中 CA10 服务 → 订阅 notify)
function onConnect() {
if (Ble.isConnected()) {
uni.hideLoading()
bleIsConnect.value = true
return
}
uni.showLoading({
title: "Connecting...",
mask: true
})
pushMsg("start", "connect: " + bleAddress.value)
getApp().globalData.ConnectBle(bleAddress.value, false)
}
// 发送 CLI 命令
async function onSendCmd() {
const cmd = cmdText.value.trim()
if (cmd.length == 0) return
sending.value = true
pushMsg("tx", cmd)
cmdText.value = ""
const r: CliResult = await McmCmd.execCli(cmd, 8000)
sending.value = false
if (r.status == 0) {
pushMsg("rx", r.text.length > 0 ? r.text : "(ok)")
} else if (r.status == 1) {
pushMsg("message", "未知命令或行超长")
} else {
pushMsg("message", "命令失败 status=" + r.status + (r.text.length > 0 ? (", 已收: " + r.text) : ""))
}
}
function onGetStatus() {
Ble.readRssi(function(res: MyApiResult) {
pushMsg("message", res.message + ": " + res.data)
})
}
// ======= 生命周期 ========
let subscribed = false
function subscribe() {
if (subscribed) return
uni.$on("bleData", onBleDataListener)
uni.$on("bleState", onBleStatueListener)
subscribed = true
}
function unsubscribe() {
if (!subscribed) return
uni.$off("bleData", onBleDataListener)
uni.$off("bleState", onBleStatueListener)
subscribed = false
}
onLoad((options: UTSJSONObject | null) => {
if (options != null) {
const address = options["address"] as string | null
if (address != null) {
bleAddress.value = address
}
}
subscribe()
// 已连接(如从设备页过来)则直接进入可用状态
if (Ble.isConnected()) {
bleIsConnect.value = true
pushMsg("message", "already connected: " + Ble.getConnectMac())
}
})
onPageShow(() => {
subscribe()
})
onPageHide(() => {
unsubscribe()
})
onUnload(() => {
unsubscribe()
})
</script>
<style scoped>
.page {
flex: 1;
position: relative;
display: flex;
flex-direction: column;
}
/* 底部面板 */
.bottomPanel {
position: absolute;
left: 0;
right: 0;
bottom: 20px;
background-color: #fff;
padding: 0 12px;
box-sizing: border-box;
box-shadow: 0 -6px 18px rgba(0, 0, 0, 0.12);
}
.cmdRow {
display: flex;
flex-direction: row;
align-items: center;
margin-top: 10px;
}
.cmdInput {
flex: 1;
border-width: 1px;
border-style: solid;
border-color: #ddd;
border-radius: 8px;
padding: 6px 10px;
font-size: 14px;
margin-right: 8px;
}
.sendBtn {
min-width: 60px;
}
.btnRow {
display: flex;
flex-direction: row;
margin-top: 10px;
}
.btnType {
flex: 1;
margin-left: 10px;
min-width: 0;
font-size: 12px;
}
/* 消息列表占满剩余高度 */
.msgList {
flex: 1;
margin-bottom: 120px;
margin-left: 12px;
margin-right: 12px;
}
/* 卡片 */
.msgCard {
border-radius: 12px;
padding: 10px 12px;
margin-bottom: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.06);
background-color: #fff;
}
.msgCard.tx {
border-left-width: 4px;
border-left-style: solid;
border-left-color: #3c9cff;
}
.msgCard.rx {
border-left-width: 4px;
border-left-style: solid;
border-left-color: #67c23a;
}
.msgCard.message {
border-left-width: 4px;
border-left-style: solid;
border-left-color: #7e50c2;
}
.msgCard.start {
border-left-width: 4px;
border-left-style: solid;
border-left-color: #ff5500;
}
.msgHeader {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-bottom: 6px;
}
.msgTag {
font-size: 12px;
color: #333;
}
.msgTime {
font-size: 12px;
color: #999;
}
.msgBody {
font-size: 14px;
color: #222;
}
</style>