发帖
2 0 0

AI-WB2-32S-Kit蓝牙信标实现安防检测(二)

ch999
高级会员

3

主题

10

回帖

513

积分

高级会员

积分
513
电子DIY 48 2 前天 16:09
[i=s] 本帖最后由 ch999 于 2025-5-30 16:13 编辑 [/i]

AI-WB2-32S-Kit蓝牙信标实现安防检测(二)

上一章链接:使用AI-WB2-32s-Kit制作安防检测

IMG_20250530_1537501.jpg

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

完成雷达扫描和蓝牙信标后,现在来完成信息发送功能,参照这位大神的做法 https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=45846&highlight=wb2

Screenshot_20250530_130048_com.github.gotify1.jpg

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

接下来是开发板代码,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

这里的WiFi是从sdk里的WiFi 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地址的蓝牙,则表示自己回家,否则就发送消息到服务器,接下来只需要把服务器放公网上或者用内网穿透,即可实现公网通知了,当然,用其他的消息通知也是一样的,看个人喜好了。

Screenshot_20250530_133246_com.github.gotify.jpg

──── 0人觉得很赞 ────

使用道具 举报

赞👍~
不错不错~
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28853 个
  • 话题数: 41317 篇