簡體   English   中英

如何使 java 應用程序與 ESP32 板通信?

[英]How do I make a java app communicate with an ESP32 board?

我一直在嘗試在 ESP32 板和 Java 服務器之間建立 TCP 套接字連接。 建立連接后,我希望服務器向 ESP32 發送一個數據包以請求其 ID(我使用 ID 來識別客戶端,因為它們會更多),但服務器似乎沒有傳輸任何東西(ESP32 沒有接收任何東西)。 我什至嘗試使用 Wireshark 來跟蹤數據包,但是在連接時,沒有消息可以看到。 對不起,可怕的代碼,在通信編程方面,我仍然是初學者。 在此先感謝您的幫助。

這是 ESP32 的代碼:

#include <WiFi.h>

WiFiClient client;

// network info
char *ssid = "SSID";
char *pass = "Password";

// wifi stats
int wifiStatus;
int connAttempts = 0;

// Client ID
int id = 128;

IPAddress server(192,168,1,14);
int port = 3241;

String inData;

void setup() {
  Serial.begin(115200); // for debug

  // attempting to connect to the network
  wifiStatus = WiFi.begin(ssid, pass);
  while(wifiStatus != WL_CONNECTED){
    Serial.print("Attempting to connect to the network, attempt: ");
    Serial.println(connAttempts++);
    wifiStatus = WiFi.begin(ssid, pass);
    delay(1000);
  }

  // info
  Serial.print("Connected to the network, IP address is: '");
  Serial.print(WiFi.localIP());
  Serial.print("', that took ");
  Serial.print(connAttempts);
  Serial.println(" attempt(s).");
  connAttempts = 0;

  // connection to the main server
  Serial.println("Starting connection to the server...");
  while(!client.connect(server, port)){
    Serial.print("Attempting connection to the server, attempt no. ");
    Serial.println(connAttempts++);
    delay(1000);
  }
  Serial.print("Connection successful after ");
  Serial.print(connAttempts);
  Serial.println(" attempt(s)!");
}

void loop() {
  if(client.available()){
    Serial.println("Incoming data!");
    inData = client.readString();
  }
  if(inData != ""){
    Serial.print("Incoming data: ");
    Serial.println(inData);

    if(inData == "REQ_ID"){
      String msg = "INTRODUCTION;"
      strcat(msg, m);
      client.print(msg);
    }
    inData = "";
  }
  if(!client.connected()){
    Serial.println("Lost connection to the server! Reconnecting...");
    connAttempts = 0;
    while(!client.connect(server, port)){
      Serial.print("Attempting connection to the server, attempt no. ");
      Serial.println(connAttempts++);
      delay(1000);
    }
    Serial.print("Reconnection successful after ");
    Serial.print(connAttempts);
    Serial.println(" attempt(s)!");
  }
  delay(10);
}

這是來自 Java 服務器的客戶端處理程序 class:

package org.elektrio.vsd2020;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

public class ClientHandler implements Runnable {

    public Socket netSocket;
    public BufferedInputStream in;
    public BufferedOutputStream out;

    private int clientID;

    public ClientHandler(Socket skt) throws IOException {
        this.netSocket = skt;

        this.in = new BufferedInputStream(this.netSocket.getInputStream());
        this.out = new BufferedOutputStream(this.netSocket.getOutputStream());
    }

    public void close() throws IOException{
        this.in.close();
        this.out.close();
        this.netSocket.close();
    }

    @Override
    public void run() {
        while(netSocket.isConnected()){
            try{
                byte[] arr = new byte[2048];
                in.read(arr);
                String[] input = new String(arr, StandardCharsets.US_ASCII).split(";");

                // if the message is tagged as "INTRODUCTION", it identifies a reply from the ESP32, which contains the client ID
                if(input[0].equals("INTRODUCTION")){
                    clientID = Integer.parseInt(input[1]);
                }
            }
            catch (IOException e) {
                System.out.println("[" + LocalDateTime.now() + " at ClientHandler] Exception at client ID '" + clientID + "'!");
                e.printStackTrace();
            }
        }
        System.out.println("[" + LocalDateTime.now() + " at ClientHandler] Client ID '" + clientID + "' disconnected!");
        Tools.clients.remove(this);
    }

    public int getID(){
        return clientID;
    }

    public int reqID() throws IOException{
        String req = "REQ_ID";
        out.write(req.getBytes(StandardCharsets.US_ASCII));
    }
}

服務器主class:

package org.elektrio.vsd2020;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    public static ServerSocket server;
    public static ServerSocket remoteAccessServer;

    public static ExecutorService pool;

    public static boolean serviceRunning = true;

    public static void main(String[] args) {
        try{
            // startup args
            int port = args.length > 0 ? Integer.parseInt(args[0]) : 3241;                  
            int maxClients = args.length > 1 ? Integer.parseInt(args[2]) : 10;

            // startup parameters info
            Tools.log("Main", "Server started with parameters: ");
            if(args.length > 0) Tools.log("Main", args);
            else Tools.log("Main", "Default parameters");

            // server socket and the threadpool, where the client threads get executed
            server = new ServerSocket(port);
            pool = Executors.newFixedThreadPool(maxClients);

            // main loop
            while(true){
                if(Tools.clients.size() < maxClients){

                    // connection establishment
                    Socket clientSocket = server.accept();
                    ClientHandler client = new ClientHandler(clientSocket);

                    Tools.log("Main", "New client connected from " + clientSocket.getRemoteSocketAddress());

                    // starting the client operation
                    pool.execute(client);
                    Tools.clients.add(client);
                    Thread.sleep(500);
                    client.reqID();
                }
            }
        }
        catch (IOException | InterruptedException ioe){
            Tools.log("Main", "IOException at MAIN");
            ioe.printStackTrace();
        }
    }
}

最后,工具 class

package org.elektrio.vsd2020;

import java.time.LocalDateTime;
import java.util.ArrayList;

public class Tools {

    public static ArrayList<ClientHandler> clients = new ArrayList<>();

    public static void log(String origin, String message){
        System.out.println("[" + LocalDateTime.now() + " at " + origin + "] " + message);
    }

    public static void log(String origin, String[] messages){
        for(String msg : messages) System.out.println("[" + LocalDateTime.now() + " at " + origin + "] " + msg);
    }

}

我有一些建議:

I-您的服務器實現,即 while(true){... Thread.sleep(500); ... },類似於微控制器式編程。 Java 具有更強大的套接字通信工具,例如反應式框架。 我建議使用像 Netty 這樣的框架:

Netty 4 用戶指南

Netty 簡介

學習這些可能需要一些努力,但它們的表現要好得多。

並且還存在用於物聯網系統的現代協議,例如 MQTT 甚至 RSocket。 您可以使用它們代替普通的 TCP 連接。

II:在物聯網系統中,隔離問題非常重要。 所以在你的情況下,使用像Hercules這樣的 TCP 終端工具有很大幫助。 這些工具既可以充當服務器,也可以充當客戶端; 因此您可以使用它們代替 ESP32 和 Java 服務器並測試對方是否正常工作。

三:在物聯網通信中,盡量限制消息。 因此,不要在 ESP32 和 Java 之間進行這種轉換:

ESP32:嗨

Java:你好,你是誰?

. 我的身份證是...

. 把數據傳給我...

. 這是數據...

用這個:

ESP32:嗨。 我是 ID.. 這是我的數據

服務器:好的,謝謝!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM