简体   繁体   English

如何使 java 应用程序与 ESP32 板通信?

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

I've been trying to establish a TCP socket connection between an ESP32 board and a Java server.我一直在尝试在 ESP32 板和 Java 服务器之间建立 TCP 套接字连接。 After establishing the connection, I want the server to send a packet to the ESP32 to request its ID (I use the ID to identify the clients, as there are going to be more of them), but the server doesn't seem to be transmitting anything (ESP32 isn't receiving anything).建立连接后,我希望服务器向 ESP32 发送一个数据包以请求其 ID(我使用 ID 来识别客户端,因为它们会更多),但服务器似乎没有传输任何东西(ESP32 没有接收任何东西)。 I even tried using Wireshark to track the packets, but upon connection, there is no message to be seen.我什至尝试使用 Wireshark 来跟踪数据包,但是在连接时,没有消息可以看到。 Sorry for the horrible code, I'm still a beginner, when it comes to communication programming.对不起,可怕的代码,在通信编程方面,我仍然是初学者。 Thanks in advance for your help.在此先感谢您的帮助。

Here is the code for the ESP32:这是 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);
}

And here is the client handler class from the Java server:这是来自 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));
    }
}

Server's main class:服务器主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();
        }
    }
}

And lastly, the Tools class最后,工具 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 have some recommendations:我有一些建议:

I- Your server implementation, ie while(true){... Thread.sleep(500); I-您的服务器实现,即 while(true){... Thread.sleep(500); ... }, resembles microcontroller-style programming. ... },类似于微控制器式编程。 Java has much more powerful tools for socket communication, such as reactive frameworks. Java 具有更强大的套接字通信工具,例如反应式框架。 I suggest using frameworks like Netty:我建议使用像 Netty 这样的框架:

Netty 4 User Guide Netty 4 用户指南

Introduction to Netty Netty 简介

It may require some effort to learn these but their performance is much better.学习这些可能需要一些努力,但它们的表现要好得多。

And also there exists modern protocols for IoT systems, like MQTT or even RSocket.并且还存在用于物联网系统的现代协议,例如 MQTT 甚至 RSocket。 You can use them instead of plain TCP connection.您可以使用它们代替普通的 TCP 连接。

II: In IoT systems, isolating the problem is very important. II:在物联网系统中,隔离问题非常重要。 So in your case, using TCP terminal tools like Hercules helps a lot.所以在你的情况下,使用像Hercules这样的 TCP 终端工具有很大帮助。 These tools can act as both server and client;这些工具既可以充当服务器,也可以充当客户端; so you can use them instead of ESP32 and Java Server and test if the other side works well.因此您可以使用它们代替 ESP32 和 Java 服务器并测试对方是否正常工作。

III: In IoT communications, try to limit the messages.三:在物联网通信中,尽量限制消息。 Thus Instead of this conversion between ESP32 and Java:因此,不要在 ESP32 和 Java 之间进行这种转换:

ESP32: Hi ESP32:嗨

Java: Hello, who are you? Java:你好,你是谁?

. . My ID is...我的身份证是...

. . Pass me the data...把数据传给我...

. . Here is the data...这是数据...

Use this:用这个:

ESP32: Hi. ESP32:嗨。 I am ID.. and This is my data我是 ID.. 这是我的数据

Server: OK Thanks!服务器:好的,谢谢!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM