首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【DIY】用安信可WiFi+蓝牙模组Ai-WB2-32S-Kit实现安防检测

【DIY】用安信可WiFi+蓝牙模组Ai-WB2-32S-Kit实现安防检测

原创
作者头像
安信可科技
发布2025-06-18 15:32:07
发布2025-06-18 15:32:07
1440
举报
文章被收录于专栏:DIYDIY

以下作品由安信可社区用户

ch999制作

前言:

笔者这次决定使用AI-WB2-32s-Kit雷达模块制+蓝牙信标作安防检测,灵感来源是想着马上毕业要外出租房,担心陌生人进入房间。

制作这个项目,目的是实现当有人进入房间时起到提示作用。但如果仅用雷达检查,每次自己回家都也会触发报告,那样就太烦了,所以决定通过蓝牙信标来过滤指定目标。

01

材料

●Ai-WB2-32S-Kit

●雷达模块(自带uart串口,通过串口输出数据)

●蓝牙模块

●服务器,用来做中转发送消息

雷达部分的代码

#include <stdio.h> #include <string.h> #include <FreeRTOS.h> #include <task.h> #include <blog.h> #include "bl_sys.h" #include <stdio.h> #include <cli.h> #include <hosal_uart.h> #include <bl_gpio.h> #include "bl_uart.h" #define TAG "uart_demo" #define GPIO_LED_PIN 3 hosal_uart_dev_t uart_dev_log = { .config = { .uart_id = 0, .tx_pin = 16, // TXD GPIO .rx_pin = 7, // RXD GPIO .cts_pin = 255, .rts_pin = 255, .baud_rate = 115200, .data_width = HOSAL_DATA_WIDTH_8BIT, .parity = HOSAL_NO_PARITY, .stop_bits = HOSAL_STOP_BITS_1, .mode = HOSAL_UART_MODE_POLL, }, }; //UART radar void uart_radar_data(void *param) { char data[64]; int ret; while (1) { /* UART receive poll */ ret = hosal_uart_receive(&uart_dev_log, data, sizeof(data)-1); if (ret > 0) { bl_gpio_output_set(GPIO_LED_PIN, 1);//set led } else{ bl_gpio_output_set(GPIO_LED_PIN, 0);//set led } /* sscanf 是 C 语言标准库中的一个函数, * 用于从字符串中按照指定的格式读取数据, * 并将数据存储到指定的变量中123。 * 它的原型定义在 <stdio.h> 头文件中 */ //雷达串口输出数据的格式: v=-0.6 km/h, str=208 float velocity; int str_value; if (2 == sscanf(data, "v=%f km/h, str=%d", &velocity, &str_value)) { printf("Parsed: v=%.1f, str=%d\r\n", velocity, str_value); } vTaskDelay(200); } } void main(void) { /* UART InIt device */ hosal_uart_init(&uart_dev_log); /*LED*/ bl_gpio_enable_output(GPIO_LED_PIN, 0, 0); xTaskCreate(uart_radar_data, "radar", 1024, NULL, 15, NULL); }

第一阶段先通过这个小项目,测试了点灯和串口,以及结合外设实现安防功能。

接下来要做的:蓝牙信标(该部分以完成)

开发板以主机模式扫描设备,雷达发现有人进屋且扫描到指定MAC设备,表示是自己回家,否则就是陌生人闯入。

蓝牙部分代码

在bl_interface.c库文件里添加如下代码实现mac比对和rssi。

