首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 透過 Serial Port 控制 Modem 發送 SMS 簡訊完整範例

     編輯:Java 相關知識

背景:傳統 Modem / GSM 模組發送簡訊

雖然現在多用 HTTP API 發簡訊,但在嵌入式、工控、離線環境仍常透過 AT 指令 直接操作串口連接的 Modem/GSM 模組。本文提供基於 javax.comm(或 gnu.io)的完整掃描、連線、發送流程。

核心流程

  1. 列舉所有可用串口(CommPortIdentifier.getPortIdentifiers())。
  2. 篩選 PORT_SERIAL 類型的埠。
  3. 嘗試常見鮑率(9600, 19200, 57600, 115200)開啟連線。
  4. 設定序列埠參數:8N1(8 data bits, No parity, 1 stop bit)+ RTS/CTS 流控。
  5. 發送 AT\r 測試通訊,收到 OK 代表連線正常。
  6. 發送 AT+CGMM\r 取得裝置型號資訊。
  7. 後續可發送 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 指令序列

AT+CMGF=1\r           // 設定為文字模式
AT+CSCS="GSM"\r       // 字元集
AT+CMGS="+886912345678"\r  // 目標號碼,收到 > 提示後
發送內容文字
Ctrl+Z (0x1A)         // 結束送出

常見坑點與解決

  • 權限問題:Linux 需將使用者加入 dialout 或 uucp 群組。
  • 鮑率不匹配:請查閱裝置手冊,部份模組預設 115200。
  • 流控制:若無回應,嘗試關閉流控或改用 XON/XOFF。
  • 編碼:中文簡訊需設定 AT+CSCS="UCS2" 並以 UCS-2 編碼發送 PDU 模式更穩定。
  • JAR 相依:Maven 可用 org.screamingforge:gnu.io:1.0.0 或 com.fazecast:jSerialComm(更現代、無需原生庫)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved