4.4. 蓝牙发射器

概述

简单介绍蓝牙发射器的使用流程

4.4.1. 操作说明

    1. 在app_config.h中打开宏

  • #define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能

  • #define TCFG_USER_EMITTER_ENABLE 1 //蓝牙发射功能

  • #define CONFIG_POWER_ON_ENABLE_BT 1 //开机自动打开经典蓝牙(demo_edr默认开启,wifi_story_machine未开启需使用时通过按键开启蓝牙)

    1. 蓝牙发射功能(bt_emitter.c):蓝牙发射搜索结果回调处理,根据过滤规则可以做名字过滤、地址过滤、自定义过滤和无限制规则,也可以保存搜索到的所有设备再选择一个进行连接

    1. 在选择使用的过滤方式下填入所需连接的蓝牙参数(名称或地址)

    1. 蓝牙发射 提供按键切换发射器或者是音箱功能:2:发射 1:接收 0: 关闭

    1. 发射器设置回调包括设备名字name、设备名字长度len、设备类型class和设备信号强度rssi等

//bt_emitter.c
//首先通过宏选择使用的过滤方式
#define  SEARCH_BD_ADDR_LIMITED 0  //搜索蓝牙地址过滤
#define  SEARCH_BD_NAME_LIMITED 1  //搜索蓝牙名称过滤
#define  SEARCH_CUSTOM_LIMITED  2  //自定义搜索
#define  SEARCH_NULL_LIMITED    3  //没有指定限制,则搜到什么就连接什么

#define SEARCH_LIMITED_MODE  SEARCH_BD_NAME_LIMITED    //选择过滤方式

//地址过滤
#if (SEARCH_LIMITED_MODE == SEARCH_BD_ADDR_LIMITED)
static const u8 bd_addr_filt[][6] = {
    {0x8E, 0xA7, 0xCA, 0x0A, 0x5E, 0xC8}, /*S10_H*/
    {0xA7, 0xDD, 0x05, 0xDD, 0x1F, 0x00}, /*ST-001*/
    {0xE9, 0x73, 0x13, 0xC0, 0x1F, 0x00}, /*HBS 730*/
    {0x38, 0x7C, 0x78, 0x1C, 0xFC, 0x02}, /*Bluetooth*/
    //{0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX}, /*填入所需搜索连接蓝牙地址*/
};

/*----------------------------------------------------------------------------*/
/**@brief    蓝牙发射搜索通过地址过滤
@param    无
@return   无
@note
*/
/*----------------------------------------------------------------------------*/
static u8 search_bd_addr_filt(const u8 *addr)
{
    log_i("bd_addr:");
    put_buf(addr, 6);

    for (u8 i = 0; i < (sizeof(bd_addr_filt) / sizeof(bd_addr_filt[0])); i++) {
        if (memcmp(addr, bd_addr_filt[i], 6) == 0) {
            /* printf("bd_addr match:%d\n", i); */
            return TRUE;
        }
    }
    /*log_i("bd_addr not match\n"); */
    return FALSE;
}
#endif

//名称过滤
#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED)
#if 0
static const u8 bd_name_filt[][32] = {
    "BeMine",
    "EDIFIER CSR8635",/*CSR*/
    "JL-BT-SDK",/*Realtek*/
    "I7-TWS",/*ZKLX*/
    "TWS-i7",/*ZKLX*/
    "I9",/*ZKLX*/
    "小米小钢炮蓝牙音箱",/*XiaoMi*/
    "小米蓝牙音箱",/*XiaoMi*/
    "XMFHZ02",/*XiaoMi*/
    "JBL GO 2",
    "i7mini",/*JL tws AC690x*/
    "S08U",
    "AI8006B_TWS00",
    "S046",/*BK*/
    "AirPods",
    "CSD-TWS-01",
    "AC692X_wh",
    "JBL GO 2",
    "JBL Flip 4",
    "BT Speaker",
    "CSC608",
    "QCY-QY19",
    "Newmine",
    "HT1+",
    "S-35",
    "T12-JL",
    "Redmi AirDots_R",
    "Redmi AirDots_L",
    "AC69_Bluetooth",
    "FlyPods 3",
    "MNS",
    "Jam Heavy Metal",
    "Bluedio",
    "HR-686",
    "BT MUSIC",
    "BW-USB-DONGLE",
    "S530",
    "XPDQ7",
    "MICGEEK Q9S",
    "S10_H",
    "S10",/*JL AC690x*/
    "S11",/*JL AC460x*/
    "HBS-730",
    "SPORT-S9",
    "Q5",
    "IAEB25",
    "T5-JL",
    "MS-808",
    "LG HBS-730",
    "NG-BT07"
};
#else
static const u8 bd_name_filt[][30] = {
    "JL-AC79XX-AF0B",
    "JL-AC79XX-AAFF",
    //"填入所需搜索连接蓝牙名称"
};
#endif

/*----------------------------------------------------------------------------*/
/**@brief    蓝牙发射搜索通过名字过滤
@param    无
@return   无
@note
*/
/*----------------------------------------------------------------------------*/
u8 search_bd_name_filt(const char *data, u8 len, u32 dev_class, char rssi)
{
    char bd_name[64] = {0};

    if ((len > (sizeof(bd_name))) || (len == 0)) {
        return FALSE;
    }

    memcpy(bd_name, data, len);
    log_i("name:%s,len:%d,class %x ,rssi %d\n", bd_name, len, dev_class, rssi);

    for (u8 i = 0; i < (sizeof(bd_name_filt) / sizeof(bd_name_filt[0])); i++) {
        if (memcmp(data, bd_name_filt[i], len) == 0) {
            log_i("\n*****find dev ok******\n");
            return TRUE;
        }
    }

    return FALSE;
}
#endif