// int ble_master_get_rssi_by_mac(uint8_t *target_mac){ if(target_mac==NULL)return -127; int ret=0; int rssi=0; int retry=3; struct bt_le_scan_param scan_param; char scan_data[250]; scan_param.type = BT_LE_SCAN_TYPE_ACTIVE; scan_param.filter_dup = BT_LE_SCAN_FILTER_DUPLICATE; scan_param.interval = 320; scan_param.window = 48; master_current_scan = 0; memset(scan_le_addr, 0, sizeof(scan_le_addr)); memset(master_scan_tbl, 0, sizeof(master_scan_tbl)); //scan ret = bt_le_scan_start(&scan_param, scan_device_found); if(ret!=0){rssi=-127;} vTaskDelay(800 / portTICK_PERIOD_MS);//持续扫描的时间 for (int i = 0; i < master_current_scan; i++) { ble_reverse_byte(master_scan_tbl[i].mac, 6); if(memcmp(target_mac,master_scan_tbl[i].mac, 6)==0){ sprintf(scan_data,"My BLE MAC:%02X%02X%02X%02X%02X%02X RSSI:%i name:%s\r\n", master_scan_tbl[i].mac[0],master_scan_tbl[i].mac[1],master_scan_tbl[i].mac[2], master_scan_tbl[i].mac[3],master_scan_tbl[i].mac[4],master_scan_tbl[i].mac[5], master_scan_tbl[i].rssi, master_scan_tbl[i].name); bleuart_printf(scan_data); rssi=master_scan_tbl[i].rssi; break; } else{ //bleuart_printf("Not Found MAC Device\r\n"); rssi= -127; } } return rssi; }

再部署完服务器后,进行一下简单测试。

完成雷达扫描和蓝牙信标后,现在来完成信息发送功能,参照安信可社区这位大佬的做法 :用AI-WB2消息推送到个人通知https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=45846&highlight=wb2&_dsign=04722896

可以看到手机可以正常接收消息。

接下来是开发板代码,notify部分的代码参考原文链接,记得添加必要的network库到MAKEFILE以及修改pro_config.mk

notify.h

#ifndef __NOTIFY_H__ #define __NOTIFY_H__ #define WEB_SERVER "192.168.43.218" //这里改成你搭建的gotify服务器地址 #define WEB_PORT "8000" //默认地址是80 我改为了8000,dokcer部署时选到什么端口这里填什么端口,最好避开80,怕运营商屏蔽 #define WEB_PATH_BASE "/message" #define QUERY_STRING "?token=AQSv2fQhrE.8_Fq" //token替换为你的通道token,token加到token=Axxxxxx后面 void notify_task(void *pvParameters); #endif

notify.c

这里的Wi-Fi是从sdk里的Wi-Fi demo修改过来的。

