esp32cam与android app的同步udp通信

编程入门 行业动态 更新时间:2024-10-23 07:38:10

esp32cam与android app的同步udp<a href=https://www.elefans.com/category/jswz/34/1769529.html style=通信"/>

esp32cam与android app的同步udp通信

esp32cam

#include "esp_camera.h"
#include <WiFi.h>
#include <WiFiUdp.h> //引用以使用UDP
#include <vector>const char *ssid = "dsx_zj";
const char *password = "dsxbs725";
WiFiUDP Udp;                      //创建UDP对象
unsigned int localUdpPort = 8081; //本地端口号
#define maxcache 1430
bool is_tran_camera =  false; //是否传输视频数据
String cam_on = "camon";  
String cam_off = "camoff";
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22static camera_config_t camera_config = {.pin_pwdn = PWDN_GPIO_NUM,.pin_reset = RESET_GPIO_NUM,.pin_xclk = XCLK_GPIO_NUM,.pin_sscb_sda = SIOD_GPIO_NUM,.pin_sscb_scl = SIOC_GPIO_NUM,.pin_d7 = Y9_GPIO_NUM,.pin_d6 = Y8_GPIO_NUM,.pin_d5 = Y7_GPIO_NUM,.pin_d4 = Y6_GPIO_NUM,.pin_d3 = Y5_GPIO_NUM,.pin_d2 = Y4_GPIO_NUM,.pin_d1 = Y3_GPIO_NUM,.pin_d0 = Y2_GPIO_NUM,.pin_vsync = VSYNC_GPIO_NUM,.pin_href = HREF_GPIO_NUM,.pin_pclk = PCLK_GPIO_NUM,.xclk_freq_hz = 20000000,.ledc_timer = LEDC_TIMER_0,.ledc_channel = LEDC_CHANNEL_0,.pixel_format = PIXFORMAT_JPEG,.frame_size = FRAMESIZE_VGA,.jpeg_quality = 12,.fb_count = 1,
};esp_err_t camera_init() {//initialize the cameraesp_err_t err = esp_camera_init(&camera_config);if (err != ESP_OK) {Serial.println("Camera Init Failed!");return err;}sensor_t * s = esp_camera_sensor_get();//initial sensors are flipped vertically and colors are a bit saturatedif (s->id.PID == OV2640_PID) {//        s->set_vflip(s, 1);//flip it back//        s->set_brightness(s, 1);//up the blightness just a bit//        s->set_contrast(s, 1);}Serial.println("Camera Init OK!");return ESP_OK;
}void wifi_init(void)
{delay(10);WiFi.mode(WIFI_STA);WiFi.setSleep(false); //鍏抽棴STA妯″紡涓媤ifi浼戠湢锛屾彁楂樺搷搴旈�熷害WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED){delay(500);Serial.print(".");}Serial.println();Serial.println("WiFi Connected OK!");Serial.print("IP Address:");Serial.println(WiFi.localIP());Udp.begin(localUdpPort); //启用UDP监听以接收数据
}void cssp(){camera_fb_t * fb = esp_camera_fb_get();uint8_t * temp = fb->buf; //这个是为了保存一个地址,在摄像头数据发送完毕后需要返回,否则会出现板子发送一段时间后自动重启,不断重复if (!fb){Serial.print( "Camera Capture Failed!");}else{ Udp.beginPacket(IPAddress(192,168,2,201), 8081);Udp.print("FrameBegin");   //视频数据的标志头Udp.endPacket();// 将图片数据分段发送int leng = fb->len;int timess = leng/maxcache;int extra = leng%maxcache;for(int j = 0;j< timess;j++){Udp.beginPacket(IPAddress(192,168,2,201), 8081);Udp.write(fb->buf, maxcache); Udp.endPacket(); for(int i =0;i< maxcache;i++){fb->buf++;}}Udp.beginPacket(IPAddress(192,168,2,201), 8081);Udp.write(fb->buf, extra);Udp.endPacket(); Udp.beginPacket(IPAddress(192,168,2,201), 8081);Udp.print("FrameOverr");   //视频数据的标志尾Udp.endPacket();  // Serial.print("This Frame Length:");// Serial.print(fb->len);// Serial.println(".Succes To Send Image For UDP");//return the frame buffer back to the driver for reusefb->buf = temp; //将当时保存的指针重新返还esp_camera_fb_return(fb);  //这一步在发送完毕后要执行,具体作用还未可知。}delay(20); //不加延时会导致数据发送混乱 稍微延时增加数据传输可靠性
}
void recv_data(){int packetSize = Udp.parsePacket(); //获取当前队首数据包长度if (packetSize)                     //如果有数据可用{char buf[packetSize];Udp.read(buf, packetSize); //读取当前包数据// Serial.println();// Serial.print("Received: ");// Serial.println(buf);// Serial.print("From IP: ");// Serial.println(Udp.remoteIP());// Serial.print("From Port: ");// Serial.println(Udp.remotePort());String tmp = String(buf);if(tmp.substring(0,cam_on.length()) == "camon"){is_tran_camera = true;Udp.beginPacket(IPAddress(192,168,2,201), 8081);Udp.print("Camera ON");Udp.endPacket();  }if(tmp.substring(0,cam_off.length()) == "camoff"){is_tran_camera = false;Udp.beginPacket(IPAddress(192,168,2,201), 8081);Udp.print("Camera OFF");Udp.endPacket();  }}
}
void setup() {Serial.begin(115200);camera_init(); wifi_init(); Serial.println("Sys Is Running!");
}void loop() 
{recv_data();if(is_tran_camera){cssp();}
}

