The mobile app acts as the master, while the ESP32CAM serves as the slave. The mobile app receives image data uploaded by the ESP32CAM and sends control commands to the ESP32CAM.
01
—
ESP32CAM Program Design
The development environment for the ESP32CAM program is Arduino, and the steps to be completed are as follows.
1. Open the Arduino example program, File – Examples – ESP32-Camera – CameraWebServer.

#define CAMERA_MODEL_AI_THINKER// Has PSRAM
4. UDP communication, especially asynchronous communication, is divided into client (client) and server (server).
(1) The client connects to the server and needs to know the server’s IP address and port number.
(2) The server connects to the client and can listen to its own port for data without needing to know the client’s IP address and port number in advance.
Therefore, during wireless communication between the ESP32CAM and the mobile app, the ESP32CAM acts as the server, while the mobile app acts as the client. The ESP32CAM opens the UDP service, enters the listening state, and checks for data.
5. When using <WiFiUdp.h>, the example is as follows:
Common methods (functions) description:
(1) uint8_t begin(uint16_t p)
(2) uint8_t begin(IPAddress a, uint16_t p)
Start listening on a certain port or for data sent to a certain port from a certain address;
(3) void stop()
Stop listening, release resources;
(4) int beginPacket()
Prepare to send a data packet (only available when running the parsePacket() method and the return value is greater than 0);
(5) int beginPacket(IPAddress ip, uint16_t port)
Prepare to send a data packet, with parameters being the target IP and target port number;
(6) size_t write(uint8_t)
(7) size_t write(const uint8_t *buffer, size_t size)
Copy data to the send buffer (the maximum size for a single data packet is 1460 bytes);
(8) int endPacket()
Send data;
(9) int parsePacket()
Get information on received data; if there is a data packet available, return the length of the first packet, otherwise return 0;
(10) int read()
Read the first byte of data (only available when running the parsePacket() method and the return value is greater than 0);
(11) int read(unsigned char* buffer, size_t len)
(12) int read(char* buffer, size_t len)
Read data (only available when running the parsePacket() method and the return value is greater than 0);
(13) int peek()
Read the first byte of data but does not remove it from the receive buffer (only available when running the parsePacket() method and the return value is greater than 0);
(14) void flush()
Clear the current receive buffer (only available when running the parsePacket() method and the return value is greater than 0);
(15) IPAddress remoteIP()
Return the remote address (only available when running the parsePacket() method and the return value is greater than 0);
(16) uint16_t remotePort()
Return the remote port number (only available when running the parsePacket() method and the return value is greater than 0);
AsyncUDP class:
void onPacket(AuPacketHandlerFunctionWithArg cb, void * arg=NULL)
void onPacket(AuPacketHandlerFunction cb)
Register an event and bind a callback function;
bool listen(const IPAddress addr, uint16_t port)
bool listen(uint16_t port)
bool listen(const IPv6Address addr, uint16_t port)
bool listen(uint16_t port)
Start listening;
bool listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
bool listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
bool listenMulticast(const IPv6Address addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
Start multicast listening;
bool connect(const ip_addr_t *addr, uint16_t port)
bool connect(const IPAddress addr, uint16_t port)
bool connect(const IPv6Address addr, uint16_t port)
Connect as a client to the server (after successful connection, you can directly use write or send methods without using writeTo or sendTo);
void close()
Close UDP;
size_t writeTo(const uint8_t *data, size_t len, const ip_addr_t *addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t writeTo(const uint8_t *data, size_t len, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t write(const uint8_t *data, size_t len)
size_t write(uint8_t data)
Send data;
size_t broadcastTo(uint8_t *data, size_t len, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t broadcastTo(const char * data, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t broadcast(uint8_t *data, size_t len)
size_t broadcast(const char * data)
Broadcast data;
size_t sendTo(AsyncUDPMessage &message, const ip_addr_t *addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t sendTo(AsyncUDPMessage &message, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t send(AsyncUDPMessage &message)
Send data;
size_t broadcastTo(AsyncUDPMessage &message, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX)
size_t broadcast(AsyncUDPMessage &message)
Broadcast data;
AsyncUDPPacket class:
AsyncUDPPacket(AsyncUDP *udp, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif)
Constructor;
uint8_t * data()
Return data pointer;
size_t length()
Return data length;
bool isBroadcast()
Check if it is broadcast data;
bool isMulticast()
Check if it is a multicast address;
IPAddress localIP()
Return the target (local) IP;
uint16_t localPort()
Return the target (local) port number;
IPAddress remoteIP()
Return the remote IP;
uint16_t remotePort()
Return the remote port number;
size_t read(uint8_t *data, size_t len)
Read data;
int read()
Read the first byte of data;
int peek()
Read the first byte of data but does not remove it from the receive buffer;
void flush()
Clear the current receive buffer;
size_t write(const uint8_t *data, size_t len)
size_t write(uint8_t data)
Send data to the remote;
AsyncUDPMessage class:
AsyncUDPMessage(size_t size=CONFIG_TCP_MSS)
Constructor (this acts as a buffer, putting the data to be sent here, and then sending it through the corresponding method);
size_t write(const uint8_t *data, size_t len)
size_t write(uint8_t data)
Write data into the AsyncUDPMessage object;
size_t space()
Return the remaining available space in the AsyncUDPMessage object;
uint8_t * data()
Return the data pointer in the AsyncUDPMessage object;
size_t length()
Return the current used length of the AsyncUDPMessage object;
void flush()
Clear the current data in the AsyncUDPMessage object;
02
—
Mobile App Program Design
The development environment for the mobile app program is MIT App Inventor, and the steps to be completed are as follows.
1. Create a new project, and add extensions UDPXmitter1 and UDPListener1.
The new page is shown in the figure below, which includes a Web browser frame, buttons, and extension UDP communication instructions.

2. The program design (part) is shown in the figure below.

3. Package the APK, and install the mobile app to connect.
4. Debug.