#include "notify.h" #include <FreeRTOS.h> #include <blog.h> #include <cli.h> #include <http_client.h> #include <lwip/err.h> #include <lwip/netdb.h> #include <lwip/sockets.h> #include <lwip/tcp.h> #include <stdio.h> #include <task.h> #define BOUNDARY "---" static char REQUEST[512]; typedef struct { const char *title; const char *message; const char *priority; } Message; void notify_task(void *pvParameters) { Message *params = (Message *)pvParameters; // 接收参数 // // // printf("title=%s \r\nmessage=%s\r\npriority=%s\r\n", params->title, params->message, params->priority); // const struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, }; struct addrinfo *res; struct in_addr *addr; int s, r; char recv_buf[4096]; while (1) { int err = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &res); if (err != 0 || res == NULL) { blog_error("DNS lookup failed err=%d res=%p", err, res); vTaskDelay(1000 / portTICK_PERIOD_MS); continue; } /* Code to print the resolved IP. Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */ addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr; blog_info("DNS lookup succeeded. IP=%s", inet_ntoa(*addr)); s = socket(res->ai_family, res->ai_socktype, 0); if (s < 0) { blog_error("... Failed to allocate socket."); freeaddrinfo(res); vTaskDelay(1000 / portTICK_PERIOD_MS); continue; } blog_info("... allocated socket"); if (connect(s, res->ai_addr, res->ai_addrlen) != 0) { blog_error("... socket connect failed errno=%d", errno); close(s); freeaddrinfo(res); vTaskDelay(4000 / portTICK_PERIOD_MS); continue; } blog_info("... connected"); freeaddrinfo(res); // 构造请求体 char body[1024]; snprintf(body, sizeof(body), "--%s\r\n" "Content-Disposition: form-data; name=\"title\"\r\n\r\n" "%s\r\n" "--%s\r\n" "Content-Disposition: form-data; name=\"message\"\r\n\r\n" "%s\r\n" "--%s\r\n" "Content-Disposition: form-data; name=\"priority\"\r\n\r\n" "%s\r\n" "--%s--\r\n", BOUNDARY, params->title, BOUNDARY, params->message, BOUNDARY, params->priority, BOUNDARY); snprintf(REQUEST, sizeof(REQUEST), "POST %s%s HTTP/1.0\r\n" "Host: %s:%s\r\n" "User-Agent: aithinker wb2\r\n" "Content-Type: multipart/form-data; boundary=%s\r\n" "Content-Length: %d\r\n" "\r\n" "%s", WEB_PATH_BASE, QUERY_STRING, WEB_SERVER, WEB_PORT, BOUNDARY, strlen(body), body); if (write(s, REQUEST, strlen(REQUEST)) < 0) { blog_error("... socket send failed"); close(s); vTaskDelay(4000 / portTICK_PERIOD_MS); continue; } blog_info("... socket send success"); struct timeval receiving_timeout; receiving_timeout.tv_sec = 5; receiving_timeout.tv_usec = 0; if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout, sizeof(receiving_timeout)) < 0) { blog_error("... failed to set socket receiving timeout"); close(s); vTaskDelay(4000 / portTICK_PERIOD_MS); continue; } blog_info("... set socket receiving timeout success"); // FIXME fix putchar extern int bl_putchar(int c); /* Read HTTP response */ do { bzero(recv_buf, sizeof(recv_buf)); r = read(s, recv_buf, sizeof(recv_buf) - 1); for (int i = 0; i < r; i++) { bl_putchar(recv_buf[i]); } } while (r > 0); blog_info("... done reading from socket. Last read return=%d " "errno=%d\r\n", r, errno); close(s); for (int countdown = 10; countdown >= 0; countdown--) { blog_info("%d... ", countdown); vTaskDelay(1000 / portTICK_PERIOD_MS); } blog_info("Starting again!"); } } #include <stdio.h> #include <string.h> #include <FreeRTOS.h> #include <task.h> #include <timers.h> #include <stdint.h> #include <vfs.h> #include <aos/kernel.h> #include <aos/yloop.h> #include <event_device.h> #include <cli.h> #include <lwip/tcpip.h> #include <lwip/sockets.h> #include <lwip/netdb.h> #include <lwip/tcp.h> #include <lwip/err.h> #include <netutils/netutils.h> #include <bl602_glb.h> #include <bl602_hbn.h> #include <bl60x_fw_api.h> #include <bl_uart.h> #include <bl_chip.h> #include <bl_sec.h> #include <bl_cks.h> #include <bl_irq.h> #include <bl_dma.h> #include <bl_adc.h> #include <bl_timer.h> #include <bl_gpio_cli.h> #include <bl_wdt_cli.h> #include <bl_gpio.h> #include <hal_sys.h> #include <hal_gpio.h> #include <hal_boot2.h> #include <hal_board.h> #include <looprt.h> #include <loopset.h> #include <bl_sys_time.h> #include <bl_sys_ota.h> #include <bl_romfs.h> #include <fdt.h> #include <bl_timer.h> #include <easyflash.h> #include <utils_log.h> #include <libfdt.h> #include <blog.h> #include <hosal_uart.h> #include "bluetooth.h" #include "ble_interface.h" #include <bl_sys.h> #include "notify.h" #include <wifi_mgmr_ext.h> #include <http_client.h> #include <hal_wifi.h> #include <event_groups.h> #define ROUTER_SSID "Play4T" #define ROUTER_PWD "qq123456" typedef struct { const char *title; const char *message; const char *priority; } Message; hosal_uart_dev_t ble_uart_dev = { .config = { .uart_id = 0, .tx_pin = 16, // TXD GPIO .rx_pin = 7, // RXD GPIO .cts_pin = 255, .rts_pin = 255, .baud_rate = 115200, .data_width = HOSAL_DATA_WIDTH_8BIT, .parity = HOSAL_NO_PARITY, .stop_bits = HOSAL_STOP_BITS_1, .mode = HOSAL_UART_MODE_POLL, }, }; static wifi_conf_t conf = { .country_code = "CN", }; // bool is_Send=false; uint32_t last_send_time=0; int rssi; // 构建消息内容结构体 static const char title[] = "tt"; static const char message[] = "12345"; static const char priority[] = "0"; static uint8_t target_mac[6] ={0xD1,0x10,0x91,0x29,0x8F,0xF5}; // 目标设备MAC地址,请改为实际MAC static Message msg = {title, message, priority}; extern uint8_t axk_HalBleInit(); /** * @brief wifi_sta_connect * wifi station mode connect start * @param ssid * @param password */ static void wifi_sta_connect(char *ssid, char *password) { wifi_interface_t wifi_interface; wifi_interface = wifi_mgmr_sta_enable(); wifi_mgmr_sta_connect(wifi_interface, ssid, password, NULL, NULL, 0, 0); } // WiFi事件处理 static void event_cb_wifi_event(input_event_t *event, void *private_data) { static char *ssid; static char *password; switch (event->code) { case CODE_WIFI_ON_INIT_DONE: { printf("[APP] [EVT] INIT DONE %lld\r\n", aos_now_ms()); wifi_mgmr_start_background(&conf); } break; case CODE_WIFI_ON_MGMR_DONE: { printf("[APP] [EVT] MGMR DONE %lld\r\n", aos_now_ms()); //_connect_wifi(); wifi_sta_connect(ROUTER_SSID, ROUTER_PWD); } break; case CODE_WIFI_ON_SCAN_DONE: { printf("[APP] [EVT] SCAN Done %lld\r\n", aos_now_ms()); // wifi_mgmr_cli_scanlist(); } break; case CODE_WIFI_ON_DISCONNECT: { printf("[APP] [EVT] disconnect %lld\r\n", aos_now_ms()); } break; case CODE_WIFI_ON_CONNECTING: { printf("[APP] [EVT] Connecting %lld\r\n", aos_now_ms()); } break; case CODE_WIFI_CMD_RECONNECT: { printf("[APP] [EVT] Reconnect %lld\r\n", aos_now_ms()); } break; case CODE_WIFI_ON_CONNECTED: { printf("[APP] [EVT] connected %lld\r\n", aos_now_ms()); } break; case CODE_WIFI_ON_PRE_GOT_IP: { printf("[APP] [EVT] connected %lld\r\n", aos_now_ms()); } break; case CODE_WIFI_ON_GOT_IP: { printf("[APP] [EVT] GOT IP %lld\r\n", aos_now_ms()); printf("[SYS] Memory left is %d Bytes\r\n", xPortGetFreeHeapSize()); } break; case CODE_WIFI_ON_PROV_SSID: { printf("[APP] [EVT] [PROV] [SSID] %lld: %s\r\n", aos_now_ms(), event->value ? (const char *)event->value : "UNKNOWN"); if (ssid) { vPortFree(ssid); ssid = NULL; } ssid = (char *)event->value; } break; case CODE_WIFI_ON_PROV_BSSID: { printf("[APP] [EVT] [PROV] [BSSID] %lld: %s\r\n", aos_now_ms(), event->value ? (const char *)event->value : "UNKNOWN"); if (event->value) { vPortFree((void *)event->value); } } break; case CODE_WIFI_ON_PROV_PASSWD: { printf("[APP] [EVT] [PROV] [PASSWD] %lld: %s\r\n", aos_now_ms(), event->value ? (const char *)event->value : "UNKNOWN"); if (password) { vPortFree(password); password = NULL; } password = (char *)event->value; } break; case CODE_WIFI_ON_PROV_CONNECT: { printf("[APP] [EVT] [PROV] [CONNECT] %lld\r\n", aos_now_ms()); printf("connecting to %s:%s...\r\n", ssid, password); wifi_sta_connect(ssid, password); } break; case CODE_WIFI_ON_PROV_DISCONNECT: { printf("[APP] [EVT] [PROV] [DISCONNECT] %lld\r\n", aos_now_ms()); } break; default: { printf("[APP] [EVT] Unknown code %u, %lld\r\n", event->code, aos_now_ms()); /*nothing*/ } } } //开启蓝牙扫描必须要声明bleuart_printf这个函数,不知道为什么,这个函数在ble_interface.c中要用到 //注释掉ble_interface.c会报错,实再没看懂,留着吧 void bleuart_printf(char *buf) { hosal_uart_send(&ble_uart_dev, buf, strlen(buf)); } // UART InIt device static void uart_init(void) { hosal_uart_init(&ble_uart_dev); } //UART radar static void radar_detection(void *param) { char data[64]; while (1) { //接收到数据data hosal_uart_receive(&ble_uart_dev, data, sizeof(data)-1); /*data: v=-0.6 km/h, str=208 * sscanf 是 C 语言标准库中的一个函数, * 用于从字符串中按照指定的格式读取数据, * 并将数据存储到指定的变量中123。 * 它的原型定义在 <stdio.h> 头文件中 */ //解析data float velocity; int str_value; if (2 == sscanf(data, "v=%f km/h, str=%d", &velocity, &str_value)) { //printf("radar data: v=%.1f, str=%d\r\n", velocity, str_value); } if(str_value>1000 && rssi==-127){ xTaskCreate(¬ify_task, "notify_task", 2048, &msg, 5, NULL); printf("There are strangers entering the house\r\n"); } vTaskDelay(200); } } //BLE static void ble_loop_proc(void *pvParameters) { char data[250]; while (1) { rssi=ble_master_get_rssi_by_mac(target_mac); // 扫描指定MAC的蓝牙设备 if(rssi>-80){ bl_gpio_output_set(3, 1); } else{ bl_gpio_output_set(3, 0); } hosal_uart_receive(&ble_uart_dev, data, sizeof(data)); vTaskDelay(100/portTICK_PERIOD_MS); } } ////发送消息 //static void send_message(void *param){ // while(1){ // if(is_BreakIn){ //printf("is_BreakIn"); // //uint32_t current_time=aos_now_ms(); // //if((current_time-last_send_time)>10){ // xTaskCreate(¬ify_task, "notify_task", 1024, &msg, 5, NULL); // //last_send_time=current_time; // is_BreakIn=false; // printf("There are strangers entering the house\r\n"); // //} // // } // } // //} void main() { uart_init(); bl_sys_init(); // if use BLE ,must InIt axk_HalBleInit(); //printf("BLE MASTER InIt\r\n"); tcpip_init(NULL, NULL); aos_register_event_filter(EV_WIFI, event_cb_wifi_event, NULL); hal_wifi_start_firmware_task(); aos_post_event(EV_WIFI, CODE_WIFI_ON_INIT_DONE, 0); bl_gpio_enable_output(3, 0, 0);//GPIO xTaskCreate(ble_loop_proc, "ble master", 1024, NULL, 15, NULL); xTaskCreate(radar_detection, "radar", 1024, NULL, 15, NULL); // xTaskCreate(send_message, "send_message", 1024, NULL, 15, NULL); }

雷达扫描到有人时,如果开发板同时扫描到指定MAC地址的蓝牙,则表示自己回家,否则就发送消息到服务器,接下来只需要把服务器放公网上或者用内网穿透,即可实现公网通知了,当然用其他的消息通知也是一样的,看个人喜好。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档