#include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_err.h" #include "esp_log.h" #include "nvs_flash.h" #include "esp_wifi.h" #include "esp_event.h" #include "esp_netif.h" #include "lwip/sockets.h" #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include #include "esp_camera.h" #include "esp_http_server.h" #include "cJSON.h" #include "esp_log.h" #include "mqtt_client.h" #include "sdkconfig.h" #include "esp_event.h" #include "esp_netif.h" // #include "protocol_examples_common.h" #include "usart.h" #include "wifi_softap_sta.h" #include "lwip/sockets.h" #include "lwip/dns.h" #include "lwip/netdb.h" #include "esp_log.h" #include #include "esp_system.h" #include #include "public.h" // #include "protocol_examples_common.h" #define CONFIG_EXAMPLE_IPV4 static const char *TAG = "example"; //在esp_camera.h中定义了CONFIG_OV2640_SUPPORT 用于选择摄像头型号 //#define CONFIG_OV2640_SUPPORT 1 #define CAM_PIN_PWDN -1 //该引脚接地 #define CAM_PIN_RESET -1 //software reset will be performed #define CAM_PIN_SIOD 26 #define CAM_PIN_SIOC 27 #define CAM_PIN_D7 35 #define CAM_PIN_D6 34 #define CAM_PIN_D5 39 #define CAM_PIN_D4 36 #define CAM_PIN_D3 21 #define CAM_PIN_D2 19 #define CAM_PIN_D1 18 #define CAM_PIN_D0 5 #define CAM_PIN_VSYNC 25 #define CAM_PIN_HREF 23 #define CAM_PIN_PCLK 22 int udp_socket; struct sockaddr_in remote_addr;//配置UDP远端地址变量 #define JPEG_PORT 8888 //传输图像 #define DATA_PORT 9999 //传输命令数据 #define left_forward_gpio 33 //左轮前进GPIO #define left_back_gpio 14 //左轮后退GPIO #define right_forward_gpio 17 //右轮前进GPIO #define right_back_gpio 16 //右轮后退GPIO void gpio_init(){ //gpio配置结构体 gpio_config_t io_conf; //禁止中断 io_conf.intr_type = GPIO_PIN_INTR_DISABLE; //输出模式 io_conf.mode = GPIO_MODE_OUTPUT; //配置要设置的引脚 io_conf.pin_bit_mask = (((unsigned long long)1<sin_addr.s_addr = htonl(INADDR_ANY); dest_addr_ip4->sin_family = AF_INET; dest_addr_ip4->sin_port = htons(JPEG_PORT); ip_protocol = IPPROTO_IP; } else if (addr_family == AF_INET6) { bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); dest_addr.sin6_family = AF_INET6; dest_addr.sin6_port = htons(JPEG_PORT); ip_protocol = IPPROTO_IPV6; } int sock = socket(addr_family, SOCK_DGRAM, ip_protocol); if (sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); break; } ESP_LOGI(TAG, "Socket created"); #if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6) if (addr_family == AF_INET6) { // Note that by default IPV6 binds to both protocols, it is must be disabled // if both protocols used at the same time (used in CI) int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); } #endif int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err < 0) { ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); } ESP_LOGI(TAG, "Socket bound, port %d", JPEG_PORT); while (1) { struct sockaddr_in6 source_addr; // Large enough for both IPv4 or IPv6 socklen_t socklen = sizeof(source_addr); int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen); // Error occurred during receiving if (len < 0) { ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); break; } // Data received else { // Get the sender's ip address as string if (source_addr.sin6_family == PF_INET) { inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); } else if (source_addr.sin6_family == PF_INET6) { inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); } /*检测是否采集完了摄像头图像*/ fb = esp_camera_fb_get(); if (!fb) { ESP_LOGI(TAG,"Camera capture failed"); res = ESP_FAIL; } else { if (fb->format != PIXFORMAT_JPEG) { bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); if (!jpeg_converted) { ESP_LOGI(TAG,"JPEG compression failed"); esp_camera_fb_return(fb); res = ESP_FAIL; } } else { _jpg_buf_len = fb->len; _jpg_buf = fb->buf; res = ESP_OK; } } if (res == ESP_OK) { if(len==4) { if (rx_buffer[0]==0x55 && rx_buffer[1]==0xAA && rx_buffer[2]==0x01 &&rx_buffer[3]==0x02) { int err = sendto(sock, _jpg_buf, _jpg_buf_len, 0, (struct sockaddr *)&source_addr, sizeof(source_addr)); if (err < 0) { ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); break; } } } } if (fb->format != PIXFORMAT_JPEG) { free(_jpg_buf); } esp_camera_fb_return(fb);//重新开始采集 } } if (sock != -1) { ESP_LOGE(TAG, "Shutting down socket and restarting..."); shutdown(sock, 0); close(sock); } } vTaskDelete(NULL); } static void udp_server_data_task(void *pvParameters) { char rx_buffer[128]; char addr_str[128]; int addr_family = (int)pvParameters; int ip_protocol = 0; struct sockaddr_in6 dest_addr; while (1) { if (addr_family == AF_INET) { struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr; dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY); dest_addr_ip4->sin_family = AF_INET; dest_addr_ip4->sin_port = htons(DATA_PORT); ip_protocol = IPPROTO_IP; } else if (addr_family == AF_INET6) { bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); dest_addr.sin6_family = AF_INET6; dest_addr.sin6_port = htons(DATA_PORT); ip_protocol = IPPROTO_IPV6; } int sock = socket(addr_family, SOCK_DGRAM, ip_protocol); if (sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); break; } ESP_LOGI(TAG, "Socket created"); #if defined(CONFIG_EXAMPLE_IPV4) && defined(CONFIG_EXAMPLE_IPV6) if (addr_family == AF_INET6) { // Note that by default IPV6 binds to both protocols, it is must be disabled // if both protocols used at the same time (used in CI) int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); } #endif int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err < 0) { ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); } ESP_LOGI(TAG, "Socket bound, port %d", DATA_PORT); while (1) { struct sockaddr_in6 source_addr; // Large enough for both IPv4 or IPv6 socklen_t socklen = sizeof(source_addr); int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen); // Error occurred during receiving if (len < 0) { ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); break; } // Data received else { // Get the sender's ip address as string if (source_addr.sin6_family == PF_INET) { inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); } else if (source_addr.sin6_family == PF_INET6) { inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); } if(len==3) { if (rx_buffer[0]==0x55 && rx_buffer[1]==0xAA) { if (rx_buffer[2]==0x00) { car_stop(); } else if(rx_buffer[2]==0x01) { ESP_LOGI(TAG, "↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"); car_forward(); } else if(rx_buffer[2]==0x02) { ESP_LOGI(TAG, "↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓"); car_back(); } else if(rx_buffer[2]==0x03) { ESP_LOGI(TAG, "←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←"); car_left(); } else if(rx_buffer[2]==0x04) { ESP_LOGI(TAG, "→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→"); car_right(); } } } } } if (sock != -1) { ESP_LOGE(TAG, "Shutting down socket and restarting..."); shutdown(sock, 0); close(sock); } } vTaskDelete(NULL); } uint8_t mqtt_sendCnt=0; //是否连接服务器 bool isConnectMqttServer = false; //mqtt static esp_mqtt_client_handle_t client; char deviceUUID[17]; char MqttTopicSub[50], MqttTopicPub[50]; #define ali_MQTT_TopicPub "/a1E4l5c9AoW/lh_light/user/update" #define ali_MQTT_TopicSub "/a1E4l5c9AoW/lh_light/user/get" #define APP_TAG "APP_MAIN" /* * @Description: MQTT服务器的下发消息回调 * @param: * @return: */ esp_err_t MqttCloudsCallBack(esp_mqtt_event_handle_t event) { int msg_id; client = event->client; switch (event->event_id) { //连接成功 case MQTT_EVENT_CONNECTED: ESP_LOGI(APP_TAG, "MQTT_EVENT_CONNECTED"); msg_id = esp_mqtt_client_subscribe(client, ali_MQTT_TopicSub, 1); ESP_LOGI(APP_TAG, "sent subscribe[%s] successful, msg_id=%d", ali_MQTT_TopicSub, msg_id); ESP_LOGI(APP_TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); //post_data_to_clouds(); isConnectMqttServer = true; break; //断开连接回调 case MQTT_EVENT_DISCONNECTED: ESP_LOGI(APP_TAG, "MQTT_EVENT_DISCONNECTED"); isConnectMqttServer = false; break; //订阅成功 case MQTT_EVENT_SUBSCRIBED: ESP_LOGI(APP_TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); break; //订阅失败 case MQTT_EVENT_UNSUBSCRIBED: ESP_LOGI(APP_TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); break; //推送发布消息成功 case MQTT_EVENT_PUBLISHED: ESP_LOGI(APP_TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); break; //服务器下发消息到本地成功接收回调 case MQTT_EVENT_DATA: { printf("TOPIC=%.*s \r\n", event->topic_len, event->topic); printf("DATA=%.*s \r\n\r\n", event->data_len, event->data); break; } default: break; } return ESP_OK; } //ProductSecret:YAJUJnp2mSt3Ja6P //ProductKey:a1E4l5c9AoW //DeviceName:lh_light #define ProductKey "a1E4l5c9AoW" #define DeviceName "lh_light" #define ProductSecret "092ea6988775cb980f5cb2f45c19dd22" // { // "ProductKey": "a1E4l5c9AoW", // "DeviceName": "lh_light", // "DeviceSecret": "092ea6988775cb980f5cb2f45c19dd22" // } esp_err_t ret; uint16_t step=0; uint16_t getListCnt=0; // uint8_t pcWriteBuffer[1024]={0}; char RegisterOpte[128]={0}; char MqttClientID[512]={0}; char MqttName[128]={0}; char MainBuff[512]={0}; char MqttPass[128]={0}; uint32_t Random; uint32_t len=0; uint8_t wifi_net=0; void app_main() { //初始化 NVS(配置WiFi的参数存储需要用到NVS) esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK(err); //初始化内部的lwip ESP_ERROR_CHECK(esp_netif_init()); //创建系统事件任务 ESP_ERROR_CHECK(esp_event_loop_create_default()); camera_config_t camera_config = { .ledc_timer = LEDC_TIMER_0, .ledc_channel = LEDC_CHANNEL_0, .pin_d7 = CAM_PIN_D7, .pin_d6 = CAM_PIN_D6, .pin_d5 = CAM_PIN_D5, .pin_d4 = CAM_PIN_D4, .pin_d3 = CAM_PIN_D3, .pin_d2 = CAM_PIN_D2, .pin_d1 = CAM_PIN_D1, .pin_d0 = CAM_PIN_D0, .pin_pclk = CAM_PIN_PCLK, .pin_vsync = CAM_PIN_VSYNC, .pin_href = CAM_PIN_HREF, .pin_sscb_sda = CAM_PIN_SIOD, .pin_sscb_scl = CAM_PIN_SIOC, //.pin_pwdn = CAM_PIN_PWDN,//硬件上没有该引脚 //.pin_reset = CAM_PIN_RESET, //硬件上没有该引脚 //.pin_xclk = CAM_PIN_XCLK,//硬件上没有该引脚 //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) .xclk_freq_hz = 20000000, .pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG .frame_size = FRAMESIZE_QVGA, .jpeg_quality = 15, //0-63 lower number means higher quality .fb_count = 2 //if more than one, i2s runs in continuous mode. Use only with JPEG }; //摄像头初始化 //gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1); //设置中断优先级最低 // err = esp_camera_init(&camera_config); // if (err != ESP_OK) // { // printf("Camera init failed with error 0x%x\r\n", err); // return; // } setvbuf(stdout, NULL, _IONBF, 0); gpio_init(); wifi_init_softap();//初始化模组连接的路由器 //获取mac地址(station模式) uint8_t mac[6]; esp_read_mac(mac, ESP_MAC_WIFI_STA); sprintf(deviceUUID, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); //组建MQTT订阅的主题 sprintf(MqttTopicSub, "/esp32-c3/%s/devSub", deviceUUID); //组建MQTT推送的主题 sprintf(MqttTopicPub, "/esp32-c3/%s/devPub", deviceUUID); ESP_LOGI(APP_TAG, "deviceUUID: %s", deviceUUID); ESP_LOGI(APP_TAG, "MqttTopicSub: %s", MqttTopicSub); ESP_LOGI(APP_TAG, "MqttTopicPub: %s", MqttTopicPub); // ESP_ERROR_CHECK(esp_netif_init()); // ESP_ERROR_CHECK(esp_event_loop_create_default()); // /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. // * Read "Establishing Wi-Fi or Ethernet Connection" section in // * examples/protocols/README.md for more information about this function. // */ // ESP_ERROR_CHECK(example_connect()); //连接的配置参数 // esp_mqtt_client_config_t mqtt_cfg = { // .host = "www.xiaohaodianzi.cn", //连接的域名 ,请务必修改为您的 // .port = 1883, //端口,请务必修改为您的 // .username = "xhdz", //用户名,请务必修改为您的 // .password = "1520747634", //密码,请务必修改为您的 // .client_id = deviceUUID, // .event_handle = MqttCloudsCallBack, //设置回调函数 // .keepalive = 120, //心跳 // .disable_auto_reconnect = true, //开启自动重连 // .disable_clean_session = false, //开启 清除会话 // }; printf("free_heap_size = %d\n", esp_get_free_heap_size()); // Random=esp_timer_get_time()%1024; // sprintf(RegisterOpte,"|securemode=2,authType=regnwl,random=%d,signmethod=hmacsha1|",Random); // printf("\r\nRegisterOpte:%s\r\n",RegisterOpte); // memset(MqttClientID,0,sizeof(MqttClientID)); // sprintf(MqttClientID,"%s.%s%s",(char*)ProductKey,(char*)DeviceName,RegisterOpte); // printf("\r\nMqttClientID:%s\r\n",MqttClientID); // sprintf(MqttName,"%s&%s",(char*)DeviceName,(char*)ProductKey); // sprintf(MainBuff,"deviceName%sproductKey%srandom%d",DeviceName,ProductKey,Random); // printf("\r\nMainBuff:%s\r\n",MainBuff); // utils_hmac_sha1(MainBuff,strlen(MainBuff),MqttPass,ProductSecret,strlen(ProductSecret)); // printf("\r\nMqttPass:%s\r\n",MqttPass); // esp_mqtt_client_config_t mqtt_cfg = { // .host = "a1E4l5c9AoW.iot-as-mqtt.cn-shanghai.aliyuncs.com", //连接的域名 ,请务必修改为您的 // //.uri = "a1E4l5c9AoW.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883", // .port = 1883, //端口,请务必 // .username = MqttName, //用户名,请务必 // .password = MqttPass, //密码,请务必 // .client_id = MqttClientID, // .event_handle = MqttCloudsCallBack, //设置回调函数 // .keepalive = 120, //心跳 // .disable_auto_reconnect = false, //开启自动重连 // .disable_clean_session = false, //开启 清除会话 // }; esp_mqtt_client_config_t mqtt_cfg = { .host = "a1E4l5c9AoW.iot-as-mqtt.cn-shanghai.aliyuncs.com", //连接的域名 ,请务必修改为您的 //.uri = "a1E4l5c9AoW.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883", .port = 1883, //端口,请务必修改为您的 .username = "lh_light&a1E4l5c9AoW", //用户名,请务必修改为您的 .password = "810639EB23072D05F9213FD636BD2FF311202F42", //密码,请务必修改为您的 .client_id = "esp32_test|securemode=3,signmethod=hmacsha1,timestamp=120|", .event_handle = MqttCloudsCallBack, //设置回调函数 .keepalive = 120, //心跳 .disable_auto_reconnect = false, //开启自动重连 .disable_clean_session = false, //开启 清除会话 }; #ifdef CONFIG_EXAMPLE_IPV4 xTaskCreate(udp_server_jpeg_task, "udp_server_jpeg_task", 4096, (void*)AF_INET, 5, NULL); #endif #ifdef CONFIG_EXAMPLE_IPV6 xTaskCreate(udp_server_jpeg_task, "udp_server_jpeg_task", 4096, (void*)AF_INET6, 5, NULL); #endif #ifdef CONFIG_EXAMPLE_IPV4 xTaskCreate(udp_server_data_task, "udp_server_data_task", 4096, (void*)AF_INET, 6, NULL); #endif #ifdef CONFIG_EXAMPLE_IPV6 xTaskCreate(udp_server_data_task, "udp_server_data_task", 4096, (void*)AF_INET6, 6, NULL); #endif while (1) { // printf("hello camera!\r\n"); vTaskDelay(100); if(wifi_net) { wifi_net=0; client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_start(client); } // ag_timer_sched(); // vTaskDelay(1000 / portTICK_PERIOD_MS); // /* Blink off (output low) */ if(++step>10) { step=0; if(isConnectMqttServer) { esp_mqtt_client_publish(client,ali_MQTT_TopicPub,"hello_world\r\n",strlen("hello_world\r\n"),0,00); ESP_LOGI(APP_TAG,"MQTT_PUB:hello_world\r\n"); } } } }