app

package com.example.esp32cam_app;import androidx.appcompat.app.AppCompatActivity;import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;public class MainActivity extends AppCompatActivity {private Button send;   //发送按钮private EditText content;public static final String local_ip = "192.168.2.201"; //本机ippublic static final int local_recv_port = 8081; //本机接收udp绑定的端口public static final int local_send_port = 38383; //本机发送udp绑定的端口public static final String client_ip = "192.168.2.204";  //客户端IPpublic static final int client_port = 8081; //客户端portprivate DatagramSocket socket;  //接收数据用的socketint data_len = 1430;//与esp32cam约定的数据传输的长度int headFlag = 0;// 0 数据流不是图像数据   1 数据流是图像数据byte[] RevBuff = new byte[data_len];//定义接收数据流的包的大小byte[] temp = new byte[0];  //存放一帧图像的数据Bitmap bitmap = null; //展示图片MyHandler myHandler; //处理信息ImageView show_cam; //展示图片@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myHandler = new MyHandler();show_cam = findViewById(R.id.show_cam);content = findViewById(R.id.content);//生成接受数据使用的sockettry {InetAddress serverAdder = InetAddress.getByName(local_ip); //本手机的ip地址socket = new DatagramSocket(local_recv_port,serverAdder);//socket = new DatagramSocket(local_recv_port);  //只使用端口也可以} catch (SocketException | UnknownHostException e) {e.printStackTrace();}
//        启动接收数据的线程new Thread(new Recv()).start();
//        发送数据send = findViewById(R.id.send);send.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {new Thread((new Send())).start();  //启动发送数据线程 发送一次数据}});}//    接收数据的线程public class Recv implements Runnable {public void run() {// 接收UDP广播,有的手机不支持while (true) {byte[] recbuf = new byte[data_len];DatagramPacket recpacket = new DatagramPacket(recbuf,recbuf.length);try {socket.receive(recpacket);RevBuff = recpacket.getData();
//                                              图像数据包的头  FrameBeginboolean begin_cam_flag = RevBuff[0] == 70 && RevBuff[1] == 114 && RevBuff[2] == 97 && RevBuff[3] == 109 && RevBuff[4] == 101&& RevBuff[5] == 66 && RevBuff[6] == 101 && RevBuff[7] == 103 && RevBuff[8] == 105 && RevBuff[9] == 110;
//                            图像数据包的尾  FrameOverrboolean end_cam_flag = RevBuff[0] == 70 && RevBuff[1] == 114 && RevBuff[2] == 97 && RevBuff[3] == 109 && RevBuff[4] == 101&& RevBuff[5] == 79 && RevBuff[6] == 118 && RevBuff[7] == 101 && RevBuff[8] == 114 && RevBuff[9] == 114;if (headFlag == 0 && begin_cam_flag) {headFlag = 1;} else if (end_cam_flag) {  //判断包是不是图像的结束包 是的话 将数据传给 myHandler  3 同时将headFlag置0Message msg = myHandler.obtainMessage();msg.what = 3;myHandler.sendMessage(msg);headFlag = 0;} else if (headFlag == 1) { //如果 headFlag == 1 说明包是图像数据  将数据发给byteMerger方法 合并一帧图像temp = byteMerger(temp, RevBuff);}else{Log.v("Message:",new String(RevBuff));}} catch (IOException e) {e.printStackTrace();}}}}//  发送数据线程public class Send implements Runnable {@Overridepublic void run() {try {InetAddress serverAdder = InetAddress.getByName(client_ip);InetAddress local_serverAdder = InetAddress.getByName(local_ip); //本手机的ip地址DatagramSocket send_socket = new DatagramSocket(local_send_port,local_serverAdder);String tmp = content.getText().toString();byte[] buf = tmp.getBytes();DatagramPacket send_packet = new DatagramPacket(buf, buf.length, serverAdder, client_port);send_socket.send(send_packet);send_socket.close();Thread.sleep(100);} catch (SocketException | UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}//处理一些不能在线程里面执行的信息class MyHandler extends Handler {public void handleMessage(Message msg){super.handleMessage(msg);switch (msg.what){case 0:
//                    连接服务器成功信息break;case 1:
//                    连接服务器失败信息break;case 2:
//                    处理接收到的非图像数据break;case 3:try {//处理接受到的图像数据 并展示bitmap = BitmapFactory.decodeByteArray(temp, 0,temp.length);show_cam.setImageBitmap(bitmap);//这句就能显示图片(bitmap数据没问题的情况下) 存在图像闪烁情况 待解决temp = new byte[0];  //一帧图像显示结束  将 temp清零}catch (Exception e){Log.i("Error","Error image data!");}break;default: break;}}}//    合并一帧图像数据  a 全局变量 temp   b  接受的一个数据包 RevBuffpublic byte[] byteMerger(byte[] a,byte[] b){int i = a.length + b.length;byte[] t = new byte[i]; //定义一个长度为 全局变量temp  和 数据包RevBuff 一起大小的字节数组 tSystem.arraycopy(a,0,t,0,a.length);  //先将 temp(先传过来的数据包)放进  tSystem.arraycopy(b,0,t,a.length,b.length);//然后将后进来的这各数据包放进treturn t; //返回t给全局变量 temp}@Overrideprotected void onDestroy() {super.onDestroy();socket.close(); //关闭接收使用的socketSystem.out.println("UDP Client程序退出,关掉socket,停止广播");}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><ImageViewandroid:id="@+id/show_cam"android:layout_width="match_parent"android:layout_height="220dp"android:background="#333"android:scaleType="center"android:layout_marginBottom="4dp"/><EditTextandroid:id="@+id/content"android:layout_width="match_parent"android:layout_height="60dp" /><Buttonandroid:id="@+id/send"android:layout_width="match_parent"android:layout_height="60dp"android:text="发送" /></LinearLayout>
<uses-permission android:name="android.permission.INTERNET"/>

更多推荐

esp32cam与android app的同步udp通信

本文发布于:2023-06-25 22:02:40,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/884999.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:通信   android   esp32cam   udp   app

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!