HarmonyOS 5.0 AT指令4G透传控制器

HarmonyOS 5.0 AT指令4G透传控制器项目概述基于HarmonyOS 5.0开发的AT指令4G透传控制器,通过发送标准AT指令控制4G模块,实现设备连接、数据传输和网络管理功能。支持多种AT指令集,适用于物联网设备开发和调试。

1. 核心功能

  • AT指令发送:支持自定义AT指令输入和发送

  • 设备响应解析:实时显示设备响应数据

  • 快速指令模板:预置常用AT指令集

  • 连接管理:TCP连接建立、断开和数据传输

  • 状态监控:4G模块状态、信号强度、运营商信息

2. 支持的AT指令

  • 基础指令:AT、AT+CGSN、AT+ICCID等

  • 网络指令:AT+CSQ、AT+CREG、AT+COPS等

  • TCP/IP指令:APN设置、PDP激活、TCP连接、数据收发

  • 短信指令:短信格式设置、短信发送

  • 系统指令:模块重启、温度查询、版本查询

3. 模拟特性

  • 模拟4G模块状态变化(开机、注册、连接等)

  • 模拟信号强度变化

  • 模拟设备响应生成

  • 模拟TCP连接和数据传输

4. UI设计

  • 三选项卡布局(指令控制、快速指令、连接管理)

  • 实时状态显示栏

  • 响应数据颜色编码

  • 现代化卡片式设计

  • 统计信息展示

5. 适用场景

  • 4G模块开发调试

  • 物联网设备测试

  • 通信模块监控

  • 远程设备控制

  • 工业自动化系统

这个应用展示了HarmonyOS 5.0在物联网设备控制和调试领域的应用,可以作为学习AT指令和串口通信的实用工具。

代码

复制代码
// ATCommandController.ets
import { serialPort } from '@kit.SerialPortKit';
import { network } from '@kit.NetworkKit';
import { common } from '@kit.ArkTS';

// AT指令类型
interface ATCommand {
  id: string;
  name: string;
  command: string;
  description: string;
  category: string;
}

// 设备响应
interface DeviceResponse {
  timestamp: number;
  command: string;
  response: string;
  status: 'success' | 'error' | 'timeout';
}

// 4G模块状态
enum ModuleState {
  POWER_OFF = 'power_off',
  POWER_ON = 'power_on',
  REGISTERING = 'registering',
  REGISTERED = 'registered',
  CONNECTED = 'connected'
}

@Entry
@Component
struct ATCommandController {
  // AT指令相关
  @State currentCommand: string = '';
  @State commandHistory: ATCommand[] = [];
  @State deviceResponses: DeviceResponse[] = [];
  
  // 4G模块状态
  @State moduleState: ModuleState = ModuleState.POWER_ON;
  @State signalStrength: number = 0;
  @State networkOperator: string = '中国移动';
  @State imei: string = '864888040000001';
  @State iccid: string = '89860118800000000001';
  
  // 连接参数
  @State apn: string = 'cmnet';
  @State serverAddress: string = 'iot.example.com';
  @State serverPort: number = 8080;
  @State connectionId: number = 0;
  
  // UI状态
  @State currentTab: string = 'control';
  @State showCommandHistory: boolean = false;
  @State showConnectionSettings: boolean = false;
  @State autoScroll: boolean = true;
  
  // 串口模拟
  @State serialPortOpen: boolean = false;
  @State baudRate: number = 115200;
  
  // 统计数据
  @State stats = {
    commandsSent: 0,
    bytesSent: 0,
    bytesReceived: 0,
    connectionTime: 0,
    lastHeartbeat: Date.now()
  };
  
