import { useState } from "react"; import { WindowConsoleRegular, WarningRegular } from "@fluentui/react-icons"; import { api } from "../../api"; import { Button, Input, Select } from "../ui"; import { AT_COMMAND_GROUPS } from "./atCommands"; import { AtLogEntry, AtTypingBubble, type AtLogItem } from "./AtLogEntry"; import { useI18n } from "../../lib/i18n"; export interface DeviceAtTabProps { deviceId: string; backendMode?: string; atPort?: string; running: boolean; } export function DeviceAtTab({ deviceId, backendMode, atPort, running }: DeviceAtTabProps) { const { t } = useI18n(); const [cmd, setCmd] = useState(""); const [template, setTemplate] = useState(""); const [timeoutMs, setTimeoutMs] = useState(10000); const [sending, setSending] = useState(false); const [log, setLog] = useState([]); const hasAtPort = String(atPort || "").trim().length > 0; const usable = !!running && hasAtPort; const unavailableTitle = running ? (hasAtPort ? t("AT 终端暂不可用") : t("当前设备没有可用 AT 口")) : t("当前设备未运行"); const unavailableDesc = running ? !hasAtPort && backendMode === "qmi" ? t("设备当前处于纯 QMI 模式,但没有解析到可用的 AT 口,因此无法提供 AT 串口终端。") : hasAtPort ? t("当前设备暂时无法提供 AT 串口终端,请稍后重试。") : t("设备当前没有可用的 AT 口,因此无法提供 AT 串口终端。") : t("设备当前未启动,AT 终端暂时不可用。待设备运行后,如果存在可用的 AT 口,即可在这里直接发送 AT 指令。"); async function send() { const command = String(cmd || "").trim(); if (!command) return; setSending(true); setCmd(""); try { const res = await api<{ ok?: boolean; response?: string; result?: string }>(`/devices/${deviceId}/actions/at`, { method: "POST", body: { cmd: command, timeoutMs: timeoutMs || 10000 }, }); setLog((prev) => [ ...prev, { ts: Date.now(), cmd: command, ok: res?.ok ?? true, response: res?.response ?? res?.result ?? JSON.stringify(res ?? {}) }, ]); } catch (e) { setLog((prev) => [...prev, { ts: Date.now(), cmd: command, ok: false, response: e instanceof Error ? e.message : t("请求异常") }]); } finally { setSending(false); } } return (
{t("AT 终端")}
{t("发送 AT 指令并查看回显(多行响应会完整返回)")}
{usable ? ( <>
{log.length === 0 && !sending ? (
{t("暂无 AT 会话记录")}
) : null} {log.map((item, i) => ( ))} {sending ? : null}
{t("快捷指令模板")}
setCmd(e.target.value)} placeholder={t("例如 AT+CSQ (可自由编辑)")} disabled={sending} onKeyDown={(e) => { if (e.key === "Enter") send(); }} />
{t("超时(ms)")}
setTimeoutMs(Number(e.target.value))} placeholder="10000" />
{t("操作")}
) : (
{unavailableTitle}
{unavailableDesc}
)}
); }