雖然現在多用 HTTP API 發簡訊,但在嵌入式、工控、離線環境仍常透過 AT 指令 直接操作串口連接的 Modem/GSM 模組。本文提供基於 javax.comm(或 gnu.io)的完整掃描、連線、發送流程。
CommPortIdentifier.getPortIdentifiers())。PORT_SERIAL 類型的埠。AT\r 測試通訊,收到 OK 代表連線正常。AT+CGMM\r 取得裝置型號資訊。AT+CMGF=1(文字模式)、AT+CMGS="號碼" 等指令發送簡訊。package com.example.sms;
import gnu.io.*;
import java.io.*;
import java.util.*;
public class ModemSmsTest {
private static final int[] BAUD_RATES = {9600, 19200, 57600, 115200};
public static void main(String[] args) {
Enumeration<CommPortIdentifier> ports = CommPortIdentifier.getPortIdentifiers();
System.out.println("=== 簡訊裝置連接測試開始 ===");
while (ports.hasMoreElements()) {
CommPortIdentifier portId = ports.nextElement();
if (portId.getPortType() != CommPortIdentifier.PORT_SERIAL) continue;
System.out.println("發現串口: " + portId.getName());
for (int baud : BAUD_RATES) {
System.out.print(" 嘗試鮑率 " + baud + " ... ");
if (testPort(portId, baud)) {
System.out.println("✅ 成功");
// 這裡可進一步發送簡訊指令
} else {
System.out.println("❌ 失敗");
}
}
}
}
private static boolean testPort(CommPortIdentifier portId, int baud) {
SerialPort serial = null;
InputStream in = null;
OutputStream out = null;
try {
serial = (SerialPort) portId.open("SMSLibCommTester", 2000);
serial.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN);
serial.setSerialPortParams(baud, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serial.enableReceiveTimeout(1000);
in = serial.getInputStream();
out = serial.getOutputStream();
// 清空緩衝區
while (in.read() != -1) {}
// 發送 AT 指令
writeBytes(out, "AT\r");
Thread.sleep(500);
String resp = readResponse(in);
if (!resp.contains("OK")) return false;
// 查詢裝置型號
writeBytes(out, "AT+CGMM\r");
Thread.sleep(500);
resp = readResponse(in);
System.out.println(" 裝置回應: " + resp.replaceAll("\\s+OK\\s+", "").trim());
return true;
} catch (Exception e) {
return false;
} finally {
closeQuietly(out);
closeQuietly(in);
if (serial != null) serial.close();
}
}
private static void writeBytes(OutputStream out, String cmd) throws IOException {
out.write(cmd.getBytes());
out.flush();
}
private static String readResponse(InputStream in) throws IOException {
StringBuilder sb = new StringBuilder();
int c;
while ((c = in.read()) != -1) sb.append((char) c);
return sb.toString();
}
private static void closeQuietly(Closeable c) {
if (c != null) try { c.close(); } catch (IOException ignored) {}
}
}
AT+CMGF=1\r // 設定為文字模式
AT+CSCS="GSM"\r // 字元集
AT+CMGS="+886912345678"\r // 目標號碼,收到 > 提示後
發送內容文字
Ctrl+Z (0x1A) // 結束送出
dialout 或 uucp 群組。AT+CSCS="UCS2" 並以 UCS-2 編碼發送 PDU 模式更穩定。org.screamingforge:gnu.io:1.0.0 或 com.fazecast:jSerialComm(更現代、無需原生庫)。