一、場景 1:接收硬件傳感器信號(最常用)

如果感應信號來自硬件設備(如温度傳感器、紅外感應器、運動傳感器等),通常通過以下方式與 Java 程序通信:

  • 串口通信(RS-232/USB):傳感器通過串口線或 USB 轉串口連接電腦,Java 用 RXTX 或 jSerialComm 庫讀取串口數據。
  • USB 直接通信:部分傳感器支持 USB HID 協議,可通過 usb4java 庫訪問。
  • 藍牙 / WiFi:無線傳感器通過藍牙(BlueCove 庫)或 WiFi(TCP/UDP)傳輸數據。

示例:串口通信接收傳感器信號(jSerialComm 庫)

jSerialComm 是一個簡單易用的 Java 串口通信庫,支持 Windows、Linux、Mac。

步驟 1:添加依賴

Maven 依賴:

xml

<dependency>
    <groupId>com.fazecast</groupId>
    <artifactId>jSerialComm</artifactId>
    <version>2.10.3</version> <!-- 最新版本 -->
</dependency>

Gradle 依賴:

groovy

implementation 'com.fazecast:jSerialComm:2.10.3'

步驟 2:Java 代碼實現

java

運行

import com.fazecast.jSerialComm.SerialPort;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class SensorSerialReceiver {
    public static void main(String[] args) {
        // 1. 獲取所有可用串口
        SerialPort[] ports = SerialPort.getCommPorts();
        if (ports.length == 0) {
            System.out.println("未找到可用串口!");
            return;
        }

        // 2. 選擇目標串口(根據實際傳感器連接的串口選擇,如 COM3、/dev/ttyUSB0)
        SerialPort targetPort = ports[0]; // 這裏默認選擇第一個,實際需修改
        System.out.println("選擇的串口:" + targetPort.getSystemPortName());

        // 3. 配置串口參數(需與傳感器一致,如波特率、數據位、停止位、校驗位)
        targetPort.setComPortParameters(
            9600,                // 波特率(常見:9600、115200)
            SerialPort.DATABITS_8, // 數據位
            SerialPort.STOPBITS_1, // 停止位
            SerialPort.PARITY_NONE  // 校驗位(無)
        );
        targetPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 100, 0); // 讀取超時

        // 4. 打開串口
        if (!targetPort.openPort()) {
            System.out.println("串口打開失敗!");
            return;
        }
        System.out.println("串口已打開,等待接收傳感器信號...");

        // 5. 讀取串口數據(傳感器通常按行發送數據,如 "温度:25.5℃\n")
        try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(targetPort.getInputStream(), "UTF-8")
        )) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("收到傳感器信號:" + line);
                // 在這裏解析信號(如提取温度、濕度等)
                parseSensorData(line);
            }
        } catch (Exception e) {
            System.err.println("串口讀取異常:" + e.getMessage());
        } finally {
            // 6. 關閉串口(重要!)
            targetPort.closePort();
            System.out.println("串口已關閉");
        }
    }

    // 解析傳感器數據(根據實際信號格式修改)
    private static void parseSensorData(String data) {
        // 示例:假設信號格式為 "温度:25.5,濕度:60.0"
        if (data.contains("温度:") && data.contains("濕度:")) {
            String tempStr = data.split("温度:")[1].split(",")[0];
            String humidityStr = data.split("濕度:")[1];
            try {
                double temperature = Double.parseDouble(tempStr);
                double humidity = Double.parseDouble(humidityStr);
                System.out.println("解析結果:温度=" + temperature + "℃,濕度=" + humidity + "%");
            } catch (NumberFormatException e) {
                System.err.println("數據解析失敗:" + data);
            }
        }
    }
}

注意事項:

  • 串口參數(波特率、數據位等)必須與傳感器手冊一致,否則會讀取到亂碼。
  • Windows 系統串口名格式為 COMx(如 COM3),Linux/Mac 為 /dev/ttyUSBx 或 /dev/tty.usbmodemx
  • 若傳感器發送二進制數據(而非文本),需用 targetPort.getInputStream() 直接讀取字節流,而非 BufferedReader

二、場景 2:接收網絡傳輸的感應信號(TCP/UDP)

