功能説明
這個4G AT指令測試器包含以下功能:

AT指令輸入:用户可以輸入任何AT指令
快捷按鈕:提供常用AT指令的快捷按鈕
指令發送:發送AT指令並獲取模擬響應
歷史記錄:顯示發送過的指令和響應
自動滾動:可選是否自動滾動到最新響應
歷史管理:可以清空歷史記錄
支持的AT指令
工具內置了以下常見AT指令的模擬響應:

AT - 基本測試

AT+CGMI - 查詢製造商

AT+CGMM - 查詢型號

AT+CGSN - 查詢IMEI

AT+CSQ - 信號質量

AT+CREG - 網絡註冊

AT+CGATT - GPRS附着

AT+CEREG - EPS網絡註冊

AT+COPS - 運營商選擇

AT+CGACT - PDP上下文激活

AT+CGDCONT - PDP上下文定義

AT+CIMI - 國際移動用户識別碼

AT+CGREG - GPRS網絡註冊

AT+CGPADDR - 顯示PDP地址

AT+CNUM - 本機號碼

AT+CPIN - SIM卡狀態

AT+CCID - SIM卡識別

使用方法

在輸入框中輸入AT指令(如AT+CSQ)

點擊"發送指令"按鈕

查看響應結果

使用快捷按鈕快速發送常見指令

可以查看歷史記錄或清空歷史