  // 常用AT指令模板
  private commonCommands: ATCommand[] = [
    // 基本指令
    { id: '1', name: 'AT测试', command: 'AT', description: '测试模块是否正常', category: 'basic' },
    { id: '2', name: '查询IMEI', command: 'AT+CGSN', description: '查询设备IMEI号码', category: 'basic' },
    { id: '3', name: '查询ICCID', command: 'AT+ICCID', description: '查询SIM卡ICCID', category: 'basic' },
    
    // 网络指令
    { id: '4', name: '查询信号强度', command: 'AT+CSQ', description: '查询当前信号强度', category: 'network' },
    { id: '5', name: '查询网络注册', command: 'AT+CREG?', description: '查询网络注册状态', category: 'network' },
    { id: '6', name: '查询运营商', command: 'AT+COPS?', description: '查询当前运营商', category: 'network' },
    
    // TCP/IP指令
    { id: '7', name: '设置APN', command: `AT+CGDCONT=1,"IP","${this.apn}"`, description: '设置APN接入点', category: 'tcp' },
    { id: '8', name: '激活PDP', command: 'AT+CGACT=1,1', description: '激活PDP上下文', category: 'tcp' },
    { id: '9', name: 'TCP连接', command: `AT+QIOPEN=1,0,"TCP","${this.serverAddress}",${this.serverPort}`, description: '建立TCP连接', category: 'tcp' },
    { id: '10', name: 'TCP发送', command: 'AT+QISEND=0,10,Hello1234', description: '发送TCP数据', category: 'tcp' },
    { id: '11', name: 'TCP接收', command: 'AT+QIRD=0,1500', description: '读取接收数据', category: 'tcp' },
    { id: '12', name: '关闭连接', command: 'AT+QICLOSE=0', description: '关闭TCP连接', category: 'tcp' },
    
    // 短信指令
    { id: '13', name: '设置短信格式', command: 'AT+CMGF=1', description: '设置短信为文本模式', category: 'sms' },
    { id: '14', name: '发送短信', command: 'AT+CMGS="13800138000"', description: '发送短信', category: 'sms' },
    
    // 其他指令
    { id: '15', name: '重启模块', command: 'AT+CFUN=1,1', description: '重启4G模块', category: 'other' },
    { id: '16', name: '查询温度', command: 'AT+QTEMP', description: '查询模块温度', category: 'other' },
    { id: '17', name: '查询版本', command: 'AT+QGMR', description: '查询模块版本信息', category: 'other' }
  ];
  
  aboutToAppear() {
    // 初始化指令历史
    this.commandHistory = [...this.commonCommands];
    
    // 模拟设备响应
    this.addDeviceResponse({
      timestamp: Date.now() - 3000,
      command: 'AT',
      response: 'OK',
      status: 'success'
    });
    
    // 开始状态更新
    this.startStatusUpdate();
  }
  
  // 开始状态更新
  startStatusUpdate() {
    setInterval(() => {
      this.updateModuleStatus();
    }, 5000);
  }
  
  // 更新模块状态
  updateModuleStatus() {
    // 模拟状态变化
    if (this.moduleState === ModuleState.POWER_ON) {
      this.moduleState = ModuleState.REGISTERING;
    } else if (this.moduleState === ModuleState.REGISTERING) {
      this.moduleState = Math.random() > 0.2 ? ModuleState.REGISTERED : ModuleState.POWER_ON;
    } else if (this.moduleState === ModuleState.REGISTERED) {
      this.moduleState = Math.random() > 0.3 ? ModuleState.CONNECTED : ModuleState.REGISTERED;
    }
    
    // 更新信号强度
    this.signalStrength = Math.floor(Math.random() * 32);
    
    // 更新统计数据
    this.stats.connectionTime = Math.floor((Date.now() - this.stats.lastHeartbeat) / 1000);
  }
  
  // 发送AT指令
  sendATCommand(command?: string) {
    const cmdToSend = command || this.currentCommand.trim();
    
    if (!cmdToSend) {
      this.showToast('请输入AT指令');
      return;
    }
    
    // 添加到历史
    if (!command) {
      const newCmd: ATCommand = {
        id: Date.now().toString(),
        name: '自定义指令',
        command: cmdToSend,
        description: '用户自定义AT指令',
        category: 'custom'
      };
      
      this.commandHistory.unshift(newCmd);
      if (this.commandHistory.length > 50) {
        this.commandHistory.pop();
      }
    }
    
    // 添加到发送记录
    this.addDeviceResponse({
      timestamp: Date.now(),
      command: cmdToSend,
      response: '',
      status: 'success'
    });
    
    // 清空输入框
    if (!command) {
      this.currentCommand = '';
    }
    
    // 更新统计
    this.stats.commandsSent++;
    this.stats.bytesSent += cmdToSend.length;
    
    // 模拟设备响应
    setTimeout(() => {
      this.simulateResponse(cmdToSend);
    }, 100 + Math.random() * 500);
  }
  
