Android ble startLeScan() 方法没有回调mina 信息回调bta_dm_ble_observe BTM_BleObserve failed. status 2

博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)android - Get BLE Scan without filter duplicate UUID - Stack Overflow
Join Stack Overflow to learn, share knowledge, and build your career.
or sign in with
I'm writing an BLE application, where need to track if peripherals device
is advertising or has stop.
I followed
this and BLE
and I completely agree over here.
To make it feasible I kept timer which re-scan for peripherals after certain time (3 sec). But with new device available on market(with 5.0 update), some time re-scan take bit time to find peripherals.
Any suggestion or if anyone have achieved this?
5,2551152123
Sounds like you're interested in scanning advertisements rather than connecting to devices. This is the "observer" role in Bluetooth Low Evergy, and corresponds to the "broadcaster" role more commonly known as a Beacon. (Bluetooth Core 4.1 Vol 1 Part A Section 6.2)
Typically you enable passive scanning, looking for ADV_IND packets broadcast by beacons. These may or may not contain a UUID. Alternatively, you can active scan by transmitting SCAN_REQ to which you may receive a SCAN_RSP. Many devices use different advertising content in ADV_IND and SCAN_RSP to increase the amount of information that can be broadcast - you could, for instance, fit a UUID128 into the ADV_IND followed by the Device Name in the SCAN_RSP. (Bluetooth Core 4.1 Vol 2 Part E Section 7.8.10)
Now you need to define "go away" - are you expecting the advertisements to stop or to fade away? You will get a Receive Signal Strength Indication "RSSI" with each advertisement (Bluetooth Core 4.1 Vol 2 Part E Section 7.7.65.2) - this is how iBeacon positioning works and there's plenty of support for beacon receivers in Android.
Alternatively you wait for N seconds for an advertisement that should be transmitted every T seconds where N>2T. The downside of the timed approach is that probably not receiving a beacon isn't the same as definitely rec to be sure you need N to be large and that impacts the latency between the broadcaster being switched off or moving out of range and your app detecting it.
One more thing - watch out that Advertising stops if something connects to a Peripheral (if you really are scanning for peripherals) another good reason to monitor RSSI.
First scenario: Bonded Devices
We know that if a bond is made, then most of the commercially available devices send directed advertisements in during re-connection. In situations such as this, according to BLE 4.0 specification, you cannot scan these devices on any BLE sniffer.
Second scenario: Connectable Devices
Peripheral devices are usually in this mode when they are initially in the reset phase. The central sends a connect initiator in response to an advertisement packet. This scenario offers you a lot of flexibility since you can play around with two predominant configuration options to alter connection time. These are: slavelatency on the peripheral and conninterval on the central. Now, I don't know how much effort it's going to take get it working on the Android platform, but if you use the Bluez BLE stack and a configurable peripheral such as a TI Sensor tag, then you can play around with these values.
Third scenario: Beacon devices
Since this is what your question revolves around, according to the BLE architecture, there are no parameters to play with. In this scenario, the central is just a dumb device left at the mercy of when a peripheral chooses to send it's beaconing signal.
Reference:
Edit: I forgot, have you tried setting the advertiser to non-connectable? That way you should be able to get duplicate scan results
I am dealing with a similar issue, that is, reliably track the RSSI values of multiple advertising devices over time.
It is sad, the most reliable way i found is not nice, rather dirty and battery consuming. It seems due to the number of android devices that handle BLE differently the most reliable.
I start LE scan, as soon as i get a callback i set a flag to stop and start scan again. That way you work around that DUPLICATE_PACKET filter issue since it resets whenever you start a fresh scan.
The ScanResults i dump into a sqlite db wich i shrink and evaluate once every x seconds.
It should be easy to adapt the shrinking to your use case, i.e. removing entries that are older than X, and then query for existance of a device to find out if you received a ScanResult in the last X seconds. However dont put that X value too low, as you must take into account that you still lose alot of advertisement packets on android LE scan, compared to a BLE scan on i.e. bluez..
I can add some information i already found for speeding up the performance on Advertisement discovery. It involves modifying and compiling the bluedroid sources and root access to the device. Easiest would be building a full android yourself, i.e. Cyanogenmod.
When a LE scan is running, the bluetooth module sends the scan sesponse via HCI to the bluedroid stack. There various checks are done until it finally gets handed to the Java onScanResult(...) which is accessed via JNI.
By comparing the log of the hci data sent from the bluetooth module (can be enabled in /etc/bluetooth/bt_stack.conf) with debug output in the bluedroid stack aswell as the Java side i noticed that alot of advertisement packets are discarded, especially in some check. i dont really understand, beside that it has something to do with the bluedroid inquiry database
From the documentation of ScanResult we see that the ScanRecord includes the advertisement data plus the scan response data. So it might be that android blocks the report until it got the scan response data/ until it is clear there is no scan response data. This i could not verify, however a possibility.
As i am only interested in rapid updates on the RSSI of those packets, i simply commented that check out. It seems that way every single packet i get from the bluetooth moduly by hci is handed through to the Java side.
in function BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
comment out to_report = FALSE; in the following check starting on line 2265.
/* active scan, always wait until get scan_rsp to report the result */
if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
(evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))
BTM_TRACE_DEBUG("btm_ble_update_inq_result scan_rsp=false, to_report=false,\
scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);
p_i-&scan_rsp = FALSE;
// to_report = FALSE; // to_report is initialized as TRUE, so we basically leave it to report it anyways.
p_i-&scan_rsp = TRUE;
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Post as a guest
Post as a guest
By posting your answer, you agree to the
Not the answer you're looking for?
Browse other questions tagged
Stack Overflow works best with JavaScript enabled&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
Android蓝牙源码分析&&BTA层消息分发
摘要:这里BTA是BluetoothApplication的缩写,从上层下来的请求都要经过这个BTA层,通过发送消息的方式将请求丢到BTA层中处理。这个发送消息的函数定义在bta_sys_main.c中,如下:voidbta_sys_sendmsg(void*p_msg){GKI_send_msg(bta_sys_cb.task_id,p_bta_sys_cfg-&mbox,p_msg);}我们在进入GKI_send_msg前,先搞清楚bta_sys_cb,这货定义在bta_
这里BTA是Bluetooth Application的缩写,从上层下来的请求都要经过这个BTA层,通过发送消息的方式将请求丢到BTA层中处理。这个发送消息的函数定义在bta_sys_main.c中,如下: void bta_sys_sendmsg(void *p_msg){ GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg-&mbox, p_msg);}
我们在进入GKI_send_msg前,先搞清楚bta_sys_cb,这货定义在bta_sys_main.c中,如下: /* system manager control block definition */tBTA_SYS_CB bta_sys_
这个bta_sys_cb是BTA层的总体Control Block。数据结构定义在bta_sys_int.h中,如下: /* system manager control block */typedef struct{ tBTA_SYS_REG *reg[BTA_ID_MAX]; /* registration structures */ BOOLEAN is_reg[BTA_ID_MAX]; /* registration structures */ ......} tBTA_SYS_CB;
这里值得注意的是reg,这是个数组,数组类型是tBTA_SYS_REG,里面是BTA下面的各个子系统的回调,最多有BTA_ID_MAX个。我们看看tBTA_SYS_REG的定义: /* registration structure */typedef struct{ tBTA_SYS_EVT_HDLR *evt_ tBTA_SYS_DISABLE *} tBTA_SYS_REG;/* event handler function type */typedef BOOLEAN (tBTA_SYS_EVT_HDLR)(BT_HDR *p_msg);/* disable function type */typedef void (tBTA_SYS_DISABLE)(void);
原来就是两个函数,一个是关于事件处理的,一个是关于disable的。就是说BTA下面的各个子系统都有自己的事件处理逻辑和disable逻辑。
我们再看看有哪些子系统,各子系统ID定义如下: /* SW sub-systems */#define BTA_ID_SYS 0 /* system manager *//* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */#define BTA_ID_DM 1 /* device manager */#define BTA_ID_DM_SEARCH 2 /* device manager search */#define BTA_ID_DM_SEC 3 /* device manager security */#define BTA_ID_DG 4 /* data gateway */#define BTA_ID_AG 5 /* audio gateway */#define BTA_ID_OPC 6 /* object push client */#define BTA_ID_OPS 7 /* object push server */#define BTA_ID_FTS 8 /* file transfer server */#define BTA_ID_CT 9 /* cordless telephony terminal */#define BTA_ID_FTC 10 /* file transfer client */#define BTA_ID_SS 11 /* synchronization server */#define BTA_ID_PR 12 /* Printer client */#define BTA_ID_BIC 13 /* Basic Imaging Client */#define BTA_ID_PAN 14 /* Personal Area Networking */#define BTA_ID_BIS 15 /* Basic Imaging Server */#define BTA_ID_ACC 16 /* Advanced Camera Client */#define BTA_ID_SC 17 /* SIM Card Access server */#define BTA_ID_AV 18 /* Advanced audio/video */#define BTA_ID_AVK 19 /* Audio/video sink */#define BTA_ID_HD 20 /* HID Device */#define BTA_ID_CG 21 /* Cordless Gateway */#define BTA_ID_BP 22 /* Basic Printing Client */#define BTA_ID_HH 23 /* Human Interface Device Host */#define BTA_ID_PBS 24 /* Phone Book Access Server */#define BTA_ID_PBC 25 /* Phone Book Access Client */#define BTA_ID_JV 26 /* Java */#define BTA_ID_HS 27 /* Headset */#define BTA_ID_MSE 28 /* Message Server Equipment */#define BTA_ID_MCE 29 /* Message Client Equipment */#define BTA_ID_HL 30 /* Health Device Profile*/#define BTA_ID_GATTC 31 /* GATT Client */#define BTA_ID_GATTS 32 /* GATT Client */#define BTA_ID_BLUETOOTH_MAX 33 /* last BT profile *//* FM */#define BTA_ID_FM 34 /* FM */#define BTA_ID_FMTX 35 /* FM TX *//* SENSOR */#define BTA_ID_SSR 36 /* Sensor *//* GPS */#define BTA_ID_GPS 37 /* GPS *//* GENERIC */#define BTA_ID_PRM 38#define BTA_ID_SYSTEM 39 /* platform-specific */#define BTA_ID_SWRAP 40 /* Insight script wrapper */#define BTA_ID_MIP 41 /* Multicase Individual Polling */#define BTA_ID_RT 42 /* Audio Routing module: This module is always on. *//* JV */#define BTA_ID_JV1 43 /* JV1 */#define BTA_ID_JV2 44 /* JV2 */#define BTA_ID_MAX (43 + BTA_DM_NUM_JV_ID)
可见一共有43个ID,另外加两个JV_ID。这些ID中比较眼熟的有BTA_ID_GATTC和BTA_ID_GATTS,应该都是和GATT相关的,一个是Server,一个是Client。
我们再来看bta_sys_cb是在哪里初始化的,在bta_sys_main.c中,如下: BTA_API void bta_sys_init(void){ memset(&;bta_sys_cb, 0, sizeof(tBTA_SYS_CB)); ptim_init(&;bta_sys_cb.ptim_cb, BTA_SYS_TIMER_PERIOD, p_bta_sys_cfg-&timer); bta_sys_cb.task_id = GKI_get_taskid(); /* register BTA SYS message handler */ bta_sys_register( BTA_ID_SYS, &;bta_sys_hw_reg); /* register for BTM notifications */ BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB*)&;bta_sys_hw_btm_cback );}
这个bta_sys_init就是初始化整个BTA的,是在btu_task线程中调用的。而btu_task线程入口是在bte_main.c的bte_main_enable中,再往上走是btif_core.c的btif_enable_bluetooth中,看样子这是打开蓝牙时调用的,再往上走是bluetooth.c的enable函数。而btif_task初始化是在btif_core.c中的btif_init_bluetooth,往上是bluetooth.c中的init函数,相比btu_task还是简单些。
我们回到bta_sys_init,这里我们关注的逻辑是首先设置bta_sys_cb的task_id为BTU TASK。然后注册BTA_ID_SYS的消息处理函数。我们看这个bta_sys_register是怎么注册的,如下: void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg){ bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_ bta_sys_cb.is_reg[id] = TRUE;}
逻辑很简单,我们看看GATTC是在哪里注册的,是在bta_gattc_api.c中的BTA_GATTC_AppRegister,如下: void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb){ tBTA_GATTC_API_REG *p_ if (bta_sys_is_register(BTA_ID_GATTC) == FALSE) { bta_sys_register(BTA_ID_GATTC, &;bta_gattc_reg); } ......}
这个函数是在btif_gatt_client.c的btgattc_handle_event中调用,往上走是注册clientIf时也就是打开gatt时。所以我们了解了当打开gatt连接时,会自动去注册GATTC子系统。这个子系统的回调在bta_gattc_api.c中: static const tBTA_SYS_REG bta_gattc_reg ={ bta_gattc_hdl_event, // 在bta_gattc_main.c中 BTA_GATTC_Disable};
我们重点关注GATTC子系统下的事件处理函数为bta_gattc_hdl_event,这个之后会用到的。因为所有Gatt相关的事件处理最终都调到了这个。
我们回到bta_sys_sendmsg,这里调用了GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg-&mbox, p_msg);,这个bta_sys_cb的task_id毫无疑问是btu_task了,其中的mbox是什么呢?我们来看p_bta_sys_cfg是在哪里初始化的,在bta_sys_cfg.c中,如下: /* GKI task mailbox event for BTA. */#ifndef BTA_MBOX_EVT#define BTA_MBOX_EVT TASK_MBOX_2_EVT_MASK#endif/* GKI task mailbox for BTA. */#ifndef BTA_MBOX#define BTA_MBOX TASK_MBOX_2#endif/* GKI timer id used for protocol timer for BTA. */#ifndef BTA_TIMER#define BTA_TIMER TIMER_1#endifconst tBTA_SYS_CFG bta_sys_cfg ={ BTA_MBOX_EVT, /* GKI mailbox event */ BTA_MBOX, /* GKI mailbox id */ BTA_TIMER, /* GKI timer id */ APPL_INITIAL_TRACE_LEVEL /* initial trace level */};tBTA_SYS_CFG *p_bta_sys_cfg = (tBTA_SYS_CFG *)&;bta_sys_
就是说bta对应的mailbox是BTA_MBOX,也就是TASK_MBOX_2。每个task都有4个mailbox用于接收buff,这个是2号邮箱。
好了,bta_sys_sendmsg就是向btu task的2号邮箱发送了msg。处理函数在哪里呢?在btu_task中如下: if (event &; TASK_MBOX_2_EVT_MASK){ while ((p_msg = (BT_HDR *) GKI_read_mbox(TASK_MBOX_2)) != NULL) { bta_sys_event(p_msg); }}
是在bta_sys_event中,发送消息可以在别的线程,但是处理消息都回到了btu_task线程内部。 BTA_API void bta_sys_event(BT_HDR *p_msg){ UINT8 BOOLEAN freebuf = TRUE; /* get subsystem id from event */ id = (UINT8) (p_msg-&event && 8); /* verify id and call subsystem event handler */ if ((id & BTA_ID_MAX) &;&; (bta_sys_cb.reg[id] != NULL)) { freebuf = (*bta_sys_cb.reg[id]-&evt_hdlr)(p_msg); } if (freebuf) { GKI_freebuf(p_msg); }}
这里根据event获取id,然后获取到对应BTA的子系统的回调,每个子系统有自己的事件处理函数的。所以如果这里是GATT相关的事件,则会走到GATT的事件处理函数,为bta_gattc_hdl_event,在bta_gattc_main.c中。
总结一下,所有BTA消息最终都送到了BTU TASK中,由bta_sys_event来处理。如果是Gatt相关的消息,则最终由bta_gattc_hdl_event处理。
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
为您提供0门槛上云实践机会
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
Android蓝牙源码分析&&BTA层消息分发相关信息,包括
的信息,所有Android蓝牙源码分析&&BTA层消息分发相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 支付宝回调信息 的文章

 

随机推荐