/*----------------------------------------------------------------------------*/
/**@brief    蓝牙发射搜索结果回调处理
@param    name : 设备名字
            name_len: 设备名字长度
            addr:   设备地址
            dev_class: 设备类型
            rssi:   设备信号强度
@return   无
@note
            蓝牙设备搜索结果,可以做名字/地址过滤,也可以保存搜到的所有设备
            在选择一个进行连接,获取其他你想要的操作。
            返回TRUE,表示搜到指定的想要的设备,搜索结束,直接连接当前设备
            返回FALSE,则继续搜索,直到搜索完成或者超时
*/
/*----------------------------------------------------------------------------*/
u8 emitter_search_result(char *name, u8 name_len, u8 *addr, u32 dev_class, char rssi)
{
    if (emitter_or_receiver != BT_EMITTER_EN) {
        return 0;
    }

#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED)
    if (name == NULL) {
        struct inquiry_noname_remote *remote = zalloc(sizeof(struct inquiry_noname_remote));
        remote->match = 0;
        remote->class = dev_class;
        remote->rssi = rssi;
        memcpy(remote->addr, addr, 6);
        os_mutex_pend(&mutex, 0);
        list_add_tail(&remote->entry, &inquiry_noname_list);
        if (read_name_start == 0) {
            read_name_start = 1;
            user_send_cmd_prepare(USER_CTRL_READ_REMOTE_NAME, 6, addr);
        }
        os_mutex_post(&mutex);
    }
#endif

#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED)
    return search_bd_name_filt(name, name_len, dev_class, rssi);
#endif

#if (SEARCH_LIMITED_MODE == SEARCH_BD_ADDR_LIMITED)
    return search_bd_addr_filt(addr);
#endif

#if (SEARCH_LIMITED_MODE == SEARCH_CUSTOM_LIMITED)
    /*以下为搜索结果自定义处理*/
    char bt_name[63] = {0};
    u8 len;
    if (name_len == 0) {
        log_i("No_eir\n");
    } else {
        len = (name_len > 63) ? 63 : name_len;
        /* display bd_name */
        memcpy(bt_name, name, len);
        log_i("name:%s,len:%d,class %x ,rssi %d\n", bt_name, name_len, dev_class, rssi);
    }

    /* display bd_addr */
    put_buf(addr, 6);

    /* You can connect the specified bd_addr by below api      */
    //user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR,6,addr);

    return FALSE;
#endif

#if (SEARCH_LIMITED_MODE == SEARCH_NULL_LIMITED)
    /*没有指定限制,则搜到什么就连接什么*/
    return TRUE;
#endif
}
//demo_edr在bt_music.c的bt_music_key_event_handler()长按KEY_MODE切换发射器和接收器
case KEY_MODE:
#if TCFG_USER_EMITTER_ENABLE
            //发射器或者接收器切换
            if (__this->enable) {
                if (__this->emitter) {
                    bt_emitter_disable();
                } else {
                    key_event_disable();
                    bt_connection_disable();
                    sys_timeout_add(NULL, bt_emitter_enable, 1000);
                }
            }
#endif
            break;

//wifi_story_machine在app_music.c的app_music_key_long()中切换发射器和接收器
static int app_music_key_long(struct key_event *key)
{
    switch (key->value) {
    case KEY_OK:
#if TCFG_USER_EMITTER_ENABLE
        if (__this->bt_music_enable) {
            if (__this->bt_emitter_enable) {
                app_music_play_voice_prompt("BtClose.mp3", bt_emitter_switch_to_receiver);
            } else {
                app_music_play_voice_prompt("BtOpen.mp3", bt_emitter_enable);
                bt_connection_disable();
            }
        }
#endif
        break;

4.4.2. 效果展示

    1. demo_edr工程将主机的mic采集数据通过发射器传输到从机播放

    1. wifi_story_machine工程将主机播放的数据通过发射器传输到从机播放

4.4.3. 接口说明

    1. emitter代码文件:bt_emitter.c

    1. bt_emitter接口说明

  • (1)emitter_rx_avctp_opid_deal :蓝牙发射接收到设备按键消息

  • (2)emitter_rx_vol_change :蓝牙发射接收设备同步音量

  • (3)emitter_media_source :蓝牙发射开启关闭通道

4.4.4. 代码流程

    1. demo_edr工程

  • (1)app_main.c:在app_main函数中调用bt_ble_module_init函数初始化蓝牙模块

  • (2)bt_music.c:在蓝牙开启的状态长按KEY_MODE按键进行发射器跟接收器的切换,初始化蓝牙发射器

  • (3)bt_emitter.c:在开启发射器后,设备会先轮询保存在vm中的设备是否可连接,如果是则连接最近的一台接收器,否则从设备过滤清单中找出可连接的设备

    1. wifi_story_machine工程

  • (1)app_music.c:通过按键打开蓝牙功能app_music_key_click()的KEY_MDOE

  • (2)app_music.c: 通过长按按键切换到发射器模式app_music_key_long的KEY_OK

  • (3)bt_emitter.c:在开启发射器后,设备会先轮询保存在vm中的设备是否可连接,如果是则连接最近的一台接收器,否则从设备过滤清单中找出可连接的设备