  // 模拟设备响应
  simulateResponse(command: string) {
    let response = '';
    let status: 'success' | 'error' | 'timeout' = 'success';
    
    // 根据指令生成响应
    if (command === 'AT') {
      response = 'OK';
    } else if (command === 'AT+CGSN') {
      response = `${this.imei}\nOK`;
    } else if (command === 'AT+ICCID') {
      response = `+ICCID: ${this.iccid}\nOK`;
    } else if (command === 'AT+CSQ') {
      const rssi = this.signalStrength;
      const ber = 0;
      response = `+CSQ: ${rssi},${ber}\nOK`;
    } else if (command === 'AT+CREG?') {
      const stat = this.moduleState === ModuleState.REGISTERED || 
                   this.moduleState === ModuleState.CONNECTED ? 1 : 0;
      response = `+CREG: 0,${stat}\nOK`;
    } else if (command === 'AT+COPS?') {
      response = `+COPS: 0,0,"${this.networkOperator}",0\nOK`;
    } else if (command.startsWith('AT+CGDCONT')) {
      response = 'OK';
    } else if (command === 'AT+CGACT=1,1') {
      response = 'OK';
    } else if (command.startsWith('AT+QIOPEN')) {
      response = 'OK\n\n+QIOPEN: 0,0';
      this.connectionId = 0;
      this.moduleState = ModuleState.CONNECTED;
    } else if (command.startsWith('AT+QISEND')) {
      response = 'OK\n\n>SEND OK';
      this.stats.bytesSent += 10; // 模拟发送数据
    } else if (command.startsWith('AT+QIRD')) {
      response = '+QIRD: 15\nHello from Server\nOK';
      this.stats.bytesReceived += 15;
    } else if (command.startsWith('AT+QICLOSE')) {
      response = 'OK\n\n+QIURC: "closed",0';
      this.moduleState = ModuleState.REGISTERED;
    } else if (command === 'AT+CMGF=1') {
      response = 'OK';
    } else if (command.startsWith('AT+CMGS')) {
      response = '> \n\n+CMGS: 1\nOK';
    } else if (command === 'AT+CFUN=1,1') {
      response = 'OK';
      setTimeout(() => {
        this.moduleState = ModuleState.POWER_ON;
        this.signalStrength = 0;
      }, 2000);
    } else if (command === 'AT+QTEMP') {
      const temp = 35 + Math.random() * 10;
      response = `+QTEMP: ${temp.toFixed(1)}\nOK`;
    } else if (command === 'AT+QGMR') {
      response = 'Revision: EC21CEFAR06A01M4G\nOK';
    } else {
      // 模拟随机响应
      if (Math.random() > 0.8) {
        response = 'ERROR';
        status = 'error';
      } else if (Math.random() > 0.9) {
        status = 'timeout';
      } else {
        response = 'OK';
      }
    }
    
    // 添加到响应列表
    const lastResponseIndex = this.deviceResponses.length - 1;
    if (lastResponseIndex >= 0) {
      this.deviceResponses[lastResponseIndex] = {
        ...this.deviceResponses[lastResponseIndex],
        response: response,
        status: status
      };
    }
    
    // 如果是连接相关指令,更新状态
    if (command.includes('+QIOPEN')) {
      this.moduleState = ModuleState.CONNECTED;
    } else if (command.includes('+QICLOSE')) {
      this.moduleState = ModuleState.REGISTERED;
    }
  }
  