如果感應信號通過網絡(如 WiFi 傳感器、遠程設備)傳輸,Java 可通過 TCP 或 UDP 協議接收。

示例 1:TCP 服務器接收信號(傳感器作為 TCP 客户端)

java

運行

import java.net.ServerSocket;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class SensorTcpServer {
    public static void main(String[] args) {
        int port = 8888; // 監聽端口(需與傳感器配置一致)
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("TCP 服務器啓動,監聽端口 " + port + "...");
            while (true) {
                // 等待傳感器連接
                Socket clientSocket = serverSocket.accept();
                System.out.println("傳感器連接成功:" + clientSocket.getInetAddress());

                // 讀取數據
                try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(clientSocket.getInputStream(), "UTF-8")
                )) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println("收到 TCP 信號:" + line);
                        parseSensorData(line); // 複用上面的解析方法
                    }
                } catch (Exception e) {
                    System.err.println("TCP 連接異常:" + e.getMessage());
                } finally {
                    clientSocket.close();
                    System.out.println("傳感器連接關閉");
                }
            }
        } catch (Exception e) {
            System.err.println("TCP 服務器啓動失敗:" + e.getMessage());
        }
    }

    private static void parseSensorData(String data) {
        // 同場景1的解析邏輯
    }
}

示例 2:UDP 接收信號(無連接,適合實時性要求高的場景)

java

運行

import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.nio.charset.StandardCharsets;

public class SensorUdpReceiver {
    public static void main(String[] args) {
        int port = 8888; // 監聽端口
        try (DatagramSocket socket = new DatagramSocket(port)) {
            System.out.println("UDP 接收器啓動,監聽端口 " + port + "...");
            byte[] buffer = new byte[1024]; // 緩衝區大小(根據信號長度調整)
            while (true) {
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet); // 阻塞等待數據
                String data = new String(packet.getData(), 0, packet.getLength(), StandardCharsets.UTF_8);
                System.out.println("收到 UDP 信號:" + data);
                parseSensorData(data); // 複用解析方法
            }
        } catch (Exception e) {
            System.err.println("UDP 接收器異常:" + e.getMessage());
        }
    }

    private static void parseSensorData(String data) {
        // 同場景1的解析邏輯
    }
}

三、場景 3:接收文件中的感應信號(離線數據)

如果感應信號已保存到文件(如傳感器日誌文件),Java 直接讀取文件即可。

示例:讀取文件中的傳感器信號

java

運行

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class SensorFileReceiver {
    public static void main(String[] args) {
        String filePath = "sensor_data.txt"; // 傳感器數據文件路徑
        try {
            // 讀取文件所有行
            List<String> lines = Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8);
            System.out.println("開始讀取文件:" + filePath);
            for (String line : lines) {
                System.out.println("文件中的信號:" + line);
                parseSensorData(line); // 複用解析方法
            }
        } catch (Exception e) {
            System.err.println("文件讀取異常:" + e.getMessage());
        }
    }

    private static void parseSensorData(String data) {
        // 同場景1的解析邏輯
    }
}

四、關鍵注意事項

  1. 信號格式約定:必須明確傳感器的信號格式(文本 / 二進制、分隔符、數據字段含義),否則無法正確解析。
  2. 異常處理:網絡 / 串口通信容易出現斷連、超時等問題,需加完善的異常捕獲和資源釋放(如 finally 關閉端口 / 連接)。
  3. 線程安全:如果在多線程環境中處理信號(如 UI 程序),需注意線程同步,避免數據競爭。
  4. 性能優化:若信號頻率高(如每秒 1000 次),需優化讀取邏輯(如用 NIO 替代 IO,減少緩衝區拷貝)。

五、常用工具庫總結

通信方式

推薦庫

適用場景

串口

jSerialComm、RXTX

有線傳感器(RS-232/USB)

USB

usb4java

USB 直接連接的傳感器

藍牙

BlueCove

藍牙無線傳感器

網絡

Java 原生 Socket/NIO

WiFi 傳感器、遠程設備

根據你的實際傳感器類型和傳輸方式,選擇對應的方案即可。如果不確定傳感器的通信協議,可以查看傳感器手冊,或用工具(如 SecureCRT 串口調試、Wireshark 網絡抓包)先確認信號格式