Add Wechat APP example
- Split process to core 1 - Use BluFi - Use MDNS - Manage Face id with namepull/55/head
parent
123ce3b040
commit
e26281edbc
|
@ -1 +1 @@
|
|||
Subproject commit 07e9bab3fae52c927991bf884a62534555b48260
|
||||
Subproject commit b45ecf2e3df66e7536b6ae470cfa65e099c2ee22
|
|
@ -1 +1 @@
|
|||
Subproject commit 165a47fe6a7c76daf23fa40512ae4a90a994e938
|
||||
Subproject commit 113629b1cf8769f65c09db0c3577a597e652860b
|
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := recognition_wechat
|
||||
|
||||
SOLUTION_PATH ?= $(abspath $(shell pwd))/../../..
|
||||
|
||||
include $(SOLUTION_PATH)/components/component_conf.mk
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _WECHAT_BLUFI_H_
|
||||
#define _WECHAT_BLUFI_H_
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <lwip/netdb.h>
|
||||
|
||||
/* nvs typedef */
|
||||
#define USERDATANAMESPACE "userdata"
|
||||
#define NVS_KEY_WIFI_SSID_PASS "ssid_pass"
|
||||
#define NVS_KEY_RESTART_COUNT "restart_cou"
|
||||
#define WIFI_SSID_PASS_SIZE (32+64)
|
||||
|
||||
#define BLUFI_EXAMPLE_TAG "ESP32_BLUFI"
|
||||
#define BLUFI_DEVICE_NAME "BLUFI_DEVICE_ESP_WHO1"
|
||||
|
||||
#define DEFAULT_SSID "ESP_Who_Wechat"
|
||||
#define DEFAULT_PWD "12345678"
|
||||
#define MAX_STA_CONN 2
|
||||
|
||||
#define NOTICE_MDNS_HOSTNAME "notice-mDNS"
|
||||
#define NOTICE_MDNS_INSTANCE "notice with ESP-WHO"
|
||||
#define NOTICE_MDNS_SERVICE_TYPE "_notice_service"
|
||||
#define NOTICE_MDNS_PROTO "_tcp"
|
||||
|
||||
#define TCP_DEFAULT_PORT 8899
|
||||
#define UDP_NOTICE_PORT 7899
|
||||
#define DEFAULT_PKTSIZE 135
|
||||
|
||||
#define WIFI_IP4_CONNECTED_BIT BIT0
|
||||
#define WIFI_IP6_CONNECTED_BIT BIT1
|
||||
#define ESPTOUCH_DONE_BIT BIT2
|
||||
|
||||
#define WIFI_LIST_NUM 10
|
||||
#define RESTART_TIMEOUT_MS (5000)
|
||||
#define WIFI_CONFIG_TIMEOUT (3 * 60 * 1000)
|
||||
|
||||
#define NOTICE_UDP_BUF_SIZE (64)
|
||||
#define NOTICE_UDP_RETRY_COUNT (3)
|
||||
|
||||
#define BLUFI_INFO(fmt, ...) ESP_LOGI(BLUFI_EXAMPLE_TAG, fmt, ##__VA_ARGS__)
|
||||
#define BLUFI_ERROR(fmt, ...) ESP_LOGE(BLUFI_EXAMPLE_TAG, fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief wifi_info_erase
|
||||
*/
|
||||
esp_err_t wifi_info_erase(const char *key);
|
||||
|
||||
/**
|
||||
* @brief load_info_nvs
|
||||
*/
|
||||
esp_err_t load_info_nvs(char *key, void *value, size_t len);
|
||||
|
||||
/**
|
||||
* @brief save_info_nvs
|
||||
*/
|
||||
esp_err_t save_info_nvs(char *key, void *value, size_t len);
|
||||
|
||||
/**
|
||||
* @brief 蓝牙、wifi 初始化、mdns 初始化、udp 发现初始化
|
||||
*/
|
||||
void blufi_main();
|
||||
|
||||
/**
|
||||
* @brief wifi initialise for Software AP + Sta
|
||||
*/
|
||||
void wifi_init_ap_sta();
|
||||
|
||||
/**
|
||||
* @brief 等待网络连接成功,获取到 IP 地址
|
||||
*/
|
||||
void wait_net_connected();
|
||||
|
||||
/**
|
||||
* @brief 进入 蓝牙配网模式
|
||||
*/
|
||||
void enter_blufi_config_wifi();
|
||||
|
||||
void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free);
|
||||
|
||||
int blufi_aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len);
|
||||
|
||||
int blufi_aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len);
|
||||
|
||||
uint16_t blufi_crc_checksum(uint8_t iv8, uint8_t *data, int len);
|
||||
|
||||
int blufi_security_init(void);
|
||||
|
||||
void blufi_security_deinit(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,957 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/* C Includes */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* FreeRTOS Includes */
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
/* ESP32 Includes */
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_bt.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "mdns.h"
|
||||
|
||||
/* Bluetooth Includes */
|
||||
#include "esp_blufi_api.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_bt_device.h"
|
||||
|
||||
/* wechat Includes */
|
||||
#include "wechat_blufi.h"
|
||||
|
||||
static uint8_t ble_service_uuid128[32] = {
|
||||
/* LSB <--------------------------------------------------------------------------------> MSB */
|
||||
//first uuid, 16bit, [12],[13] is the value
|
||||
0xfb,
|
||||
0x34,
|
||||
0x9b,
|
||||
0x5f,
|
||||
0x80,
|
||||
0x00,
|
||||
0x00,
|
||||
0x80,
|
||||
0x00,
|
||||
0x10,
|
||||
0x00,
|
||||
0x00,
|
||||
0xFF,
|
||||
0xFF,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
|
||||
//static uint8_t test_manufacturer[TEST_MANUFACTURER_DATA_LEN] = {0x12, 0x23, 0x45, 0x56};
|
||||
static esp_ble_adv_data_t ble_adv_data = {
|
||||
.set_scan_rsp = false,
|
||||
.include_name = true,
|
||||
.include_txpower = true,
|
||||
.min_interval = 0x100,
|
||||
.max_interval = 0x100,
|
||||
.appearance = 0x00,
|
||||
.manufacturer_len = 0,
|
||||
.p_manufacturer_data = NULL,
|
||||
.service_data_len = 0,
|
||||
.p_service_data = NULL,
|
||||
.service_uuid_len = 16,
|
||||
.p_service_uuid = ble_service_uuid128,
|
||||
.flag = 0x6,
|
||||
};
|
||||
|
||||
static esp_ble_adv_params_t ble_adv_params = {
|
||||
.adv_int_min = 0x100,
|
||||
.adv_int_max = 0x100,
|
||||
.adv_type = ADV_TYPE_IND,
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
//.peer_addr =
|
||||
//.peer_addr_type =
|
||||
.channel_map = ADV_CHNL_ALL,
|
||||
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
||||
};
|
||||
|
||||
wifi_config_t sta_config = {0};
|
||||
wifi_config_t ap_config = {0};
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected & ready to make a request */
|
||||
static EventGroupHandle_t wifi_event_group;
|
||||
|
||||
/* The event group allows multiple bits for each event,
|
||||
but we only care about one event - are we connected
|
||||
to the AP with an IP? */
|
||||
const int CONNECTED_BIT = BIT0;
|
||||
|
||||
/* store the station info for send back to phone */
|
||||
static bool gl_sta_connected = false;
|
||||
static uint8_t gl_sta_bssid[6];
|
||||
static uint8_t gl_sta_ssid[32];
|
||||
static int gl_sta_ssid_len;
|
||||
|
||||
/* connect infor*/
|
||||
static uint8_t server_if;
|
||||
static uint16_t conn_id;
|
||||
|
||||
static void blufi_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param);
|
||||
|
||||
void enter_blufi_config_wifi();
|
||||
|
||||
void wifi_connect_succuess();
|
||||
|
||||
/**
|
||||
* @brief wifi_info_erase
|
||||
*/
|
||||
esp_err_t wifi_info_erase(const char *key)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
nvs_handle handle = 0;
|
||||
|
||||
ret = nvs_open(USERDATANAMESPACE, NVS_READWRITE, &handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("nvs", "unable to open NVS namespace, errcode is %d\n", ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief If key is USERDATANAMESPACE, erase all info in USERDATANAMESPACE
|
||||
*/
|
||||
if (!strcmp(key, USERDATANAMESPACE)) {
|
||||
ret = nvs_erase_all(handle);
|
||||
} else {
|
||||
ret = nvs_erase_key(handle, key);
|
||||
}
|
||||
|
||||
nvs_commit(handle);
|
||||
if (handle > 0) {
|
||||
nvs_close(handle);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief load_info_nvs
|
||||
*/
|
||||
esp_err_t load_info_nvs(char *key, void *value, size_t len)
|
||||
{
|
||||
esp_err_t err;
|
||||
nvs_handle handle = 0;
|
||||
size_t length = len;
|
||||
|
||||
err = nvs_open(USERDATANAMESPACE, NVS_READWRITE, &handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("nvs", "unable to open NVS namespace, errcode is %d\n", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (value == NULL) {
|
||||
ESP_LOGE("nvs", "value NVS_ERR_PARAMETER_NULL\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = nvs_get_blob(handle, key, value, &length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("load_info_nvs", "load_info_nvs\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (handle > 0) {
|
||||
nvs_close(handle);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief save_info_nvs
|
||||
*/
|
||||
esp_err_t save_info_nvs(char *key, void *value, size_t len)
|
||||
{
|
||||
esp_err_t err;
|
||||
nvs_handle handle = 0;
|
||||
size_t length = len;
|
||||
|
||||
err = nvs_open(USERDATANAMESPACE, NVS_READWRITE, &handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE("nvs", "unable to open NVS namespace, errcode is %d\n", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (value == NULL) {
|
||||
ESP_LOGE("nvs", "value NVS_ERR_PARAMETER_NULL\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = nvs_set_blob(handle, key, value, length);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI("save_info_nvs", "save_info_nvs\n");
|
||||
}
|
||||
|
||||
nvs_commit(handle);
|
||||
if (handle > 0) {
|
||||
nvs_close(handle);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 等待网络连接成功,获取到 IP 地址
|
||||
*/
|
||||
void wait_net_connected()
|
||||
{
|
||||
xEventGroupWaitBits(wifi_event_group, WIFI_IP4_CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
// xEventGroupWaitBits(wifi_event_group, WIFI_IP4_CONNECTED_BIT | WIFI_IP6_CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief wifi 事件处理函数
|
||||
*/
|
||||
static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
wifi_mode_t mode;
|
||||
static uint8_t connect_try_count = 0;
|
||||
|
||||
switch (event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_STA_START\n");
|
||||
if (strlen((char *)sta_config.sta.ssid) != 0 && strlen((char *)sta_config.sta.password) != 0) {
|
||||
ESP_ERROR_CHECK(esp_wifi_connect());
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_STA_STOP:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_STA_STOP\n");
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_STA_CONNECTED\n");
|
||||
gl_sta_connected = true;
|
||||
connect_try_count = 0;
|
||||
memcpy(gl_sta_bssid, event->event_info.connected.bssid, 6);
|
||||
memcpy(gl_sta_ssid, event->event_info.connected.ssid, event->event_info.connected.ssid_len);
|
||||
gl_sta_ssid_len = event->event_info.connected.ssid_len;
|
||||
|
||||
save_info_nvs(NVS_KEY_WIFI_SSID_PASS, (void *)(sta_config.sta.ssid), WIFI_SSID_PASS_SIZE);
|
||||
/* enable ipv6 */
|
||||
tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA);
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_STA_DISCONNECTED\n");
|
||||
/* This is a workaround as ESP32 WiFi libs don't currently auto-reassociate. */
|
||||
if (connect_try_count++ > 5 && connect_try_count < 10) {
|
||||
// connect_try_count = 0;
|
||||
esp_wifi_get_mode(&mode);
|
||||
if (esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, 0, NULL) != ESP_OK) {
|
||||
ESP_LOGI("blufi","esp_fail\n");
|
||||
}
|
||||
} else {
|
||||
gl_sta_connected = false;
|
||||
memset(gl_sta_ssid, 0, 32);
|
||||
memset(gl_sta_bssid, 0, 6);
|
||||
gl_sta_ssid_len = 0;
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(wifi_event_group, WIFI_IP4_CONNECTED_BIT | WIFI_IP6_CONNECTED_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_STA_GOT_IP: {
|
||||
esp_blufi_extra_info_t info;
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_STA_GOT_IP\n");
|
||||
ESP_LOGI("event_handler", "got ip4:%s\n", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
|
||||
xEventGroupSetBits(wifi_event_group, WIFI_IP4_CONNECTED_BIT);
|
||||
esp_wifi_get_mode(&mode);
|
||||
|
||||
memset(&info, 0, sizeof(esp_blufi_extra_info_t));
|
||||
memcpy(info.sta_bssid, gl_sta_bssid, 6);
|
||||
info.sta_bssid_set = true;
|
||||
info.sta_ssid = gl_sta_ssid;
|
||||
info.sta_ssid_len = gl_sta_ssid_len;
|
||||
esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, 0, &info);
|
||||
|
||||
wifi_connect_succuess();
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSTEM_EVENT_AP_STA_GOT_IP6:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_AP_STA_GOT_IP6\n");
|
||||
ESP_LOGI("event_handler", "got ip6:%s\n", ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip));
|
||||
xEventGroupSetBits(wifi_event_group, WIFI_IP6_CONNECTED_BIT);
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_AP_START:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_AP_START\n");
|
||||
esp_wifi_get_mode(&mode);
|
||||
|
||||
/* TODO: get config or information of softap, then set to report extra_info */
|
||||
if (gl_sta_connected) {
|
||||
esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, 0, NULL);
|
||||
} else {
|
||||
esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, 0, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_AP_STOP:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_AP_STOP\n");
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_AP_STAIPASSIGNED:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_AP_STAIPASSIGNED\n");
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_AP_STACONNECTED:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_AP_STACONNECTED\n");
|
||||
ESP_LOGI("event_handler", "station:" MACSTR " join,AID=%d\n",
|
||||
MAC2STR(event->event_info.sta_connected.mac),
|
||||
event->event_info.sta_connected.aid);
|
||||
xEventGroupSetBits(wifi_event_group, WIFI_IP4_CONNECTED_BIT);
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_AP_STADISCONNECTED:
|
||||
ESP_LOGI("event_handler", "SYSTEM_EVENT_AP_STADISCONNECTED\n");
|
||||
ESP_LOGI("event_handler", "station:" MACSTR "leave,AID=%d\n",
|
||||
MAC2STR(event->event_info.sta_disconnected.mac),
|
||||
event->event_info.sta_disconnected.aid);
|
||||
xEventGroupClearBits(wifi_event_group, WIFI_IP4_CONNECTED_BIT);
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_SCAN_DONE: {
|
||||
uint16_t apCount = 0;
|
||||
esp_wifi_scan_get_ap_num(&apCount);
|
||||
if (apCount == 0) {
|
||||
BLUFI_INFO("Nothing AP found");
|
||||
break;
|
||||
}
|
||||
wifi_ap_record_t *ap_list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
|
||||
if (!ap_list) {
|
||||
BLUFI_ERROR("malloc error, ap_list is NULL");
|
||||
break;
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, ap_list));
|
||||
esp_blufi_ap_record_t *blufi_ap_list = (esp_blufi_ap_record_t *)malloc(apCount * sizeof(esp_blufi_ap_record_t));
|
||||
if (!blufi_ap_list) {
|
||||
if (ap_list) {
|
||||
free(ap_list);
|
||||
}
|
||||
BLUFI_ERROR("malloc error, blufi_ap_list is NULL");
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < apCount; ++i) {
|
||||
blufi_ap_list[i].rssi = ap_list[i].rssi;
|
||||
memcpy(blufi_ap_list[i].ssid, ap_list[i].ssid, sizeof(ap_list[i].ssid));
|
||||
}
|
||||
esp_blufi_send_wifi_list(apCount, blufi_ap_list);
|
||||
esp_wifi_scan_stop();
|
||||
free(ap_list);
|
||||
free(blufi_ap_list);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef USE_MDNS
|
||||
mdns_handle_system_event(ctx, event);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// wifi initialise for Software AP + Sta
|
||||
void wifi_init_ap_sta()
|
||||
{
|
||||
tcpip_adapter_init();
|
||||
wifi_event_group = xEventGroupCreate();
|
||||
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
|
||||
wifi_config_t ap_wifi_config = {
|
||||
.ap = {
|
||||
.ssid = DEFAULT_SSID,
|
||||
.ssid_len = 0,
|
||||
.max_connection = MAX_STA_CONN,
|
||||
.password = DEFAULT_PWD,
|
||||
.authmode = WIFI_AUTH_WPA_WPA2_PSK
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
// memcpy(sta_config.sta.ssid, sta_wifi_config.sta.ssid, WIFI_SSID_MAX_SIZE);
|
||||
// memcpy(sta_config.sta.password, sta_wifi_config.sta.password, WIFI_SSID_PASS_SIZE);
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &ap_wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &sta_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
if (strlen((char *)sta_config.sta.ssid) == 0 && strlen((char *)sta_config.sta.password) == 0) {
|
||||
enter_blufi_config_wifi();
|
||||
}
|
||||
|
||||
ESP_LOGI("wifi_init_ap_sta", "AP SSID:%s, password:%s; Station SSID:%s, pass:%s\n",
|
||||
DEFAULT_SSID, DEFAULT_PWD, sta_config.sta.ssid, sta_config.sta.password);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief blufi 回调函数结构体
|
||||
*/
|
||||
static esp_blufi_callbacks_t blufi_callbacks = {
|
||||
.event_cb = blufi_event_callback,
|
||||
.negotiate_data_handler = blufi_dh_negotiate_data_handler,
|
||||
.encrypt_func = blufi_aes_encrypt,
|
||||
.decrypt_func = blufi_aes_decrypt,
|
||||
.checksum_func = blufi_crc_checksum,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 蓝牙 blufi 时间处理函数
|
||||
*/
|
||||
static void blufi_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param)
|
||||
{
|
||||
/* actually, should post to blufi_task handle the procedure,
|
||||
* now, as a example, we do it more simply */
|
||||
switch (event) {
|
||||
case ESP_BLUFI_EVENT_INIT_FINISH:
|
||||
BLUFI_INFO("BLUFI init finish\n");
|
||||
esp_ble_gap_set_device_name(BLUFI_DEVICE_NAME);
|
||||
esp_ble_gap_config_adv_data(&ble_adv_data);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_DEINIT_FINISH:
|
||||
BLUFI_INFO("BLUFI deinit finish\n");
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_BLE_CONNECT:
|
||||
BLUFI_INFO("BLUFI ble connect\n");
|
||||
server_if = param->connect.server_if;
|
||||
conn_id = param->connect.conn_id;
|
||||
esp_ble_gap_stop_advertising();
|
||||
blufi_security_init();
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_BLE_DISCONNECT:
|
||||
BLUFI_INFO("BLUFI ble disconnect\n");
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
blufi_security_deinit();
|
||||
esp_ble_gap_start_advertising(&ble_adv_params);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_SET_WIFI_OPMODE:
|
||||
BLUFI_INFO("BLUFI Set WIFI opmode %d\n", param->wifi_mode.op_mode);
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(param->wifi_mode.op_mode));
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP:
|
||||
BLUFI_INFO("BLUFI requset wifi connect to AP\n");
|
||||
/* there is no wifi callback when the device has already connected to this wifi
|
||||
so disconnect wifi before connection.
|
||||
*/
|
||||
esp_wifi_disconnect();
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP:
|
||||
BLUFI_INFO("BLUFI requset wifi disconnect from AP\n");
|
||||
esp_wifi_disconnect();
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_REPORT_ERROR:
|
||||
BLUFI_ERROR("BLUFI report error, error code %d\n", param->report_error.state);
|
||||
esp_blufi_send_error_info(param->report_error.state);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_GET_WIFI_STATUS: {
|
||||
wifi_mode_t mode;
|
||||
esp_blufi_extra_info_t info;
|
||||
|
||||
esp_wifi_get_mode(&mode);
|
||||
|
||||
if (gl_sta_connected) {
|
||||
memset(&info, 0, sizeof(esp_blufi_extra_info_t));
|
||||
memcpy(info.sta_bssid, gl_sta_bssid, 6);
|
||||
info.sta_bssid_set = true;
|
||||
info.sta_ssid = gl_sta_ssid;
|
||||
info.sta_ssid_len = gl_sta_ssid_len;
|
||||
esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, 0, &info);
|
||||
} else {
|
||||
esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, 0, NULL);
|
||||
}
|
||||
BLUFI_INFO("BLUFI get wifi status from AP\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_SLAVE_DISCONNECT_BLE:
|
||||
BLUFI_INFO("blufi close a gatt connection");
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
esp_blufi_close(server_if, conn_id);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_DEAUTHENTICATE_STA:
|
||||
BLUFI_INFO("ESP_BLUFI_EVENT_DEAUTHENTICATE_STA\n");
|
||||
/* TODO */
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_STA_BSSID:
|
||||
memcpy(sta_config.sta.bssid, param->sta_bssid.bssid, 6);
|
||||
sta_config.sta.bssid_set = 1;
|
||||
esp_wifi_set_config(WIFI_IF_STA, &sta_config);
|
||||
BLUFI_INFO("Recv STA BSSID %s\n", sta_config.sta.ssid);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_STA_SSID:
|
||||
strncpy((char *)sta_config.sta.ssid, (char *)param->sta_ssid.ssid, param->sta_ssid.ssid_len);
|
||||
sta_config.sta.ssid[param->sta_ssid.ssid_len] = '\0';
|
||||
esp_wifi_set_config(WIFI_IF_STA, &sta_config);
|
||||
BLUFI_INFO("Recv STA SSID %s\n", sta_config.sta.ssid);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_STA_PASSWD:
|
||||
strncpy((char *)sta_config.sta.password, (char *)param->sta_passwd.passwd, param->sta_passwd.passwd_len);
|
||||
sta_config.sta.password[param->sta_passwd.passwd_len] = '\0';
|
||||
esp_wifi_set_config(WIFI_IF_STA, &sta_config);
|
||||
BLUFI_INFO("Recv STA PASSWORD %s\n", sta_config.sta.password);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_SOFTAP_SSID:
|
||||
strncpy((char *)ap_config.ap.ssid, (char *)param->softap_ssid.ssid, param->softap_ssid.ssid_len);
|
||||
ap_config.ap.ssid[param->softap_ssid.ssid_len] = '\0';
|
||||
ap_config.ap.ssid_len = param->softap_ssid.ssid_len;
|
||||
esp_wifi_set_config(WIFI_IF_AP, &ap_config);
|
||||
BLUFI_INFO("Recv SOFTAP SSID %s, ssid len %d\n", ap_config.ap.ssid, ap_config.ap.ssid_len);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD:
|
||||
strncpy((char *)ap_config.ap.password, (char *)param->softap_passwd.passwd, param->softap_passwd.passwd_len);
|
||||
ap_config.ap.password[param->softap_passwd.passwd_len] = '\0';
|
||||
esp_wifi_set_config(WIFI_IF_AP, &ap_config);
|
||||
BLUFI_INFO("Recv SOFTAP PASSWORD %s len = %d\n", ap_config.ap.password, param->softap_passwd.passwd_len);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM:
|
||||
if (param->softap_max_conn_num.max_conn_num > 4) {
|
||||
return;
|
||||
}
|
||||
ap_config.ap.max_connection = param->softap_max_conn_num.max_conn_num;
|
||||
esp_wifi_set_config(WIFI_IF_AP, &ap_config);
|
||||
BLUFI_INFO("Recv SOFTAP MAX CONN NUM %d\n", ap_config.ap.max_connection);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE:
|
||||
if (param->softap_auth_mode.auth_mode >= WIFI_AUTH_MAX) {
|
||||
return;
|
||||
}
|
||||
ap_config.ap.authmode = param->softap_auth_mode.auth_mode;
|
||||
esp_wifi_set_config(WIFI_IF_AP, &ap_config);
|
||||
BLUFI_INFO("Recv SOFTAP AUTH MODE %d\n", ap_config.ap.authmode);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL:
|
||||
if (param->softap_channel.channel > 13) {
|
||||
return;
|
||||
}
|
||||
ap_config.ap.channel = param->softap_channel.channel;
|
||||
esp_wifi_set_config(WIFI_IF_AP, &ap_config);
|
||||
BLUFI_INFO("Recv SOFTAP CHANNEL %d\n", ap_config.ap.channel);
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_GET_WIFI_LIST: {
|
||||
wifi_scan_config_t scanConf = {
|
||||
.ssid = NULL,
|
||||
.bssid = NULL,
|
||||
.channel = 0,
|
||||
.show_hidden = false
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, true));
|
||||
BLUFI_INFO("ESP_BLUFI_EVENT_GET_WIFI_LIST\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_CUSTOM_DATA:
|
||||
BLUFI_INFO("Recv Custom Data %d\n", param->custom_data.data_len);
|
||||
esp_log_buffer_hex("Custom Data", param->custom_data.data, param->custom_data.data_len);
|
||||
if (strcmp("restart", (char *)param->custom_data.data)) {
|
||||
esp_restart();
|
||||
}
|
||||
break;
|
||||
|
||||
case ESP_BLUFI_EVENT_RECV_USERNAME:
|
||||
/* Not handle currently */
|
||||
break;
|
||||
case ESP_BLUFI_EVENT_RECV_CA_CERT:
|
||||
/* Not handle currently */
|
||||
break;
|
||||
case ESP_BLUFI_EVENT_RECV_CLIENT_CERT:
|
||||
/* Not handle currently */
|
||||
break;
|
||||
case ESP_BLUFI_EVENT_RECV_SERVER_CERT:
|
||||
/* Not handle currently */
|
||||
break;
|
||||
case ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY:
|
||||
/* Not handle currently */
|
||||
break;
|
||||
;
|
||||
case ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY:
|
||||
/* Not handle currently */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 蓝牙 gap 事件处理
|
||||
*/
|
||||
static void ble_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
|
||||
esp_ble_gap_start_advertising(&ble_adv_params);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 蓝牙初始化
|
||||
*/
|
||||
static esp_err_t bluetooth_init()
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
ret = esp_bt_controller_init(&bt_cfg);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s initialize bt controller failed: %s\n", __func__, esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s enable bt controller failed: %s\n", __func__, esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bluedroid_init();
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s init bluedroid failed: %s\n", __func__, esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bluedroid_enable();
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s init bluedroid failed: %s\n", __func__, esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLUFI_INFO("BD ADDR: " ESP_BD_ADDR_STR "\n", ESP_BD_ADDR_HEX(esp_bt_dev_get_address()));
|
||||
|
||||
BLUFI_INFO("BLUFI VERSION %04x\n", esp_blufi_get_version());
|
||||
|
||||
ret = esp_ble_gap_register_callback(ble_gap_event_handler);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s gap register failed, error code = %x\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_blufi_register_callbacks(&blufi_callbacks);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s blufi register failed, error code = %x\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_blufi_profile_init();
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s blufi profile init failed, error code = %x\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 蓝牙配网析构
|
||||
*/
|
||||
static bool blufi_init = true;
|
||||
static void blufi_deinitialize()
|
||||
{
|
||||
if (blufi_init) {
|
||||
blufi_init = false;
|
||||
ESP_ERROR_CHECK(esp_blufi_profile_deinit());
|
||||
ESP_ERROR_CHECK(esp_bluedroid_disable());
|
||||
ESP_ERROR_CHECK(esp_bluedroid_deinit());
|
||||
ESP_ERROR_CHECK(esp_bt_controller_disable());
|
||||
ESP_ERROR_CHECK(esp_bt_controller_deinit());
|
||||
BLUFI_INFO("blufi_deinitialize\n");
|
||||
}
|
||||
// ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BTDM));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 蓝牙配网初始化
|
||||
*/
|
||||
static void blufi_initialize()
|
||||
{
|
||||
if (!blufi_init) {
|
||||
blufi_init = true;
|
||||
// initialise blutooth
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
|
||||
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));
|
||||
ESP_ERROR_CHECK(esp_bluedroid_init());
|
||||
ESP_ERROR_CHECK(esp_bluedroid_enable());
|
||||
ESP_ERROR_CHECK(esp_blufi_profile_init());
|
||||
BLUFI_INFO("blufi_initialize\n");
|
||||
}
|
||||
}
|
||||
|
||||
// wifi config timer
|
||||
TimerHandle_t wifi_config_timer;
|
||||
static bool wifi_configing = false;
|
||||
|
||||
/**
|
||||
* @brief wifi 连接成功
|
||||
*/
|
||||
void wifi_connect_succuess()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 蓝牙配网超时
|
||||
*/
|
||||
void wifi_config_timer_callback(void *arg)
|
||||
{
|
||||
if (wifi_configing == true){
|
||||
wifi_configing = false;
|
||||
// if (connnected) {
|
||||
// } else {
|
||||
// }
|
||||
BLUFI_ERROR("wifi_config_timer_callback out\n");
|
||||
|
||||
// de-initialise blufi
|
||||
blufi_deinitialize();
|
||||
|
||||
xTimerDelete(wifi_config_timer, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 进入 蓝牙配网模式
|
||||
*/
|
||||
void enter_blufi_config_wifi()
|
||||
{
|
||||
if (wifi_configing == false) {
|
||||
wifi_configing = true;
|
||||
|
||||
// initialise blufi
|
||||
blufi_initialize();
|
||||
|
||||
// start timer for 1 minute
|
||||
wifi_config_timer = xTimerCreate(
|
||||
"wifi_config_timer",
|
||||
WIFI_CONFIG_TIMEOUT / portTICK_PERIOD_MS, //period time
|
||||
pdFALSE, //auto load
|
||||
(void *)NULL, //timer parameter
|
||||
wifi_config_timer_callback); //timer callback
|
||||
|
||||
xTimerStart(wifi_config_timer, portMAX_DELAY);
|
||||
} else {
|
||||
xTimerReset(wifi_config_timer, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief udp 发现 server 初始化
|
||||
*/
|
||||
static int notice_udp_server_create()
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
int sockfd = 0;
|
||||
struct sockaddr_in server_addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(UDP_NOTICE_PORT),
|
||||
.sin_addr.s_addr = htonl(INADDR_ANY),
|
||||
};
|
||||
|
||||
retry:
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0) {
|
||||
goto ERR_EXIT;
|
||||
}
|
||||
|
||||
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
||||
if (sockfd < 0) {
|
||||
goto ERR_EXIT;
|
||||
}
|
||||
|
||||
struct timeval socket_timeout = {0, 100 * 1000};
|
||||
ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(struct timeval));
|
||||
if (sockfd < 0) {
|
||||
goto ERR_EXIT;
|
||||
}
|
||||
|
||||
ESP_LOGD("udp notice", "create udp server, port: %d, sockfd: %d", UDP_NOTICE_PORT, sockfd);
|
||||
|
||||
return sockfd;
|
||||
|
||||
ERR_EXIT:
|
||||
|
||||
if (sockfd != -1) {
|
||||
ret = close(sockfd);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGD("udp notice", "close fail, ret: %d", ret);
|
||||
}
|
||||
}
|
||||
goto retry;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief udp 发现初始化
|
||||
*/
|
||||
static void notice_udp_task(void *arg)
|
||||
{
|
||||
uint8_t root_mac[6] = {0};
|
||||
char *udp_server_buf = malloc(NOTICE_UDP_BUF_SIZE);
|
||||
struct sockaddr_in from_addr = {0};
|
||||
socklen_t from_addr_len = sizeof(struct sockaddr_in);
|
||||
|
||||
// wait network connected
|
||||
wait_net_connected();
|
||||
|
||||
int udp_server_sockfd = notice_udp_server_create();
|
||||
|
||||
if (udp_server_sockfd == -1) {
|
||||
ESP_LOGE("notice udp", "Failed to create UDP notification service");
|
||||
|
||||
vTaskDelete(NULL);
|
||||
return ;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_get_mac(ESP_IF_WIFI_STA, root_mac));
|
||||
|
||||
while(1){
|
||||
memset(udp_server_buf, 0, NOTICE_UDP_BUF_SIZE);
|
||||
if (recvfrom(udp_server_sockfd, udp_server_buf, NOTICE_UDP_BUF_SIZE,
|
||||
0, (struct sockaddr *)&from_addr, (socklen_t *)&from_addr_len) > 0) {
|
||||
ESP_LOGD("udp notice task", "Mlink notice udp recvfrom, sockfd: %d, port: %d, ip: %s, udp_server_buf: %s",
|
||||
udp_server_sockfd, ntohs(((struct sockaddr_in *)&from_addr)->sin_port),
|
||||
inet_ntoa(((struct sockaddr_in *)&from_addr)->sin_addr), udp_server_buf);
|
||||
|
||||
if (strcmp(udp_server_buf, "Are You ESP_Who_Wechat Device?")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(udp_server_buf, "WeChat MAC:%02x%02x%02x%02x%02x%02x TCP:%d",
|
||||
MAC2STR(root_mac), TCP_DEFAULT_PORT);
|
||||
|
||||
ESP_LOGD("udp notice task", "Mlink notice udp sendto, sockfd: %d, data: %s", udp_server_sockfd, udp_server_buf);
|
||||
|
||||
for (int i = 0, delay_time_ms = 0; i < NOTICE_UDP_RETRY_COUNT; ++i, delay_time_ms += delay_time_ms) {
|
||||
vTaskDelay(delay_time_ms);
|
||||
delay_time_ms = (i == 0) ? (10 / portTICK_RATE_MS) : delay_time_ms;
|
||||
|
||||
if (sendto(udp_server_sockfd, udp_server_buf, strlen(udp_server_buf),
|
||||
0, (struct sockaddr *)&from_addr, from_addr_len) <= 0) {
|
||||
ESP_LOGW("udp notice task", "Mlink notice udp sendto, errno: %d, errno_str: %s", errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
// mDNS initialise
|
||||
static void initialise_mdns(void)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t retry_count = 30;
|
||||
uint8_t root_mac[6] = {0};
|
||||
char mac_str[16] = {0};
|
||||
|
||||
// wait network connected
|
||||
wait_net_connected();
|
||||
|
||||
//initialize mDNS
|
||||
ESP_ERROR_CHECK(mdns_init());
|
||||
//set mDNS hostname (required if you want to advertise services)
|
||||
ESP_ERROR_CHECK(mdns_hostname_set(NOTICE_MDNS_HOSTNAME));
|
||||
//set default mDNS instance name
|
||||
ESP_ERROR_CHECK(mdns_instance_name_set(NOTICE_MDNS_INSTANCE));
|
||||
|
||||
mdns_txt_item_t mdns_txt_data[] = {
|
||||
{"esp-who", "WeChat"},
|
||||
{"mac", mac_str},
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_get_mac(ESP_IF_WIFI_STA, root_mac));
|
||||
sprintf(mac_str, "%02x%02x%02x%02x%02x%02x", MAC2STR(root_mac));
|
||||
|
||||
do {
|
||||
//initialize MDNS service
|
||||
ret = mdns_service_add(NOTICE_MDNS_INSTANCE, NOTICE_MDNS_SERVICE_TYPE, NOTICE_MDNS_PROTO, TCP_DEFAULT_PORT,
|
||||
mdns_txt_data, sizeof(mdns_txt_data) / sizeof(mdns_txt_item_t));
|
||||
|
||||
if (ret != 0) {
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
}
|
||||
} while (ret != 0 && retry_count--);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mdns 初始化、udp 发现初始化
|
||||
*/
|
||||
static void initialise_notice()
|
||||
{
|
||||
// initialise mdns
|
||||
initialise_mdns();
|
||||
|
||||
// initialise udp notice service
|
||||
xTaskCreatePinnedToCore(notice_udp_task, "notice_udp", 3 * 1024, NULL, 4, NULL, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 蓝牙、wifi 初始化、mdns 初始化、udp 发现初始化
|
||||
*/
|
||||
void blufi_main()
|
||||
{
|
||||
// initialise blutooth
|
||||
ESP_ERROR_CHECK(bluetooth_init());
|
||||
|
||||
// de-initialise blufi
|
||||
blufi_deinitialize();
|
||||
|
||||
// load wifi ssid passwd
|
||||
load_info_nvs(NVS_KEY_WIFI_SSID_PASS, (void *)(sta_config.sta.ssid), WIFI_SSID_PASS_SIZE);
|
||||
|
||||
// initialise wifi
|
||||
wifi_init_ap_sta();
|
||||
|
||||
// initialise notice service
|
||||
initialise_notice();
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/* C Includes */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* FreeRTOS Includes */
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
/* ESP32 Includes */
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_bt.h"
|
||||
|
||||
/* Blutooth Includes */
|
||||
#include "esp_blufi_api.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#include "esp_bt_main.h"
|
||||
|
||||
/* TLS Includes */
|
||||
#include "mbedtls/aes.h"
|
||||
#include "mbedtls/dhm.h"
|
||||
#include "mbedtls/md5.h"
|
||||
#include "rom/crc.h"
|
||||
|
||||
/* wechat Includes */
|
||||
#include "wechat_blufi.h"
|
||||
|
||||
/*
|
||||
The SEC_TYPE_xxx is for self-defined packet data type in the procedure of "BLUFI negotiate key"
|
||||
If user use other negotiation procedure to exchange(or generate) key, should redefine the type by yourself.
|
||||
*/
|
||||
#define SEC_TYPE_DH_PARAM_LEN 0x00
|
||||
#define SEC_TYPE_DH_PARAM_DATA 0x01
|
||||
#define SEC_TYPE_DH_P 0x02
|
||||
#define SEC_TYPE_DH_G 0x03
|
||||
#define SEC_TYPE_DH_PUBLIC 0x04
|
||||
|
||||
struct blufi_security {
|
||||
#define DH_SELF_PUB_KEY_LEN 128
|
||||
#define DH_SELF_PUB_KEY_BIT_LEN (DH_SELF_PUB_KEY_LEN * 8)
|
||||
uint8_t self_public_key[DH_SELF_PUB_KEY_LEN];
|
||||
#define SHARE_KEY_LEN 128
|
||||
#define SHARE_KEY_BIT_LEN (SHARE_KEY_LEN * 8)
|
||||
uint8_t share_key[SHARE_KEY_LEN];
|
||||
size_t share_len;
|
||||
#define PSK_LEN 16
|
||||
uint8_t psk[PSK_LEN];
|
||||
uint8_t *dh_param;
|
||||
int dh_param_len;
|
||||
uint8_t iv[16];
|
||||
mbedtls_dhm_context dhm;
|
||||
mbedtls_aes_context aes;
|
||||
};
|
||||
|
||||
static struct blufi_security *blufi_sec;
|
||||
|
||||
extern void btc_blufi_report_error(esp_blufi_error_state_t state);
|
||||
|
||||
static int myrand(void *rng_state, unsigned char *output, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
output[i] = esp_random();
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free)
|
||||
{
|
||||
int ret;
|
||||
uint8_t type = data[0];
|
||||
|
||||
if (blufi_sec == NULL) {
|
||||
BLUFI_ERROR("BLUFI Security is not initialized");
|
||||
btc_blufi_report_error(ESP_BLUFI_INIT_SECURITY_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SEC_TYPE_DH_PARAM_LEN:
|
||||
blufi_sec->dh_param_len = ((data[1] << 8) | data[2]);
|
||||
if (blufi_sec->dh_param) {
|
||||
free(blufi_sec->dh_param);
|
||||
blufi_sec->dh_param = NULL;
|
||||
}
|
||||
blufi_sec->dh_param = (uint8_t *)malloc(blufi_sec->dh_param_len);
|
||||
if (blufi_sec->dh_param == NULL) {
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
BLUFI_ERROR("%s, malloc failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case SEC_TYPE_DH_PARAM_DATA: {
|
||||
if (blufi_sec->dh_param == NULL) {
|
||||
BLUFI_ERROR("%s, blufi_sec->dh_param == NULL\n", __func__);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
uint8_t *param = blufi_sec->dh_param;
|
||||
memcpy(blufi_sec->dh_param, &data[1], blufi_sec->dh_param_len);
|
||||
ret = mbedtls_dhm_read_params(&blufi_sec->dhm, ¶m, ¶m[blufi_sec->dh_param_len]);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s read param failed %d\n", __func__, ret);
|
||||
btc_blufi_report_error(ESP_BLUFI_READ_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
free(blufi_sec->dh_param);
|
||||
blufi_sec->dh_param = NULL;
|
||||
ret = mbedtls_dhm_make_public(&blufi_sec->dhm, (int)mbedtls_mpi_size(&blufi_sec->dhm.P), blufi_sec->self_public_key, blufi_sec->dhm.len, myrand, NULL);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s make public failed %d\n", __func__, ret);
|
||||
btc_blufi_report_error(ESP_BLUFI_MAKE_PUBLIC_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_dhm_calc_secret(&blufi_sec->dhm,
|
||||
blufi_sec->share_key,
|
||||
SHARE_KEY_BIT_LEN,
|
||||
&blufi_sec->share_len,
|
||||
NULL, NULL);
|
||||
|
||||
mbedtls_md5(blufi_sec->share_key, blufi_sec->share_len, blufi_sec->psk);
|
||||
|
||||
mbedtls_aes_setkey_enc(&blufi_sec->aes, blufi_sec->psk, 128);
|
||||
|
||||
/* alloc output data */
|
||||
*output_data = &blufi_sec->self_public_key[0];
|
||||
*output_len = blufi_sec->dhm.len;
|
||||
*need_free = false;
|
||||
}
|
||||
break;
|
||||
case SEC_TYPE_DH_P:
|
||||
break;
|
||||
case SEC_TYPE_DH_G:
|
||||
break;
|
||||
case SEC_TYPE_DH_PUBLIC:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int blufi_aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len)
|
||||
{
|
||||
int ret;
|
||||
size_t iv_offset = 0;
|
||||
uint8_t iv0[16];
|
||||
|
||||
memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv));
|
||||
iv0[0] = iv8; /* set iv8 as the iv0[0] */
|
||||
|
||||
ret = mbedtls_aes_crypt_cfb128(&blufi_sec->aes, MBEDTLS_AES_ENCRYPT, crypt_len, &iv_offset, iv0, crypt_data, crypt_data);
|
||||
if (ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return crypt_len;
|
||||
}
|
||||
|
||||
int blufi_aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len)
|
||||
{
|
||||
int ret;
|
||||
size_t iv_offset = 0;
|
||||
uint8_t iv0[16];
|
||||
|
||||
memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv));
|
||||
iv0[0] = iv8; /* set iv8 as the iv0[0] */
|
||||
|
||||
ret = mbedtls_aes_crypt_cfb128(&blufi_sec->aes, MBEDTLS_AES_DECRYPT, crypt_len, &iv_offset, iv0, crypt_data, crypt_data);
|
||||
if (ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return crypt_len;
|
||||
}
|
||||
|
||||
uint16_t blufi_crc_checksum(uint8_t iv8, uint8_t *data, int len)
|
||||
{
|
||||
/* This iv8 ignore, not used */
|
||||
return crc16_be(0, data, len);
|
||||
}
|
||||
|
||||
esp_err_t blufi_security_init(void)
|
||||
{
|
||||
blufi_sec = (struct blufi_security *)malloc(sizeof(struct blufi_security));
|
||||
if (blufi_sec == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
memset(blufi_sec, 0x0, sizeof(struct blufi_security));
|
||||
|
||||
mbedtls_dhm_init(&blufi_sec->dhm);
|
||||
mbedtls_aes_init(&blufi_sec->aes);
|
||||
|
||||
memset(blufi_sec->iv, 0x0, 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void blufi_security_deinit(void)
|
||||
{
|
||||
if (blufi_sec == NULL) {
|
||||
return;
|
||||
}
|
||||
if (blufi_sec->dh_param) {
|
||||
free(blufi_sec->dh_param);
|
||||
blufi_sec->dh_param = NULL;
|
||||
}
|
||||
mbedtls_dhm_free(&blufi_sec->dhm);
|
||||
mbedtls_aes_free(&blufi_sec->aes);
|
||||
|
||||
memset(blufi_sec, 0x0, sizeof(struct blufi_security));
|
||||
|
||||
free(blufi_sec);
|
||||
blufi_sec = NULL;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
menu "Example Configuration"
|
||||
|
||||
config ESP_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default ""
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config ESP_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default ""
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
config MAX_STA_CONN
|
||||
int "Maximal STA connections"
|
||||
default 1
|
||||
help
|
||||
Max number of the STA connects to AP.
|
||||
|
||||
config SERVER_IP
|
||||
string "IP address of server"
|
||||
default "192.168.4.1"
|
||||
endmenu
|
|
@ -0,0 +1,73 @@
|
|||
/* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "app_camera.h"
|
||||
|
||||
static const char *TAG = "app_camera";
|
||||
|
||||
void app_camera_init()
|
||||
{
|
||||
/* IO13, IO14 is designed for JTAG by default,
|
||||
* to use it as generalized input,
|
||||
* firstly declair it as pullup input */
|
||||
gpio_config_t conf;
|
||||
conf.mode = GPIO_MODE_INPUT;
|
||||
conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
conf.intr_type = GPIO_INTR_DISABLE;
|
||||
conf.pin_bit_mask = 1LL << 13;
|
||||
gpio_config(&conf);
|
||||
conf.pin_bit_mask = 1LL << 14;
|
||||
gpio_config(&conf);
|
||||
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sscb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.xclk_freq_hz = XCLK_FREQ;
|
||||
config.pixel_format = CAMERA_PIXEL_FORMAT;
|
||||
config.frame_size = CAMERA_FRAME_SIZE;
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Camera init failed with error 0x%x", err);
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "app_httpserver.h"
|
||||
#include "fd_forward.h"
|
||||
#include "image_util.h"
|
||||
#include "app_main.h"
|
||||
|
||||
static const char *TAG = "app_process";
|
||||
|
||||
face_id_name_list st_face_list = {0};
|
||||
static dl_matrix3du_t *aligned_face = NULL;
|
||||
|
||||
extern QueueHandle_t gpst_input_image;
|
||||
extern QueueHandle_t gpst_output;
|
||||
|
||||
static inline mtmn_config_t app_mtmn_config()
|
||||
{
|
||||
mtmn_config_t mtmn_config;
|
||||
mtmn_config.min_face = 80;
|
||||
mtmn_config.pyramid = 0.7;
|
||||
mtmn_config.p_threshold.score = 0.6;
|
||||
mtmn_config.p_threshold.nms = 0.7;
|
||||
mtmn_config.p_threshold.candidate_number = 100;
|
||||
mtmn_config.r_threshold.score = 0.6;
|
||||
mtmn_config.r_threshold.nms = 0.7;
|
||||
mtmn_config.r_threshold.candidate_number = 4;
|
||||
mtmn_config.o_threshold.score = 0.6;
|
||||
mtmn_config.o_threshold.nms = 0.4;
|
||||
mtmn_config.o_threshold.candidate_number = 1;
|
||||
|
||||
return mtmn_config;
|
||||
}
|
||||
|
||||
static inline box_array_t *do_detection(camera_fb_t *fb, dl_matrix3du_t *image_mat, mtmn_config_t *mtmn_config)
|
||||
{
|
||||
if(!fmt2rgb888(fb->buf, fb->len, fb->format, image_mat->item))
|
||||
{
|
||||
ESP_LOGW(TAG, "fmt2rgb888 failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
box_array_t *net_boxes = face_detect(image_mat, mtmn_config);
|
||||
return net_boxes;
|
||||
}
|
||||
|
||||
|
||||
void task_process(void *arg)
|
||||
{
|
||||
camera_fb_t * fb = NULL;
|
||||
dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, 320, 240, 3);
|
||||
if (!image_matrix)
|
||||
{
|
||||
ESP_LOGE(TAG, "dl_matrix3du_alloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
mtmn_config_t mtmn_config = app_mtmn_config();
|
||||
http_img_process_result out_res = {0};
|
||||
//out_res.lock = xSemaphoreCreateBinary();
|
||||
|
||||
out_res.image = image_matrix->item;
|
||||
|
||||
while (1)
|
||||
{
|
||||
xQueueReceive(gpst_input_image, &fb, portMAX_DELAY);
|
||||
|
||||
//xSemaphoreTake(out_res.lock, portMAX_DELAY);
|
||||
out_res.net_boxes = NULL;
|
||||
out_res.face_id = NULL;
|
||||
|
||||
out_res.net_boxes = do_detection(fb, image_matrix, &mtmn_config);
|
||||
|
||||
if (out_res.net_boxes)
|
||||
{
|
||||
if (g_state == START_DETECT)
|
||||
{
|
||||
xQueueSend(gpst_output, &out_res, portMAX_DELAY);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get face ID
|
||||
if (align_face(out_res.net_boxes, image_matrix, aligned_face) == ESP_OK)
|
||||
{
|
||||
out_res.face_id = get_face_id(aligned_face);
|
||||
}
|
||||
}
|
||||
xQueueSend(gpst_output, &out_res, portMAX_DELAY);
|
||||
}
|
||||
|
||||
dl_matrix3du_free(image_matrix);
|
||||
}
|
||||
|
||||
void app_facenet_main()
|
||||
{
|
||||
face_id_name_init(&st_face_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
|
||||
aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3);
|
||||
read_face_id_from_flash_with_name(&st_face_list);
|
||||
|
||||
xTaskCreatePinnedToCore(task_process, "process", 4 * 1024, NULL, 5, NULL, 1);
|
||||
}
|
|
@ -0,0 +1,616 @@
|
|||
/* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "app_httpserver.h"
|
||||
#include "esp_log.h"
|
||||
#include "image_util.h"
|
||||
#include "fb_gfx.h"
|
||||
#include "app_main.h"
|
||||
|
||||
static const char *TAG = "app_httpserver";
|
||||
|
||||
#define FACE_COLOR_WHITE 0x00FFFFFF
|
||||
#define FACE_COLOR_BLACK 0x00000000
|
||||
#define FACE_COLOR_RED 0x000000FF
|
||||
#define FACE_COLOR_GREEN 0x0000FF00
|
||||
#define FACE_COLOR_BLUE 0x00FF0000
|
||||
#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN)
|
||||
#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN)
|
||||
#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED)
|
||||
|
||||
|
||||
#define PART_BOUNDARY "123456789000000000000987654321"
|
||||
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
|
||||
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
|
||||
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
|
||||
|
||||
extern face_id_name_list st_face_list;
|
||||
static int8_t g_is_enrolling = 0;
|
||||
static int8_t g_stop_stream = 0;
|
||||
static int8_t g_detection_enabled = 0;
|
||||
static int8_t g_recognition_enabled = 0;
|
||||
typedef struct
|
||||
{
|
||||
char enroll_name[ENROLL_NAME_LEN];
|
||||
} httpd_resp_value;
|
||||
|
||||
httpd_resp_value st_name;
|
||||
QueueHandle_t gpst_input_image = NULL;
|
||||
QueueHandle_t gpst_output = NULL;
|
||||
|
||||
// Profiling
|
||||
static int64_t fr_start = 0;
|
||||
static int64_t fr_ready = 0;
|
||||
static int64_t fr_face = 0;
|
||||
static int64_t fr_recognize = 0;
|
||||
static int64_t fr_encode = 0;
|
||||
|
||||
//static void oneshot_timer_callback(void* arg);
|
||||
char *number_suffix(int32_t number)
|
||||
{
|
||||
uint8_t n = number % 10;
|
||||
|
||||
if (n == 0)
|
||||
return "zero";
|
||||
else if (n == 1)
|
||||
return "st";
|
||||
else if (n == 2)
|
||||
return "nd";
|
||||
else if (n == 3)
|
||||
return "rd";
|
||||
else
|
||||
return "th";
|
||||
}
|
||||
|
||||
|
||||
static void rgb_print(void *image, int w, int h, uint32_t color, const char * str){
|
||||
fb_data_t fb;
|
||||
fb.width = w;
|
||||
fb.height = h;
|
||||
fb.data = image;
|
||||
fb.bytes_per_pixel = 3;
|
||||
fb.format = FB_BGR888;
|
||||
fb_gfx_print(&fb, (fb.width - (strlen(str) * 14)) / 2, 10, color, str);
|
||||
}
|
||||
|
||||
static int rgb_printf(void *image, int w, int h, uint32_t color, const char *format, ...)
|
||||
{
|
||||
char loc_buf[64];
|
||||
char * temp = loc_buf;
|
||||
int len;
|
||||
va_list arg;
|
||||
va_list copy;
|
||||
va_start(arg, format);
|
||||
va_copy(copy, arg);
|
||||
len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg);
|
||||
va_end(copy);
|
||||
if(len >= sizeof(loc_buf)){
|
||||
temp = (char*)malloc(len+1);
|
||||
if(temp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
vsnprintf(temp, len+1, format, arg);
|
||||
va_end(arg);
|
||||
rgb_print(image, w, h, color, temp);
|
||||
if(len > 64){
|
||||
free(temp);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void draw_face_boxes(void *image, int width, int height, box_array_t *boxes){
|
||||
int x, y, w, h, i;
|
||||
uint32_t color = FACE_COLOR_YELLOW;
|
||||
fb_data_t fb;
|
||||
fb.width = width;
|
||||
fb.height = height;
|
||||
fb.data = image;
|
||||
fb.bytes_per_pixel = 3;
|
||||
fb.format = FB_BGR888;
|
||||
for (i = 0; i < boxes->len; i++){
|
||||
// rectangle box
|
||||
x = (int)boxes->box[i].box_p[0];
|
||||
y = (int)boxes->box[i].box_p[1];
|
||||
w = (int)boxes->box[i].box_p[2] - x + 1;
|
||||
h = (int)boxes->box[i].box_p[3] - y + 1;
|
||||
fb_gfx_drawFastHLine(&fb, x, y, w, color);
|
||||
fb_gfx_drawFastHLine(&fb, x, y+h-1, w, color);
|
||||
fb_gfx_drawFastVLine(&fb, x, y, h, color);
|
||||
fb_gfx_drawFastVLine(&fb, x+w-1, y, h, color);
|
||||
#if 0
|
||||
// landmark
|
||||
int x0, y0, j;
|
||||
for (j = 0; j < 10; j+=2) {
|
||||
x0 = (int)boxes->landmark[i].landmark_p[j];
|
||||
y0 = (int)boxes->landmark[i].landmark_p[j+1];
|
||||
fb_gfx_fillRect(&fb, x0, y0, 3, 3, color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static inline int do_enrollment(face_id_name_list *face_list, dl_matrix3d_t *new_id)
|
||||
{
|
||||
ESP_LOGD(TAG, "START ENROLLING");
|
||||
|
||||
int left_sample_face = enroll_face_id_to_flash_with_name(face_list, new_id, st_name.enroll_name);
|
||||
ESP_LOGD(TAG, "Face ID %s Enrollment: Taken the %d%s sample",
|
||||
face_list->tail->id_name,
|
||||
ENROLL_CONFIRM_TIMES - left_sample_face,
|
||||
number_suffix(ENROLL_CONFIRM_TIMES - left_sample_face));
|
||||
gpio_set_level(GPIO_LED_RED, 0);
|
||||
return left_sample_face;
|
||||
}
|
||||
|
||||
esp_err_t facenet_stream_handler(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t res = ESP_OK;
|
||||
g_state = START_STREAM;
|
||||
g_stop_stream = 0;
|
||||
|
||||
camera_fb_t * fb = NULL;
|
||||
size_t _jpg_buf_len = 0;
|
||||
uint8_t * _jpg_buf = NULL;
|
||||
char * part_buf[64];
|
||||
|
||||
http_img_process_result out_res = {0};
|
||||
|
||||
static int64_t last_frame = 0;
|
||||
if(!last_frame) {
|
||||
last_frame = esp_timer_get_time();
|
||||
}
|
||||
|
||||
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
|
||||
if(res != ESP_OK){
|
||||
return res;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Get count %d\n", st_face_list.count);
|
||||
|
||||
while(true)
|
||||
{
|
||||
// update fsm state
|
||||
if (g_stop_stream)
|
||||
{
|
||||
g_stop_stream = 0;
|
||||
httpd_resp_send_404(req);
|
||||
break;
|
||||
}
|
||||
else if (g_is_enrolling)
|
||||
{
|
||||
g_state = START_ENROLL;
|
||||
}
|
||||
else if (g_recognition_enabled && (st_face_list.count > 0))
|
||||
{
|
||||
g_state = START_RECOGNITION;
|
||||
}
|
||||
else if (g_detection_enabled)
|
||||
{
|
||||
g_state = START_DETECT;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_state = START_STREAM;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "State: %d, count:%d", g_state, st_face_list.count);
|
||||
// exec event
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb)
|
||||
{
|
||||
ESP_LOGE(TAG, "Camera capture failed");
|
||||
res = ESP_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_state == START_STREAM)
|
||||
{
|
||||
_jpg_buf = fb->buf;
|
||||
_jpg_buf_len = fb->len;
|
||||
goto http_response;
|
||||
}
|
||||
|
||||
fr_start = esp_timer_get_time();
|
||||
fr_ready = fr_start;
|
||||
fr_face = fr_start;
|
||||
fr_encode = fr_start;
|
||||
fr_recognize = fr_start;
|
||||
|
||||
xQueueSend(gpst_input_image, &fb, portMAX_DELAY);
|
||||
|
||||
xQueueReceive(gpst_output, &out_res, portMAX_DELAY);
|
||||
|
||||
fr_recognize = fr_face;
|
||||
|
||||
if (out_res.net_boxes)
|
||||
{
|
||||
draw_face_boxes(out_res.image, fb->width, fb->height, out_res.net_boxes);
|
||||
free(out_res.net_boxes->box);
|
||||
free(out_res.net_boxes->landmark);
|
||||
free(out_res.net_boxes);
|
||||
|
||||
if (out_res.face_id)
|
||||
{
|
||||
if (g_state == START_ENROLL)
|
||||
{
|
||||
int left_sample_face = do_enrollment(&st_face_list, out_res.face_id);
|
||||
rgb_print(out_res.image, fb->width, fb->height, FACE_COLOR_YELLOW, "START ENROLLING");
|
||||
rgb_printf(out_res.image, fb->width, fb->height, FACE_COLOR_CYAN, "\nThe %u%s sample",
|
||||
ENROLL_CONFIRM_TIMES - left_sample_face,
|
||||
number_suffix(ENROLL_CONFIRM_TIMES - left_sample_face));
|
||||
if (left_sample_face == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Enrolled Face ID: %s", st_face_list.tail->id_name);
|
||||
rgb_printf(out_res.image, fb->width, fb->height, FACE_COLOR_CYAN, "\n\nFace ID: %s", st_face_list.tail->id_name);
|
||||
g_is_enrolling = 0;
|
||||
g_state = START_RECOGNITION;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
face_id_node *f = recognize_face_with_name(&st_face_list, out_res.face_id);
|
||||
|
||||
if (f)
|
||||
{
|
||||
gpio_set_level(GPIO_LED_RED, 1);
|
||||
rgb_printf(out_res.image, fb->width, fb->height, FACE_COLOR_GREEN, "Hello %s", f->id_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgb_print(out_res.image, fb->width, fb->height, FACE_COLOR_RED, "\nWHO?");
|
||||
}
|
||||
} // START_ENROLL
|
||||
dl_matrix3d_free(out_res.face_id);
|
||||
}
|
||||
//xSemaphoreGive(out_res.lock);
|
||||
|
||||
if(!fmt2jpg(out_res.image, fb->width*fb->height*3, fb->width, fb->height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len))
|
||||
{
|
||||
ESP_LOGE(TAG, "fmt2jpg failed");
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_jpg_buf = fb->buf;
|
||||
_jpg_buf_len = fb->len;
|
||||
}
|
||||
fr_encode = esp_timer_get_time();
|
||||
|
||||
|
||||
http_response:
|
||||
if(res == ESP_OK){
|
||||
size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
|
||||
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
|
||||
}
|
||||
if(res == ESP_OK){
|
||||
res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
|
||||
}
|
||||
if(res == ESP_OK){
|
||||
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
|
||||
}
|
||||
if(fb){
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
_jpg_buf = NULL;
|
||||
} else if(_jpg_buf){
|
||||
free(_jpg_buf);
|
||||
_jpg_buf = NULL;
|
||||
}
|
||||
if(res != ESP_OK){
|
||||
break;
|
||||
}
|
||||
int64_t fr_end = esp_timer_get_time();
|
||||
|
||||
int64_t ready_time = (fr_ready - fr_start)/1000;
|
||||
int64_t face_time = (fr_face - fr_ready)/1000;
|
||||
int64_t recognize_time = (fr_recognize - fr_face)/1000;
|
||||
int64_t encode_time = (fr_encode - fr_recognize)/1000;
|
||||
int64_t process_time = (fr_encode - fr_start)/1000;
|
||||
|
||||
int64_t frame_time = fr_end - last_frame;
|
||||
last_frame = fr_end;
|
||||
frame_time /= 1000;
|
||||
ESP_LOGI(TAG, "MJPG: %uKB %ums (%.1ffps), %u+%u+%u+%u=%u",
|
||||
(uint32_t)(_jpg_buf_len/1024),
|
||||
(uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
|
||||
(uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time);
|
||||
}
|
||||
|
||||
last_frame = 0;
|
||||
g_state = WAIT_FOR_CONNECT;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
httpd_uri_t _face_stream_handler = {
|
||||
.uri = "/stream",
|
||||
.method = HTTP_GET,
|
||||
.handler = facenet_stream_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
static esp_err_t cmd_handler(httpd_req_t *req){
|
||||
char* buf;
|
||||
size_t buf_len;
|
||||
char variable[32] = {0,};
|
||||
char value[FACE_ID_SAVE_NUMBER * ENROLL_NAME_LEN] = {0,};
|
||||
|
||||
buf_len = httpd_req_get_url_query_len(req) + 1;
|
||||
if (buf_len > 1) {
|
||||
buf = (char*)malloc(buf_len);
|
||||
if(!buf){
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
|
||||
if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&
|
||||
httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {
|
||||
} else {
|
||||
free(buf);
|
||||
httpd_resp_send_404(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
free(buf);
|
||||
httpd_resp_send_404(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
free(buf);
|
||||
} else {
|
||||
httpd_resp_send_404(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
int val = atoi(value);
|
||||
ESP_LOGI(TAG, "%s = %d", variable, val);
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
int res = 0;
|
||||
|
||||
if(!strcmp(variable, "framesize")) {
|
||||
if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);
|
||||
}
|
||||
else if(!strcmp(variable, "quality")) res = s->set_quality(s, val);
|
||||
else if(!strcmp(variable, "contrast")) res = s->set_contrast(s, val);
|
||||
else if(!strcmp(variable, "brightness")) res = s->set_brightness(s, val);
|
||||
else if(!strcmp(variable, "saturation")) res = s->set_saturation(s, val);
|
||||
else if(!strcmp(variable, "gainceiling")) res = s->set_gainceiling(s, (gainceiling_t)val);
|
||||
else if(!strcmp(variable, "colorbar")) res = s->set_colorbar(s, val);
|
||||
else if(!strcmp(variable, "awb")) res = s->set_whitebal(s, val);
|
||||
else if(!strcmp(variable, "agc")) res = s->set_gain_ctrl(s, val);
|
||||
else if(!strcmp(variable, "aec")) res = s->set_exposure_ctrl(s, val);
|
||||
else if(!strcmp(variable, "hmirror")) res = s->set_hmirror(s, val);
|
||||
else if(!strcmp(variable, "vflip")) res = s->set_vflip(s, val);
|
||||
else if(!strcmp(variable, "awb_gain")) res = s->set_awb_gain(s, val);
|
||||
else if(!strcmp(variable, "agc_gain")) res = s->set_agc_gain(s, val);
|
||||
else if(!strcmp(variable, "aec_value")) res = s->set_aec_value(s, val);
|
||||
else if(!strcmp(variable, "aec2")) res = s->set_aec2(s, val);
|
||||
else if(!strcmp(variable, "dcw")) res = s->set_dcw(s, val);
|
||||
else if(!strcmp(variable, "bpc")) res = s->set_bpc(s, val);
|
||||
else if(!strcmp(variable, "wpc")) res = s->set_wpc(s, val);
|
||||
else if(!strcmp(variable, "raw_gma")) res = s->set_raw_gma(s, val);
|
||||
else if(!strcmp(variable, "lenc")) res = s->set_lenc(s, val);
|
||||
else if(!strcmp(variable, "special_effect")) res = s->set_special_effect(s, val);
|
||||
else if(!strcmp(variable, "wb_mode")) res = s->set_wb_mode(s, val);
|
||||
else if(!strcmp(variable, "ae_level")) res = s->set_ae_level(s, val);
|
||||
|
||||
else if(!strcmp(variable, "stop_stream")) g_stop_stream = 1;
|
||||
else if(!strcmp(variable, "face_detect")) {
|
||||
g_detection_enabled = val;
|
||||
if(!g_detection_enabled) {
|
||||
g_recognition_enabled = 0;
|
||||
g_is_enrolling = 0;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(variable, "face_enroll"))
|
||||
{
|
||||
if (!g_is_enrolling && g_recognition_enabled)
|
||||
{
|
||||
memcpy(st_name.enroll_name, value, strlen(value) + 1);
|
||||
g_is_enrolling = 1;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(variable, "face_delete"))
|
||||
{
|
||||
// ["aaa","bbb"]
|
||||
char delete_name[ENROLL_NAME_LEN * FACE_ID_SAVE_NUMBER];
|
||||
uint8_t len = strlen(value) - strlen("%5b%22") - strlen("%22%5d");
|
||||
memcpy(delete_name, value + strlen("%5b%22"), len);
|
||||
delete_name[len] = 0;
|
||||
char *p = delete_name;
|
||||
char *q = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
q = strstr(p, "%22%2C%22");
|
||||
if (!q)
|
||||
break;
|
||||
p[q - p] = 0;
|
||||
int8_t left = delete_face_id_in_flash_with_name(&st_face_list, p);
|
||||
if (left > 0)
|
||||
ESP_LOGW(TAG, "%s ID Delete", p);
|
||||
p = q + 9;
|
||||
q = strstr(p, "%22%2C%22");
|
||||
} while (q);
|
||||
int8_t left = delete_face_id_in_flash_with_name(&st_face_list, p);
|
||||
if (left > 0)
|
||||
ESP_LOGW(TAG, "%s ID Delete", p);
|
||||
}
|
||||
else if(!strcmp(variable, "delete_all"))
|
||||
{
|
||||
delete_face_all_in_flash_with_name(&st_face_list);
|
||||
}
|
||||
else if(!strcmp(variable, "face_recognize")) {
|
||||
g_recognition_enabled = val;
|
||||
if(g_recognition_enabled){
|
||||
g_detection_enabled = val;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(variable, "get_id")) {
|
||||
static char id_json[1024];
|
||||
char *p = id_json;
|
||||
*p++ = '{';
|
||||
p += sprintf(p, "\"len\":%d,", st_face_list.count);
|
||||
p += sprintf(p, "\"list\":[");
|
||||
face_id_node *head = st_face_list.head;
|
||||
for (int i = 0; i < st_face_list.count; i++)
|
||||
{
|
||||
p += sprintf(p, "\"%s\",", head->id_name);
|
||||
head = head->next;
|
||||
}
|
||||
if (st_face_list.count)
|
||||
p--;
|
||||
*p++ = ']';
|
||||
*p++ = '}';
|
||||
*p++ = 0;
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
return httpd_resp_send(req, id_json, strlen(id_json));
|
||||
}
|
||||
else {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if(res){
|
||||
return httpd_resp_send_500(req);
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
return httpd_resp_send(req, NULL, 0);
|
||||
}
|
||||
|
||||
httpd_uri_t cmd_uri = {
|
||||
.uri = "/control",
|
||||
.method = HTTP_GET,
|
||||
.handler = cmd_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_handle_t camera_httpd = NULL;
|
||||
|
||||
|
||||
static esp_err_t status_handler(httpd_req_t *req){
|
||||
static char json_response[1024];
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
char * p = json_response;
|
||||
*p++ = '{';
|
||||
|
||||
p+=sprintf(p, "\"framesize\":%u,", s->status.framesize);
|
||||
p+=sprintf(p, "\"quality\":%u,", s->status.quality);
|
||||
p+=sprintf(p, "\"brightness\":%d,", s->status.brightness);
|
||||
p+=sprintf(p, "\"contrast\":%d,", s->status.contrast);
|
||||
p+=sprintf(p, "\"saturation\":%d,", s->status.saturation);
|
||||
p+=sprintf(p, "\"special_effect\":%u,", s->status.special_effect);
|
||||
p+=sprintf(p, "\"wb_mode\":%u,", s->status.wb_mode);
|
||||
p+=sprintf(p, "\"awb\":%u,", s->status.awb);
|
||||
p+=sprintf(p, "\"awb_gain\":%u,", s->status.awb_gain);
|
||||
p+=sprintf(p, "\"aec\":%u,", s->status.aec);
|
||||
p+=sprintf(p, "\"aec2\":%u,", s->status.aec2);
|
||||
p+=sprintf(p, "\"ae_level\":%d,", s->status.ae_level);
|
||||
p+=sprintf(p, "\"aec_value\":%u,", s->status.aec_value);
|
||||
p+=sprintf(p, "\"agc\":%u,", s->status.agc);
|
||||
p+=sprintf(p, "\"agc_gain\":%u,", s->status.agc_gain);
|
||||
p+=sprintf(p, "\"gainceiling\":%u,", s->status.gainceiling);
|
||||
p+=sprintf(p, "\"bpc\":%u,", s->status.bpc);
|
||||
p+=sprintf(p, "\"wpc\":%u,", s->status.wpc);
|
||||
p+=sprintf(p, "\"raw_gma\":%u,", s->status.raw_gma);
|
||||
p+=sprintf(p, "\"lenc\":%u,", s->status.lenc);
|
||||
p+=sprintf(p, "\"hmirror\":%u,", s->status.hmirror);
|
||||
p+=sprintf(p, "\"dcw\":%u,", s->status.dcw);
|
||||
p+=sprintf(p, "\"colorbar\":%u", s->status.colorbar);
|
||||
|
||||
p+=sprintf(p, ",\"face_detect\":%u", g_detection_enabled);
|
||||
p+=sprintf(p, ",\"face_enroll\":%u,", g_is_enrolling);
|
||||
p+=sprintf(p, "\"face_recognize\":%u", g_recognition_enabled);
|
||||
*p++ = '}';
|
||||
*p++ = 0;
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
return httpd_resp_send(req, json_response, strlen(json_response));
|
||||
}
|
||||
httpd_uri_t status_uri = {
|
||||
.uri = "/status",
|
||||
.method = HTTP_GET,
|
||||
.handler = status_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
#if 0
|
||||
const esp_timer_create_args_t oneshot_timer_args = {
|
||||
.callback = &oneshot_timer_callback,
|
||||
/* argument specified here will be passed to timer callback function */
|
||||
.name = "one-shot"
|
||||
};
|
||||
esp_timer_handle_t oneshot_timer;
|
||||
|
||||
static void oneshot_timer_callback(void* arg)
|
||||
{
|
||||
if(g_state != START_ENROLL)
|
||||
g_is_enrolling = 1;
|
||||
}
|
||||
|
||||
|
||||
static void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||
{
|
||||
esp_err_t err = esp_timer_start_once(oneshot_timer, 500000);
|
||||
if(err == ESP_ERR_INVALID_STATE)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_timer_stop(oneshot_timer));
|
||||
g_is_enrolling = 0;
|
||||
g_is_deleting = 1;
|
||||
gpio_set_level(GPIO_LED_WHITE, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void app_httpserver_init ()
|
||||
{
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.stack_size = 4096 * 2;
|
||||
|
||||
#if 0
|
||||
ESP_ERROR_CHECK(esp_timer_create(&oneshot_timer_args, &oneshot_timer));
|
||||
|
||||
gpio_config_t io_conf = {0};
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;
|
||||
io_conf.pin_bit_mask = 1LL << GPIO_BUTTON;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&io_conf);
|
||||
gpio_isr_handler_add(GPIO_BUTTON, gpio_isr_handler, NULL);
|
||||
#endif
|
||||
|
||||
gpst_input_image = xQueueCreate(1, sizeof(void *));
|
||||
gpst_output = xQueueCreate(1, sizeof(http_img_process_result));
|
||||
|
||||
|
||||
if (httpd_start(&camera_httpd, &config) == ESP_OK)
|
||||
{
|
||||
httpd_register_uri_handler(camera_httpd, &cmd_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &status_uri);
|
||||
}
|
||||
config.server_port += 1;
|
||||
config.ctrl_port += 1;
|
||||
if (httpd_start(&camera_httpd, &config) == ESP_OK)
|
||||
{
|
||||
httpd_register_uri_handler(camera_httpd, &_face_stream_handler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "app_main.h"
|
||||
#include "esp_partition.h"
|
||||
#include "wechat_blufi.h"
|
||||
|
||||
void gpio_led_init()
|
||||
{
|
||||
gpio_config_t gpio_conf;
|
||||
gpio_conf.mode = GPIO_MODE_OUTPUT;
|
||||
gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_conf.pin_bit_mask = 1LL << GPIO_LED_RED;
|
||||
gpio_config(&gpio_conf);
|
||||
gpio_conf.pin_bit_mask = 1LL << GPIO_LED_WHITE;
|
||||
gpio_config(&gpio_conf);
|
||||
|
||||
}
|
||||
|
||||
void led_task(void *arg)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
switch (g_state)
|
||||
{
|
||||
case WAIT_FOR_WAKEUP:
|
||||
gpio_set_level(GPIO_LED_RED, 1);
|
||||
gpio_set_level(GPIO_LED_WHITE, 0);
|
||||
break;
|
||||
|
||||
case WAIT_FOR_CONNECT:
|
||||
gpio_set_level(GPIO_LED_WHITE, 0);
|
||||
gpio_set_level(GPIO_LED_RED, 1);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
gpio_set_level(GPIO_LED_RED, 0);
|
||||
break;
|
||||
|
||||
case START_DETECT:
|
||||
case START_RECOGNITION:
|
||||
gpio_set_level(GPIO_LED_WHITE, 1);
|
||||
gpio_set_level(GPIO_LED_RED, 0);
|
||||
break;
|
||||
|
||||
case START_ENROLL:
|
||||
gpio_set_level(GPIO_LED_WHITE, 1);
|
||||
gpio_set_level(GPIO_LED_RED, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
gpio_set_level(GPIO_LED_WHITE, 1);
|
||||
gpio_set_level(GPIO_LED_RED, 0);
|
||||
break;
|
||||
}
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
en_fsm_state g_state = WAIT_FOR_WAKEUP;
|
||||
|
||||
static void restart_count_erase_timercb(void *timer)
|
||||
{
|
||||
if (!xTimerStop(timer, portMAX_DELAY)) {
|
||||
ESP_LOGD("esp-eye", "xTimerStop timer: %p", timer);
|
||||
}
|
||||
|
||||
if (!xTimerDelete(timer, portMAX_DELAY)) {
|
||||
ESP_LOGD("esp-eye", "xTimerDelete timer: %p", timer);
|
||||
}
|
||||
|
||||
wifi_info_erase(NVS_KEY_RESTART_COUNT);
|
||||
|
||||
ESP_LOGI("esp-eye", "Erase restart count");
|
||||
}
|
||||
|
||||
static int restart_count_get()
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
TimerHandle_t timer = NULL;
|
||||
uint32_t restart_count = 0;
|
||||
|
||||
/**< If the device restarts within the instruction time,
|
||||
the event_mdoe value will be incremented by one */
|
||||
load_info_nvs(NVS_KEY_RESTART_COUNT, &restart_count, sizeof(uint32_t));
|
||||
restart_count++;
|
||||
ret = save_info_nvs(NVS_KEY_RESTART_COUNT, &restart_count, sizeof(uint32_t));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("size_info_nvs", "size_info_nvs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
timer = xTimerCreate("restart_count_erase", RESTART_TIMEOUT_MS / portTICK_RATE_MS,
|
||||
false, NULL, restart_count_erase_timercb);
|
||||
|
||||
xTimerStart(timer, 0);
|
||||
|
||||
return restart_count;
|
||||
}
|
||||
|
||||
|
||||
void printTask(void *arg)
|
||||
{
|
||||
#define BUF_SIZE 1 * 1024
|
||||
char *tasklist = malloc(BUF_SIZE);
|
||||
while (1) {
|
||||
memset(tasklist, 0, BUF_SIZE);
|
||||
vTaskGetRunTimeStats(tasklist);
|
||||
printf("Running tasks CPU usage: \n %s\r\n", (char *)tasklist);
|
||||
printf("RAM size: %dKB, with PSRAM: %dKB\n", heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL) / 1024, heap_caps_get_free_size(MALLOC_CAP_8BIT));
|
||||
vTaskDelay(5000 / portTICK_RATE_MS);
|
||||
}
|
||||
|
||||
free(tasklist);
|
||||
}
|
||||
|
||||
void app_facenet_main();
|
||||
void app_main()
|
||||
{
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
// NVS partition was truncated and needs to be erased
|
||||
// Compatible V3.1. NVS format has been changed between v3.1 and v3.2 to support longer blob values.
|
||||
// Retry nvs_flash_init
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
|
||||
if (restart_count_get() > 3) {
|
||||
ESP_LOGI("esp-eye", "Erase information saved in flash");
|
||||
wifi_info_erase(USERDATANAMESPACE);
|
||||
}
|
||||
|
||||
gpio_led_init();
|
||||
app_camera_init();
|
||||
|
||||
xTaskCreatePinnedToCore(&led_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL, 0);
|
||||
|
||||
g_state = WAIT_FOR_CONNECT;
|
||||
|
||||
ESP_LOGI("esp-eye", "Version "VERSION);
|
||||
|
||||
// app_wifi_init();
|
||||
|
||||
// wifi init and blufi
|
||||
blufi_main();
|
||||
|
||||
// wait for network connected
|
||||
wait_net_connected();
|
||||
|
||||
app_facenet_main();
|
||||
app_httpserver_init();
|
||||
printf("Mem availabe after: %d\n", heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL));
|
||||
ESP_LOGI("esp-eye", "Version "VERSION" success");
|
||||
//xTaskCreatePinnedToCore(&printTask, "printTask", 2*1024, NULL, 5, NULL, 1);
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "app_wifi.h"
|
||||
|
||||
static const char *TAG = "app_wifi";
|
||||
|
||||
#define EXAMPLE_ESP_WIFI_MODE_AP 1 //TRUE:AP FALSE:STA
|
||||
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
||||
#define EXAMPLE_MAX_STA_CONN CONFIG_MAX_STA_CONN
|
||||
#define EXAMPLE_IP_ADDR CONFIG_SERVER_IP
|
||||
|
||||
static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
{/*{{{*/
|
||||
switch(event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
ESP_LOGI(TAG, "got ip:%s",
|
||||
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
|
||||
break;
|
||||
case SYSTEM_EVENT_AP_STACONNECTED:
|
||||
ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d",
|
||||
MAC2STR(event->event_info.sta_connected.mac),
|
||||
event->event_info.sta_connected.aid);
|
||||
break;
|
||||
case SYSTEM_EVENT_AP_STADISCONNECTED:
|
||||
ESP_LOGI(TAG, "station:" MACSTR " leave, AID=%d",
|
||||
MAC2STR(event->event_info.sta_disconnected.mac),
|
||||
event->event_info.sta_disconnected.aid);
|
||||
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}/*}}}*/
|
||||
|
||||
#if EXAMPLE_ESP_WIFI_MODE_AP
|
||||
static void wifi_init_softap()
|
||||
{
|
||||
tcpip_adapter_init();
|
||||
|
||||
if (strcmp(EXAMPLE_IP_ADDR, "192.168.4.1"))
|
||||
{
|
||||
int a, b, c, d;
|
||||
sscanf(EXAMPLE_IP_ADDR, "%d.%d.%d.%d", &a, &b, &c, &d);
|
||||
tcpip_adapter_ip_info_t ip_info;
|
||||
IP4_ADDR(&ip_info.ip, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.gw, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.netmask, 255, 255, 255, 0);
|
||||
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(WIFI_IF_AP));
|
||||
ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(WIFI_IF_AP, &ip_info));
|
||||
ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(WIFI_IF_AP));
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
uint8_t mac[6];
|
||||
ESP_ERROR_CHECK(esp_wifi_get_mac(ESP_IF_WIFI_AP, mac));
|
||||
|
||||
wifi_config_t wifi_config;
|
||||
memset(&wifi_config, 0, sizeof(wifi_config_t));
|
||||
if (strlen(EXAMPLE_ESP_WIFI_SSID) == 0)
|
||||
{
|
||||
snprintf((char *)wifi_config.ap.ssid, 32, "esp-eye-%x%x", mac[4], mac[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(wifi_config.ap.ssid, EXAMPLE_ESP_WIFI_SSID, sizeof(EXAMPLE_ESP_WIFI_SSID));
|
||||
}
|
||||
memcpy(wifi_config.ap.password, EXAMPLE_ESP_WIFI_PASS, sizeof(EXAMPLE_ESP_WIFI_PASS));
|
||||
wifi_config.ap.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID);
|
||||
wifi_config.ap.max_connection = EXAMPLE_MAX_STA_CONN;
|
||||
wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
|
||||
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
|
||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
||||
}
|
||||
|
||||
esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s",
|
||||
wifi_config.ap.ssid, EXAMPLE_ESP_WIFI_PASS);
|
||||
|
||||
char buf[80];
|
||||
sprintf(buf, "SSID:%s", wifi_config.ap.ssid);
|
||||
sprintf(buf, "PASSWORD:%s", wifi_config.ap.password);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void wifi_init_sta()
|
||||
{
|
||||
tcpip_adapter_init();
|
||||
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
wifi_config_t wifi_config = {0};
|
||||
memset(&wifi_config, 0, sizeof(wifi_config_t));
|
||||
memcpy(wifi_config.sta.ssid, EXAMPLE_ESP_WIFI_SSID, sizeof(EXAMPLE_ESP_WIFI_SSID));
|
||||
memcpy(wifi_config.sta.password, EXAMPLE_ESP_WIFI_PASS, sizeof(EXAMPLE_ESP_WIFI_PASS));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", wifi_config.sta.ssid, wifi_config.sta.password);
|
||||
|
||||
char buf[80];
|
||||
sprintf(buf, "SSID:%s", wifi_config.sta.ssid);
|
||||
sprintf(buf, "PASSWORD:%s", wifi_config.sta.password);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void app_wifi_init ()
|
||||
{
|
||||
//Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
#if EXAMPLE_ESP_WIFI_MODE_AP
|
||||
ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
|
||||
wifi_init_softap();
|
||||
#else
|
||||
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
|
||||
wifi_init_sta();
|
||||
#endif /*EXAMPLE_ESP_WIFI_MODE_AP*/
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
||||
# This Makefile should, at the very least, just include $(SDK_PATH)/make/component.mk. By default,
|
||||
# this will take the sources in the src/ directory, compile them and link them into
|
||||
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
|
||||
# please read the SDK documents if you need to do this.
|
||||
#
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2017 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef _APP_CAMERA_H_
|
||||
#define _APP_CAMERA_H_
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_camera.h"
|
||||
|
||||
/**
|
||||
* PIXFORMAT_RGB565, // 2BPP/RGB565
|
||||
* PIXFORMAT_YUV422, // 2BPP/YUV422
|
||||
* PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
|
||||
* PIXFORMAT_JPEG, // JPEG/COMPRESSED
|
||||
* PIXFORMAT_RGB888, // 3BPP/RGB888
|
||||
*/
|
||||
#define CAMERA_PIXEL_FORMAT PIXFORMAT_JPEG
|
||||
|
||||
/*
|
||||
* FRAMESIZE_QQVGA, // 160x120
|
||||
* FRAMESIZE_QQVGA2, // 128x160
|
||||
* FRAMESIZE_QCIF, // 176x144
|
||||
* FRAMESIZE_HQVGA, // 240x176
|
||||
* FRAMESIZE_QVGA, // 320x240
|
||||
* FRAMESIZE_CIF, // 400x296
|
||||
* FRAMESIZE_VGA, // 640x480
|
||||
* FRAMESIZE_SVGA, // 800x600
|
||||
* FRAMESIZE_XGA, // 1024x768
|
||||
* FRAMESIZE_SXGA, // 1280x1024
|
||||
* FRAMESIZE_UXGA, // 1600x1200
|
||||
*/
|
||||
#define CAMERA_FRAME_SIZE FRAMESIZE_QVGA
|
||||
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 4
|
||||
#define SIOD_GPIO_NUM 18
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 36
|
||||
#define Y8_GPIO_NUM 37
|
||||
#define Y7_GPIO_NUM 38
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 35
|
||||
#define Y4_GPIO_NUM 14
|
||||
#define Y3_GPIO_NUM 13
|
||||
#define Y2_GPIO_NUM 34
|
||||
#define VSYNC_GPIO_NUM 5
|
||||
#define HREF_GPIO_NUM 27
|
||||
#define PCLK_GPIO_NUM 25
|
||||
|
||||
#define XCLK_FREQ 20000000
|
||||
|
||||
void app_camera_init();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2017 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef _APP_FACENET_H_
|
||||
#define _APP_FACENET_H_
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_http_server.h"
|
||||
#include "app_camera.h"
|
||||
#include "fr_forward.h"
|
||||
#include "fr_flash.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#define ENROLL_CONFIRM_TIMES 3
|
||||
#define FACE_ID_SAVE_NUMBER 10
|
||||
#define ENROLL_NAME_LEN 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *image;
|
||||
box_array_t *net_boxes;
|
||||
void *face_id;
|
||||
SemaphoreHandle_t lock;
|
||||
} http_img_process_result;
|
||||
|
||||
void app_httpserver_init ();
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
#include "app_camera.h"
|
||||
#include "app_httpserver.h"
|
||||
#include "app_wifi.h"
|
||||
|
||||
#define VERSION "0.9.2"
|
||||
|
||||
#define GPIO_LED_RED 21
|
||||
#define GPIO_LED_WHITE 22
|
||||
#define GPIO_BUTTON 15
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WAIT_FOR_WAKEUP,
|
||||
WAIT_FOR_CONNECT,
|
||||
START_STREAM,
|
||||
START_DETECT,
|
||||
START_RECOGNITION,
|
||||
START_ENROLL,
|
||||
} en_fsm_state;
|
||||
|
||||
extern en_fsm_state g_state;
|
|
@ -0,0 +1,6 @@
|
|||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
extern EventGroupHandle_t g_wifi_event_group;
|
||||
|
||||
void app_wifi_init();
|
|
@ -0,0 +1,6 @@
|
|||
# Espressif ESP32 Partition Table
|
||||
# Name, Type, SubType, Offset, Size
|
||||
factory, app, factory, 0x010000, 3M
|
||||
nvs, data, nvs, 0x310000, 16K
|
||||
fr, 32, 32, 0x320000, 128K
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0"
|
||||
CONFIG_ESPTOOLPY_BAUD_115200B=
|
||||
CONFIG_ESPTOOLPY_BAUD_230400B=
|
||||
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||
CONFIG_ESPTOOLPY_BAUD_2MB=
|
||||
CONFIG_ESPTOOLPY_BAUD_OTHER=
|
||||
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
|
||||
CONFIG_ESPTOOLPY_BAUD=921600
|
||||
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||
CONFIG_FLASHMODE_QIO=y
|
||||
CONFIG_FLASHMODE_QOUT=
|
||||
CONFIG_FLASHMODE_DIO=
|
||||
CONFIG_FLASHMODE_DOUT=
|
||||
CONFIG_ESPTOOLPY_FLASHMODE="dio"
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_40M=
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_26M=
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_20M=
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ="80m"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_1MB=
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
|
||||
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
||||
CONFIG_ESPTOOLPY_BEFORE_NORESET=
|
||||
CONFIG_ESPTOOLPY_BEFORE="default_reset"
|
||||
CONFIG_ESPTOOLPY_AFTER_RESET=y
|
||||
CONFIG_ESPTOOLPY_AFTER_NORESET=
|
||||
CONFIG_ESPTOOLPY_AFTER="hard_reset"
|
||||
CONFIG_MONITOR_BAUD_9600B=
|
||||
CONFIG_MONITOR_BAUD_57600B=
|
||||
CONFIG_MONITOR_BAUD_115200B=y
|
||||
CONFIG_MONITOR_BAUD_230400B=
|
||||
CONFIG_MONITOR_BAUD_921600B=
|
||||
CONFIG_MONITOR_BAUD_2MB=
|
||||
CONFIG_MONITOR_BAUD_OTHER=
|
||||
CONFIG_MONITOR_BAUD_OTHER_VAL=115200
|
||||
CONFIG_MONITOR_BAUD=115200
|
||||
|
||||
#
|
||||
# Partition Table
|
||||
#
|
||||
CONFIG_PARTITION_TABLE_SINGLE_APP=
|
||||
CONFIG_PARTITION_TABLE_TWO_OTA=
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
||||
CONFIG_PARTITION_TABLE_MD5=y
|
||||
#
|
||||
# Camera configuration
|
||||
#
|
||||
CONFIG_ENABLE_TEST_PATTERN=
|
||||
CONFIG_OV2640_SUPPORT=y
|
||||
CONFIG_OV7725_SUPPORT=
|
||||
|
||||
#
|
||||
# ESP32-specific
|
||||
#
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_80=
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_160=
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||
CONFIG_SPIRAM_SUPPORT=y
|
||||
|
||||
#
|
||||
# SPI RAM config
|
||||
#
|
||||
CONFIG_SPIRAM_BOOT_INIT=y
|
||||
CONFIG_SPIRAM_IGNORE_NOTFOUND=
|
||||
CONFIG_SPIRAM_USE_MEMMAP=
|
||||
CONFIG_SPIRAM_USE_CAPS_ALLOC=
|
||||
CONFIG_SPIRAM_USE_MALLOC=y
|
||||
CONFIG_SPIRAM_TYPE_AUTO=y
|
||||
CONFIG_SPIRAM_TYPE_ESPPSRAM32=
|
||||
CONFIG_SPIRAM_TYPE_ESPPSRAM64=
|
||||
CONFIG_SPIRAM_SIZE=-1
|
||||
CONFIG_SPIRAM_SPEED_40M=
|
||||
CONFIG_SPIRAM_SPEED_80M=y
|
||||
CONFIG_SPIRAM_MEMTEST=y
|
||||
CONFIG_SPIRAM_CACHE_WORKAROUND=y
|
||||
CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
CONFIG_SPIRAM_BANKSWITCH_RESERVE=8
|
||||
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=3096
|
||||
CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=
|
||||
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
|
||||
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=
|
||||
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=
|
||||
CONFIG_SPIRAM_OCCUPY_HSPI_HOST=
|
||||
CONFIG_SPIRAM_OCCUPY_VSPI_HOST=y
|
||||
|
||||
CONFIG_TASK_WDT=
|
||||
CONFIG_BT_ENABLED=y
|
Loading…
Reference in New Issue