`1. entry/src/main/module.json5

json

{

"module": {

"name": "entry",

"type": "entry",

"mainElement": "EntryAbility",

"deviceTypes": ["phone"],

"pages": "$profile:main_pages",

"abilities": [

{

"name": "EntryAbility",

"srcEntry": "./ets/entryability/EntryAbility.ts",

"skills": [

{

"entities": ["entity.system.home"],

"actions": ["action.system.home"]

}

]

}

],

"requestPermissions": [

{

"name": "ohos.permission.GET_TELEPHONY_STATE"

},

{

"name": "ohos.permission.SET_TELEPHONY_STATE"

}

]

}

}

2. entry/src/main/resources/base/profile/main_pages.json

json

{

"src": ["pages/Index"]

}

3. entry/src/main/resources/base/element/string.json

json

{

"string": [

{

"name": "app_name",

"value": "4G AT指令測試器"

}

]

}

4. entry/src/main/ets/entryability/EntryAbility.ts

typescript

import UIAbility from '@ohos.app.ability.UIAbility';

import window from '@ohos.window';export default class EntryAbility extends UIAbility {

onWindowStageCreate(windowStage: window.WindowStage) {

windowStage.loadContent('pages/Index');

}

}

5. entry/src/main/ets/ATCommand.ts

typescript

export class ATCommand {

private responses: Map<string, string> = new Map();constructor() {

this.initResponses();

}private initResponses() {

this.responses.set('AT', 'OK');

this.responses.set('AT+CGMI', 'HUAWEI');

this.responses.set('AT+CGMM', 'ME909s-821');

this.responses.set('AT+CGSN', '862158040123456');

this.responses.set('AT+CSQ', '+CSQ: 24,99');

this.responses.set('AT+CREG', '+CREG: 0,1');

this.responses.set('AT+CGATT', '+CGATT: 1');

this.responses.set('AT+CEREG', '+CEREG: 0,1');

this.responses.set('AT+COPS', '+COPS: 0,0,"CHN-UNICOM"');

this.responses.set('AT+CGACT', '+CGACT: 1,1');

this.responses.set('AT+CGDCONT', '+CGDCONT: 1,"IP","3gnet"');

this.responses.set('AT+CIMI', '460001234567890');

this.responses.set('AT+CGREG', '+CGREG: 0,1');

this.responses.set('AT+CGPADDR', '+CGPADDR: 1,"10.10.10.10"');

this.responses.set('AT+CNUM', '+CNUM: ,"13800138000",129');

this.responses.set('AT+CPIN', '+CPIN: READY');

this.responses.set('AT+CCID', '89860117802012345678');

}async sendCommand(command: string): Promise {

const cmd = command.trim().toUpperCase();if (!cmd.startsWith('AT')) {
  return 'ERROR: Command must start with AT';
}

return new Promise((resolve) => {
  setTimeout(() => {
    if (this.responses.has(cmd)) {
      resolve(this.responses.get(cmd) || 'OK');
    } else if (cmd.includes('=')) {
      resolve('OK');
    } else {
      resolve('ERROR: Unknown command');
    }
  }, 500);
});}
getCommonCommands(): string[] {

return Array.from(this.responses.keys());

}

}

6. entry/src/main/ets/pages/Index.ets

typescript

import { ATCommand } from '../ATCommand';

import prompt from '@ohos.prompt';@Entry

@Component

struct Index {

@State atCommand: string = 'AT';

@State response: string = '等待發送指令...';

@State history: Array<{command: string, response: string, timestamp: string}> = [];

@State autoScroll: boolean = true;

private atHandler: ATCommand = new ATCommand();build() {

Column({ space: 10 }) {

// 標題

Text('4G AT指令測試器')

.fontSize(25)

.fontWeight(FontWeight.Bold)

.margin({ top: 20, bottom: 10 });// 指令輸入區域
  Column({ space: 5 }) {
    Text('輸入AT指令:')
      .fontSize(16)
      .align(Alignment.Start)
      .width('100%');

    TextInput({ text: this.atCommand })
      .width('100%')
      .height(50)
      .backgroundColor(Color.White)
      .border({ width: 1, color: '#cccccc', radius: 5 })
      .onChange((value: string) => {
        this.atCommand = value;
      });

    Row({ space: 10 }) {
      Button('發送指令')
        .width('60%')
        .height(40)
        .backgroundColor('#007dff')
        .onClick(() => {
          this.sendATCommand();
        });

      Button('清空')
        .width('35%')
        .height(40)
        .backgroundColor('#ff6b6b')
        .onClick(() => {
          this.clearResponse();
        });
    }
    .width('100%')
    .margin({ top: 10 });
  }
  .width('90%')
  .padding(10)
  .backgroundColor('#f5f5f5')
  .borderRadius(10);

  // 常用指令快捷按鈕
  Scroll() {
    Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
      ForEach(this.atHandler.getCommonCommands().slice(0, 8), (cmd: string) => {
        Button(cmd)
          .fontSize(12)
          .width('45%')
          .height(35)
          .margin({ right: '5%', bottom: 10 })
          .onClick(() => {
            this.atCommand = cmd;
            this.sendATCommand();
          });
      });
    }
  }
  .width('90%')
  .height(120)
  .margin({ top: 10 });

  // 響應顯示區域
  Column({ space: 5 }) {
    Row({ space: 10 }) {
      Text('響應內容:')
        .fontSize(16);
      
      Toggle({ type: ToggleType.Checkbox, isOn: this.autoScroll })
        .onChange((value: boolean) => {
          this.autoScroll = value;
        });
        
      Text('自動滾動')
        .fontSize(12);
    }
    .width('100%')
    .justifyContent(FlexAlign.SpaceBetween);

    Scroll() {
      Column() {
        ForEach(this.history, (item: {command: string, response: string, timestamp: string}, index: number) => {
          Column({ space: 5 }) {
            Text(`[${item.timestamp}] ${item.command}`)
              .fontSize(14)
              .fontColor('#0066cc')
              .width('100%')
              .textAlign(TextAlign.Start);
              
            Text(`→ ${item.response}`)
              .fontSize(14)
              .fontColor('#666666')
              .width('100%')
              .textAlign(TextAlign.Start)
              .margin({ left: 10, bottom: 10 });
          }
          .width('100%');
        });
      }
      .width('100%')
    }
    .scrollable(ScrollDirection.Vertical)
    .scrollBar(BarState.Auto)
    .edgeEffect(EdgeEffect.Spring)
    .width('100%')
    .height(250)
    .backgroundColor(Color.White)
    .border({ width: 1, color: '#cccccc', radius: 5 })
    .padding(10);
  }
  .width('90%')
  .margin({ top: 10 });

  // 狀態信息
  Column({ space: 5 }) {
    Row({ space: 20 }) {
      Button('關於')
        .width('45%')
        .height(35)
        .onClick(() => {
          prompt.showToast({ message: '4G AT指令測試器 v1.0', duration: 2000 });
        });
        
      Button('清空歷史')
        .width('45%')
        .height(35)
        .backgroundColor('#ff9800')
        .onClick(() => {
          this.clearHistory();
        });
    }
    .width('100%');
    
    Text('共執行指令: ' + this.history.length + ' 條')
      .fontSize(12)
      .fontColor('#666666')
      .margin({ top: 5 });
  }
  .width('90%')
  .margin({ top: 10, bottom: 20 });
}
.width('100%')
.height('100%')
.backgroundColor('#fafafa')
.alignItems(HorizontalAlign.Center);}
private sendATCommand() {

if (!this.atCommand.trim()) {

prompt.showToast({ message: '請輸入AT指令', duration: 2000 });

return;

}prompt.showToast({ message: '發送中...', duration: 1000 });

this.atHandler.sendCommand(this.atCommand).then((result) => {
  const timestamp = this.getCurrentTime();
  const historyItem = {
    command: this.atCommand,
    response: result,
    timestamp: timestamp
  };
  
  this.history = [historyItem, ...this.history];
  this.response = result;
  
  if (this.autoScroll && this.$scroll) {
    setTimeout(() => {
      // 自動滾動到最新內容
    }, 100);
  }
}).catch((error) => {
  prompt.showToast({ message: '發送失敗', duration: 2000 });
});}
private clearResponse() {

this.atCommand = 'AT';

this.response = '等待發送指令...';

}private clearHistory() {

this.history = [];

prompt.showToast({ message: '歷史已清空', duration: 2000 });

}private getCurrentTime(): string {

const now = new Date();

const hours = now.getHours().toString().padStart(2, '0');

const minutes = now.getMinutes().toString().padStart(2, '0');

const seconds = now.getSeconds().toString().padStart(2, '0');

return ${hours}:${minutes}:${seconds};

}

}`