  // 添加到响应列表
  addDeviceResponse(response: DeviceResponse) {
    this.deviceResponses.unshift(response);
    
    // 限制历史记录数量
    if (this.deviceResponses.length > 100) {
      this.deviceResponses.pop();
    }
  }
  
  // 清空响应记录
  clearResponses() {
    this.deviceResponses = [];
  }
  
  // 执行快速命令
  executeQuickCommand(commandId: string) {
    const command = this.commonCommands.find(cmd => cmd.id === commandId);
    if (command) {
      // 替换动态参数
      let cmd = command.command;
      if (cmd.includes('${this.apn}')) {
        cmd = cmd.replace('${this.apn}', this.apn);
      }
      if (cmd.includes('${this.serverAddress}')) {
        cmd = cmd.replace('${this.serverAddress}', this.serverAddress);
      }
      if (cmd.includes('${this.serverPort}')) {
        cmd = cmd.replace('${this.serverPort}', this.serverPort.toString());
      }
      
      this.sendATCommand(cmd);
    }
  }
  
  // 建立TCP连接
  establishTCPConnection() {
    // 执行连接序列
    const commands = [
      `AT+CGDCONT=1,"IP","${this.apn}"`,
      'AT+CGACT=1,1',
      `AT+QIOPEN=1,0,"TCP","${this.serverAddress}",${this.serverPort}`
    ];
    
    let delay = 0;
    commands.forEach(cmd => {
      setTimeout(() => {
        this.sendATCommand(cmd);
      }, delay);
      delay += 1000;
    });
  }
  
  // 断开TCP连接
  disconnectTCP() {
    this.sendATCommand('AT+QICLOSE=0');
  }
  
  // 发送测试数据
  sendTestData() {
    this.sendATCommand('AT+QISEND=0,10,HelloWorld');
  }
  
  // 重启模块
  restartModule() {
    this.sendATCommand('AT+CFUN=1,1');
  }
  
  // 获取状态颜色
  getStateColor(state: ModuleState): string {
    switch (state) {
      case ModuleState.CONNECTED: return '#4CAF50';
      case ModuleState.REGISTERED: return '#8BC34A';
      case ModuleState.REGISTERING: return '#FFC107';
      case ModuleState.POWER_ON: return '#FF9800';
      case ModuleState.POWER_OFF: return '#F44336';
      default: return '#757575';
    }
  }
  
  // 获取状态文本
  getStateText(state: ModuleState): string {
    switch (state) {
      case ModuleState.CONNECTED: return '已连接';
      case ModuleState.REGISTERED: return '已注册';
      case ModuleState.REGISTERING: return '注册中';
      case ModuleState.POWER_ON: return '已开机';
      case ModuleState.POWER_OFF: return '已关机';
      default: return '未知';
    }
  }
  
  // 获取信号强度条
  getSignalBars(): string {
    if (this.signalStrength === 0) return '▁';
    if (this.signalStrength < 10) return '▁▂';
    if (this.signalStrength < 20) return '▁▂▃';
    if (this.signalStrength < 25) return '▁▂▃▄';
    return '▁▂▃▄▅';
  }
  
  // 显示提示
  showToast(message: string) {
    // 在实际应用中可以使用更完善的Toast组件
    console.log('Toast:', message);
  }
  
  build() {
    Column({ space: 0 }) {
      // 顶部状态栏
      Row({ space: 12 }) {
        // 模块状态
        Row({ space: 8 }) {
          Circle({ width: 12, height: 12 })
            .fill(this.getStateColor(this.moduleState))
          
          Column({ space: 2 }) {
            Text(this.getStateText(this.moduleState))
              .fontSize(14)
              .fontColor(this.getStateColor(this.moduleState))
            
            Text('4G模块')
              .fontSize(10)
              .fontColor('#666666')
          }
        }
        .layoutWeight(1)
        
        // 信号强度
        Row({ space: 8 }) {
          Text(this.getSignalBars())
            .fontSize(16)
          
          Column({ space: 2 }) {
            Text(this.signalStrength.toString())
              .fontSize(12)
              .fontColor('#2196F3')
            
            Text('CSQ')
              .fontSize(10)
              .fontColor('#666666')
          }
        }
        
        // 运营商
        Column({ space: 2 }) {
          Text(this.networkOperator)
            .fontSize(12)
            .fontColor('#333333')
          
          Text('运营商')
            .fontSize(10)
            .fontColor('#666666')
        }
      }
      .width('100%')
      .padding(16)
      .backgroundColor('#FFFFFF')
      .border({ bottom: { width: 1, color: '#E0E0E0' } })
      
      // 选项卡
      Row({ space: 0 }) {
        Button('指令控制')
          .fontSize(14)
          .fontColor(this.currentTab === 'control' ? '#2196F3' : '#666666')
          .backgroundColor(this.currentTab === 'control' ? '#E3F2FD' : 'transparent')
          .layoutWeight(1)
          .height(48)
          .borderRadius(0)
          .onClick(() => { this.currentTab = 'control'; })
        
        Button('快速指令')
          .fontSize(14)
          .fontColor(this.currentTab === 'quick' ? '#2196F3' : '#666666')
          .backgroundColor(this.currentTab === 'quick' ? '#E3F2FD' : 'transparent')
          .layoutWeight(1)
          .height(48)
          .borderRadius(0)
          .onClick(() => { this.currentTab = 'quick'; })
        
        Button('连接管理')
          .fontSize(14)
          .fontColor(this.currentTab === 'connection' ? '#2196F3' : '#666666')
          .backgroundColor(this.currentTab === 'connection' ? '#E3F2FD' : 'transparent')
          .layoutWeight(1)
          .height(48)
          .borderRadius(0)
          .onClick(() => { this.currentTab = 'connection'; })
      }
      .width('100%')
      .border({ bottom: { width: 1, color: '#E0E0E0' } })
      
      // 内容区域
      Scroll() {
        Column({ space: 16 }) {
          // 指令控制视图
          if (this.currentTab === 'control') {
            // AT指令输入区域
            Column({ space: 8 }) {
              Row({ space: 8 }) {
                Text('📟')
                  .fontSize(20)
                
                Text('AT指令发送')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#333333')
              }
              
              Row({ space: 8 }) {
                TextInput({ text: this.currentCommand })
                  .layoutWeight(1)
                  .fontSize(14)
                  .backgroundColor('#F5F5F5')
                  .onChange((value: string) => {
                    this.currentCommand = value;
                  })
                
                Button('发送')
                  .fontSize(14)
                  .fontColor('#FFFFFF')
                  .backgroundColor('#2196F3')
                  .padding({ left: 16, right: 16 })
                  .height(40)
                  .borderRadius(20)
                  .onClick(() => {
                    this.sendATCommand();
                  })
              }
              
              Row({ space: 8 }) {
                Button('AT')
                  .fontSize(12)
                  .fontColor('#2196F3')
                  .backgroundColor('#E3F2FD')
                  .padding({ left: 12, right: 12, top: 6, bottom: 6 })
                  .borderRadius(16)
                  .onClick(() => {
                    this.currentCommand = 'AT';
                  })
                
                Button('AT+CGSN')
                  .fontSize(12)
                  .fontColor('#2196F3')
                  .backgroundColor('#E3F2FD')
                  .padding({ left: 12, right: 12, top: 6, bottom: 6 })
                  .borderRadius(16)
                  .onClick(() => {
                    this.currentCommand = 'AT+CGSN';
                  })
                
                Button('AT+CSQ')
                  .fontSize(12)
                  .fontColor('#2196F3')
                  .backgroundColor('#E3F2FD')
                  .padding({ left: 12, right: 12, top: 6, bottom: 6 })
                  .borderRadius(16)
                  .onClick(() => {
                    this.currentCommand = 'AT+CSQ';
                  })
              }
            }
            .padding(16)
            .backgroundColor('#FFFFFF')
            .borderRadius(12)
            .margin({ top: 12, left: 16, right: 16 })
            
            // 设备响应区域
            Column({ space: 8 }) {
              Row({ space: 8 }) {
                Text('📥')
                  .fontSize(20)
                
                Text('设备响应')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#333333')
                
                Text(`(${this.deviceResponses.length})`)
                  .fontSize(12)
                  .fontColor('#666666')
                
                Row({ space: 8 })
                  .layoutWeight(1)
                
                Button('清空')
                  .fontSize(12)
                  .fontColor('#F44336')
                  .backgroundColor(Color.Transparent)
                  .onClick(() => {
                    this.clearResponses();
                  })
              }
              
              // 响应列表
              Column({ space: 4 }) {
                ForEach(this.deviceResponses.slice(0, 20), (response: DeviceResponse, index: number) => {
                  this.buildResponseItem(response, index);
                })
              }
              .height(400)
              .border({ width: 1, color: '#E0E0E0' })
              .borderRadius(8)
              .padding(8)
            }
            .padding(16)
            .backgroundColor('#FFFFFF')
            .borderRadius(12)
            .margin({ left: 16, right: 16 })
          }
          
          // 快速指令视图
          if (this.currentTab === 'quick') {
            Column({ space: 16 }) {
              // 基础指令
              Column({ space: 8 }) {
                Text('🔧 基础指令')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#333333')
                
                Grid() {
                  ForEach(this.commonCommands.filter(cmd => cmd.category === 'basic'), (command: ATCommand) => {
                    GridItem() {
                      this.buildCommandButton(command);
                    }
                  })
                }
                .columnsTemplate('1fr 1fr')
                .rowsTemplate('1fr 1fr')
                .columnsGap(8)
                .rowsGap(8)
              }
              
              // 网络指令
              Column({ space: 8 }) {
                Text('📡 网络指令')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#333333')
                
                Grid() {
                  ForEach(this.commonCommands.filter(cmd => cmd.category === 'network'), (command: ATCommand) => {
                    GridItem() {
                      this.buildCommandButton(command);
                    }
                  })
                }
                .columnsTemplate('1fr 1fr')
                .columnsGap(8)
                .rowsGap(8)
              }
              
              // TCP/IP指令
              Column({ space: 8 }) {
                Text('🌐 TCP/IP指令')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#333333')
                
                Grid() {
                  ForEach(this.commonCommands.filter(cmd => cmd.category === 'tcp'), (command: ATCommand) => {
                    GridItem() {
                      this.buildCommandButton(command);
                    }
                  })
                }
                .columnsTemplate('1fr 1fr 1fr')
                .rowsTemplate('1fr 1fr')
                .columnsGap(8)
                .rowsGap(8)
              }
              
              // 其他指令
              Column({ space: 8 }) {
                Text('📱 其他指令')
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                  .fontColor('#333333')
                
                Grid() {
                  ForEach(this.commonCommands.filter(cmd => cmd.category === 'sms' || cmd.category === 'other'), (command: ATCommand) => {
                    GridItem() {
                      this.buildCommandButton(command);
                    }
                  })
                }
                .columnsTemplate('1fr 1fr 1fr')
                .columnsGap(8)
                .rowsGap(8)
              }
            }
            .padding(16)
          }
          
          // 连接管理视图
          if (this.currentTab === 'connection') {
            Column({ space: 16 }) {
              // 快速操作
              Row({ space: 12 }) {
                Button('建立TCP连接')
                  .fontSize(14)
                  .fontColor('#FFFFFF')
                  .backgroundColor(this.moduleState === ModuleState.CONNECTED ? '#4CAF50' : '#2196F3')
                  .layoutWeight(1)
                  .height(48)
                  .borderRadius(24)
                  .onClick(() => {
                    if (this.moduleState !== ModuleState.CONNECTED) {
                      this.establishTCPConnection();
                    }
                  })
                
                Button('断开连接')
                  .fontSize(14)
                  .fontColor('#F44336')
                  .backgroundColor('#FFEBEE')
                  .layoutWeight(1)
                  .height(48)
                  .borderRadius(24)
                  .onClick(() => {
                    this.disconnectTCP();
                  })
              }
              .width('100%')
              
              // 数据测试
              Row({ space: 12 }) {
                Button('发送测试数据')
                  .fontSize(14)
                  .fontColor('#FFFFFF')
                  .backgroundColor('#4CAF50')
                  .layoutWeight(1)
                  .height(48)
                  .borderRadius(24)
                  .onClick(() => {
                    this.sendTestData();
                  })
                
                Button('重启模块')
                  .fontSize(14)
                  .fontColor('#FFFFFF')
                  .backgroundColor('#FF9800')
                  .layoutWeight(1)
                  .height(48)
                  .borderRadius(24)
                  .onClick(() => {
                    this.restartModule();
                  })
              }
              .width('100%')
              
              // 连接设置
              Column({ space: 12 }) {
                Row({ space: 8 }) {
                  Text('⚙️')
                    .fontSize(20)
                  
                  Text('连接设置')
                    .fontSize(16)
                    .fontWeight(FontWeight.Medium)
                    .fontColor('#333333')
                }
                
                Column({ space: 8 }) {
                  Text('APN接入点')
                    .fontSize(14)
                    .fontColor('#666666')
                  
                  TextInput({ text: this.apn })
                    .width('100%')
                    .fontSize(14)
                    .backgroundColor('#F5F5F5')
                    .onChange((value: string) => {
                      this.apn = value;
                    })
                }
                
                Row({ space: 12 }) {
                  Column({ space: 8 }) {
                    Text('服务器地址')
                      .fontSize(14)
                      .fontColor('#666666')
                    
                    TextInput({ text: this.serverAddress })
                      .width('100%')
                      .fontSize(14)
                      .backgroundColor('#F5F5F5')
                      .onChange((value: string) => {
                        this.serverAddress = value;
                      })
                  }
                  
                  Column({ space: 8 }) {
                    Text('端口')
                      .fontSize(14)
                      .fontColor('#666666')
                    
                    TextInput({ text: this.serverPort.toString() })
                      .width(100)
                      .fontSize(14)
                      .backgroundColor('#F5F5F5')
                      .onChange((value: string) => {
                        this.serverPort = parseInt(value) || 8080;
                      })
                  }
                }
              }
              .padding(16)
              .backgroundColor('#FFFFFF')
              .borderRadius(12)
              
              // 统计信息
              Column({ space: 8 }) {
                Row({ space: 8 }) {
                  Text('📊')
                    .fontSize(20)
                  
                  Text('统计信息')
                    .fontSize(16)
                    .fontWeight(FontWeight.Medium)
                    .fontColor('#333333')
                }
                
                Grid() {
                  GridItem() {
                    this.buildStatCard('指令数', this.stats.commandsSent.toString(), '#2196F3');
                  }
                  
                  GridItem() {
                    this.buildStatCard('发送字节', this.stats.bytesSent.toString(), '#4CAF50');
                  }
                  
                  GridItem() {
                    this.buildStatCard('接收字节', this.stats.bytesReceived.toString(), '#FF9800');
                  }
                  
                  GridItem() {
                    this.buildStatCard('连接时间', 
                      Math.floor(this.stats.connectionTime / 60) + '分', '#9C27B0');
                  }
                }
                .columnsTemplate('1fr 1fr')
                .rowsTemplate('1fr 1fr')
                .columnsGap(8)
                .rowsGap(8)
              }
              .padding(16)
              .backgroundColor('#FFFFFF')
              .borderRadius(12)
            }
            .padding(16)
          }
        }
      }
      .scrollable(ScrollDirection.Vertical)
      .scrollBar(BarState.Auto)
      .margin({ bottom: 60 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
  
  // 构建指令按钮
  @Builder
  buildCommandButton(command: ATCommand) {
    Column({ space: 4 }) {
      Text(command.name)
        .fontSize(12)
        .fontWeight(FontWeight.Medium)
        .fontColor('#333333')
        .textOverflow({ overflow: TextOverflow.Ellipsis })
        .maxLines(1)
      
      Text(command.description)
        .fontSize(10)
        .fontColor('#666666')
        .textOverflow({ overflow: TextOverflow.Ellipsis })
        .maxLines(1)
    }
    .width('100%')
    .padding(8)
    .backgroundColor('#E8F5E9')
    .borderRadius(8)
    .onClick(() => {
      this.executeQuickCommand(command.id);
    })
  }
  
  // 构建响应项
  @Builder
  buildResponseItem(response: DeviceResponse, index: number) {
    Column({ space: 4 }) {
      // 时间戳
      Row({ space: 8 }) {
        Text(new Date(response.timestamp).toLocaleTimeString())
          .fontSize(10)
          .fontColor('#999999')
        
        Circle({ width: 6, height: 6 })
          .fill(response.status === 'success' ? '#4CAF50' : 
                response.status === 'error' ? '#F44336' : '#FF9800')
      }
      
      // 发送的指令
      Text('> ' + response.command)
        .fontSize(12)
        .fontColor('#2196F3')
        .fontFamily('monospace')
      
      // 接收的响应
      if (response.response) {
        Text(response.response.split('\n').map(line => '< ' + line).join('\n'))
          .fontSize(12)
          .fontColor('#4CAF50')
          .fontFamily('monospace')
          .margin({ top: 4 })
      }
    }
    .width('100%')
    .padding(8)
    .backgroundColor(index % 2 === 0 ? '#F9F9F9' : '#FFFFFF')
    .borderRadius(4)
  }
  
  // 构建统计卡片
  @Builder
  buildStatCard(title: string, value: string, color: string) {
    Column({ space: 6 }) {
      Text(value)
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .fontColor(color)
      
      Text(title)
        .fontSize(10)
        .fontColor('#666666')
    }
    .width('100%')
    .padding(12)
    .backgroundColor('#FFFFFF')
    .borderRadius(8)
    .border({ width: 1, color: '#E0E0E0' })
  }
}

想入门鸿蒙开发又怕花冤枉钱?别错过!现在能免费系统学 -- 从 ArkTS 面向对象核心的类和对象、继承多态,到吃透鸿蒙开发关键技能,还能冲刺鸿蒙基础 +高级开发者证书,更惊喜的是考证成功还送好礼!快加入我的鸿蒙班,一起从入门到精通,班级链接:点击https://developer.huawei.com/consumer/cn/training/classDetail/b7365031334e4353a9a0fd6785bb0791?type=1?ha_source=hmosclass\&ha_sourceId=89000248免费进入

相关推荐
御承扬6 小时前
鸿蒙原生系列之动画效果(属性动画)
华为·harmonyos·动画效果
江澎涌7 小时前
JWorker——一套简单易用的基于鸿蒙 Worker 的双向 RPC 通讯机制
typescript·harmonyos·arkts
晚霞的不甘7 小时前
Flutter + OpenHarmony 国际化与无障碍(i18n & a11y)深度实践:打造真正包容的鸿蒙应用
flutter·华为·harmonyos
song5017 小时前
鸿蒙 Flutter 离线缓存架构:多层缓存与数据一致性
人工智能·分布式·flutter·华为·开源鸿蒙
威哥爱编程15 小时前
【鸿蒙开发案例篇】定点出击!鸿蒙6.0视频碰一碰流转+实时进度同步案例
harmonyos·arkts·arkui
嗝o゚17 小时前
鱼与熊掌可兼得?用Flutter+鸿蒙的混合架构破解性能与UI的世纪难题
flutter·架构·harmonyos
遇到困难睡大觉哈哈19 小时前
HarmonyOS 应用数据持久化概述:Preferences、KV-Store、RelationalStore 到底怎么选?
笔记·华为·harmonyos
宇擎智脑科技20 小时前
Flutter 对接高德地图 SDK 适配鸿蒙踩坑记录与通信架构解析
flutter·架构·harmonyos
嗝o゚20 小时前
鸿蒙智慧屏与Flutter适配:无硬件功能的兼容处理
flutter·华为·开源·harmonyos