BLE 无法支持不同的 Android 设备
BLE Trouble Supporting Different Android Devices
我们正在创建一个 Android 应用程序,它使用 Bluegiga BLE113 连接到设备。我们在将设备与某些 Android 设备配对时遇到问题。三星设备似乎没有问题,但 Oneplus 和 LG 等其他设备并不总是合作。即使没有 PIN 或密码,我们也会收到 "Couldn't pair because of an incorrect PIN or passkey" 或 "Pairing rejected" 之类的通知。
有人遇到过这样的问题并且知道是怎么回事吗?
您是否连接到启用了绑定模式的 Android 设备?
即:BGScript 中的call sm_set_bondable_mode(1)
如果是这样,如果绑定信息不同步,您可能会收到 "Pairing rejected"。要解决此问题,请尝试使用以下方法清除绑定信息:
call sm_delete_bonding(handle)(result)
如果您这样做,绑定可能会不同步:
- 配对 BLE113 和 Android
- 断开 BLE113 与 Android
的连接
- "Unpair" Android
上的 BLE113
- 循环 Android
上的蓝牙电源
- 尝试重新连接
我刚刚写了一篇关于与 BLE113 (BGScript) 配对的完整文章 post - 请看这里:
http://www.sureshjoshi.com/embedded/bgscript-pairing-hell/
此外,请查看我的 Github 示例:
https://github.com/sureshjoshi/ble113-firmware-examples
为了简单起见,这里有一个完整的 BGScript 代码文件:
# Connection and Pairing
dim is_connected
dim current_bond_handle
const LED_PIN = # P0_0
const LED_PORT = 0
const ENCRYPTED_VALUE = 42
const TICKS_PER_SECOND = 32760
const ENCRYPTION_TIMEOUT_SECONDS = 1
const ENCRYPTION_TIMER_HANDLE = 0
# Incoming data event listener
event attributes_value(connection, reason, handle, offset, value_len, value_data)
if handle = device_reset then
# Command 1 received, reset device
if value_data(0:1) = 1 then
call system_reset(0)
end if
end if
end
event system_boot(major, minor, patch, build, ll_version, protocol_version, hw)
is_connected = 0
current_bond_handle = $ff
# configure P0.0 as output, others as input
call hardware_io_port_config_direction(LED_PORT, LED_PIN)
# Set advertisement interval
call gap_set_adv_parameters(320, 480, 7)
# Put module into discoverable/connectable mode
call gap_set_mode(gap_general_discoverable, gap_undirected_connectable)
# Set Bondable mode
call sm_set_bondable_mode(1)
# Turn on the LED
call hardware_io_port_write(LED_PORT, LED_PIN, LED_PIN)
end
event hardware_soft_timer(handle)
# Other side hasn't tried an encrypted link yet even though we are
# bonded as far as we know, so try to start it from this end
if handle = ENCRYPTION_TIMER_HANDLE then
call sm_encrypt_start(0, 1)
end if
end
# Custom read requests
event attributes_user_read_request(connection, handle, offset, maxsize)
if handle = xgatt_encrypted_value then
call attributes_user_read_response(connection, 0, 1, ENCRYPTED_VALUE)
end if
end
event connection_status(connection, flags, address, address_type, conn_interval, timeout, latency, bonding)
# Set up a connection interval of between 6*1.25ms to 10*1.25ms (7.5-12.5ms)
# Android and iOS respond to connection interval updates, but cannot set them (they also have minimums)
if is_connected = 0 then
call connection_update(connection, 6, 10, latency, timeout)
end if
is_connected = 1
# Use whatever bonding handle we're given (used in case of bond failure)
current_bond_handle = bonding
# If we're not yet encrypted, request encryption
if (flags & ) != then
# Request encryption if not encrypted already
if bonding = $ff then
call sm_encrypt_start(connection, 1)
else
# Start one-shot encryption attempt timer in case the remote side doesn't attempt an encrypted link within 1 second
# (this might happen if you bond with a smartphone and then remove the pairing info from the phone side, but not the local module side)
# Only seems to work on iOS - Android rejects the pairing a few times - works eventually...
call hardware_set_soft_timer(ENCRYPTION_TIMEOUT_SECONDS * TICKS_PER_SECOND, ENCRYPTION_TIMER_HANDLE, 1)
end if
end if
end
# Disconnection event listener
event connection_disconnected(handle, result)
# Reset the current_bond_handle
current_bond_handle = $ff
# Make peripheral discoverable
call gap_set_mode(gap_general_discoverable, gap_undirected_connectable)
end
event sm_bonding_fail(handle, result)
# If bonding fails, handle it gracefully based on the following possible results:
# - 0x018B - Out of bonds (no space left, all 8 bonding slots taken)
# - 0x0205 - Authentication failure (shouldn't happen with "just works" mode, but might otherwise)
# - 0x0206 - Pin or key missing (probably local or remote device is missing the key, but not both)
# - 0x0301 - Passkey entry failed (also shouldn't happen in "just works" mode unless bonding is cancelled)
# - 0x0302 - OOB data not available (only occurs if OOB is required and not supported on both ends)
# - 0x0303 - Authentication requirements (I/O capabilities required but not supported)
# - 0x0304 - Confirm value failed (PIN entry/comparison attempted but failed)
# - 0x0305 - Pairing not supported (also occurs if bond info removed from remote device but not local module)
# - 0x0306 - Encryption key size (key size insufficient to meet security requirements)
# - 0x0307 - Command not supported (SMP command is not supported on this device)
# - 0x0308 - Unspecified reason (may occur if bond info is present remotely but not locally)
# - 0x0309 - Repeated attempts (too little time has elapsed since last pairing/security request)
# - 0x030A - Invalid parameters (bad parameters sent during pairing/bonding process)
# NOTE: The most common cases:
# - 0x018B, which means you ran out of space and must remove at least one bond in order to bond again
# - 0x0206, which typically means the pairing info was removed on the remote device but not locally
# - 0x0301, which typically means the user cancelled the pairing request or entered the wrong passkey
# - 0x0305, which is like 0x0206 but is often generated instead if the remote device is a smartphone
# - 0x0308, which typically means the pairing info was removed on the local device but not remotely
if result = 8b then
# Only solved by removing bonds - requires the user to reset the bonds...
end if
if result = 01 then
# Usually solved simply by trying again
# Seems to solve most problems on iOS
# On Android, pairing rejected a few times if Android deleted pairing without informing device
call sm_encrypt_start(0, 1)
end if
if result = 05 || result = 06 then
# Remove local bonding info first, then the remote device needs to reconnect
# If current_bond_handle is $ff, that means we don't have a bonding handle - so not much we can do
if current_bond_handle != $ff then
call sm_delete_bonding(current_bond_handle)
end if
# Sometimes takes a few tries
call connection_disconnect(0)
end if
if result = 08 then
# Remove remote bonding info first, then the remote device needs to reconnect
# Android can recover automatically, iOS cannot
# Instead of disconnecting, just force a re-encryption... Usually works
call sm_encrypt_start(0, 1)
end if
end
我们正在创建一个 Android 应用程序,它使用 Bluegiga BLE113 连接到设备。我们在将设备与某些 Android 设备配对时遇到问题。三星设备似乎没有问题,但 Oneplus 和 LG 等其他设备并不总是合作。即使没有 PIN 或密码,我们也会收到 "Couldn't pair because of an incorrect PIN or passkey" 或 "Pairing rejected" 之类的通知。
有人遇到过这样的问题并且知道是怎么回事吗?
您是否连接到启用了绑定模式的 Android 设备?
即:BGScript 中的call sm_set_bondable_mode(1)
如果是这样,如果绑定信息不同步,您可能会收到 "Pairing rejected"。要解决此问题,请尝试使用以下方法清除绑定信息:
call sm_delete_bonding(handle)(result)
如果您这样做,绑定可能会不同步:
- 配对 BLE113 和 Android
- 断开 BLE113 与 Android 的连接
- "Unpair" Android 上的 BLE113
- 循环 Android 上的蓝牙电源
- 尝试重新连接
我刚刚写了一篇关于与 BLE113 (BGScript) 配对的完整文章 post - 请看这里:
http://www.sureshjoshi.com/embedded/bgscript-pairing-hell/
此外,请查看我的 Github 示例:
https://github.com/sureshjoshi/ble113-firmware-examples
为了简单起见,这里有一个完整的 BGScript 代码文件:
# Connection and Pairing
dim is_connected
dim current_bond_handle
const LED_PIN = # P0_0
const LED_PORT = 0
const ENCRYPTED_VALUE = 42
const TICKS_PER_SECOND = 32760
const ENCRYPTION_TIMEOUT_SECONDS = 1
const ENCRYPTION_TIMER_HANDLE = 0
# Incoming data event listener
event attributes_value(connection, reason, handle, offset, value_len, value_data)
if handle = device_reset then
# Command 1 received, reset device
if value_data(0:1) = 1 then
call system_reset(0)
end if
end if
end
event system_boot(major, minor, patch, build, ll_version, protocol_version, hw)
is_connected = 0
current_bond_handle = $ff
# configure P0.0 as output, others as input
call hardware_io_port_config_direction(LED_PORT, LED_PIN)
# Set advertisement interval
call gap_set_adv_parameters(320, 480, 7)
# Put module into discoverable/connectable mode
call gap_set_mode(gap_general_discoverable, gap_undirected_connectable)
# Set Bondable mode
call sm_set_bondable_mode(1)
# Turn on the LED
call hardware_io_port_write(LED_PORT, LED_PIN, LED_PIN)
end
event hardware_soft_timer(handle)
# Other side hasn't tried an encrypted link yet even though we are
# bonded as far as we know, so try to start it from this end
if handle = ENCRYPTION_TIMER_HANDLE then
call sm_encrypt_start(0, 1)
end if
end
# Custom read requests
event attributes_user_read_request(connection, handle, offset, maxsize)
if handle = xgatt_encrypted_value then
call attributes_user_read_response(connection, 0, 1, ENCRYPTED_VALUE)
end if
end
event connection_status(connection, flags, address, address_type, conn_interval, timeout, latency, bonding)
# Set up a connection interval of between 6*1.25ms to 10*1.25ms (7.5-12.5ms)
# Android and iOS respond to connection interval updates, but cannot set them (they also have minimums)
if is_connected = 0 then
call connection_update(connection, 6, 10, latency, timeout)
end if
is_connected = 1
# Use whatever bonding handle we're given (used in case of bond failure)
current_bond_handle = bonding
# If we're not yet encrypted, request encryption
if (flags & ) != then
# Request encryption if not encrypted already
if bonding = $ff then
call sm_encrypt_start(connection, 1)
else
# Start one-shot encryption attempt timer in case the remote side doesn't attempt an encrypted link within 1 second
# (this might happen if you bond with a smartphone and then remove the pairing info from the phone side, but not the local module side)
# Only seems to work on iOS - Android rejects the pairing a few times - works eventually...
call hardware_set_soft_timer(ENCRYPTION_TIMEOUT_SECONDS * TICKS_PER_SECOND, ENCRYPTION_TIMER_HANDLE, 1)
end if
end if
end
# Disconnection event listener
event connection_disconnected(handle, result)
# Reset the current_bond_handle
current_bond_handle = $ff
# Make peripheral discoverable
call gap_set_mode(gap_general_discoverable, gap_undirected_connectable)
end
event sm_bonding_fail(handle, result)
# If bonding fails, handle it gracefully based on the following possible results:
# - 0x018B - Out of bonds (no space left, all 8 bonding slots taken)
# - 0x0205 - Authentication failure (shouldn't happen with "just works" mode, but might otherwise)
# - 0x0206 - Pin or key missing (probably local or remote device is missing the key, but not both)
# - 0x0301 - Passkey entry failed (also shouldn't happen in "just works" mode unless bonding is cancelled)
# - 0x0302 - OOB data not available (only occurs if OOB is required and not supported on both ends)
# - 0x0303 - Authentication requirements (I/O capabilities required but not supported)
# - 0x0304 - Confirm value failed (PIN entry/comparison attempted but failed)
# - 0x0305 - Pairing not supported (also occurs if bond info removed from remote device but not local module)
# - 0x0306 - Encryption key size (key size insufficient to meet security requirements)
# - 0x0307 - Command not supported (SMP command is not supported on this device)
# - 0x0308 - Unspecified reason (may occur if bond info is present remotely but not locally)
# - 0x0309 - Repeated attempts (too little time has elapsed since last pairing/security request)
# - 0x030A - Invalid parameters (bad parameters sent during pairing/bonding process)
# NOTE: The most common cases:
# - 0x018B, which means you ran out of space and must remove at least one bond in order to bond again
# - 0x0206, which typically means the pairing info was removed on the remote device but not locally
# - 0x0301, which typically means the user cancelled the pairing request or entered the wrong passkey
# - 0x0305, which is like 0x0206 but is often generated instead if the remote device is a smartphone
# - 0x0308, which typically means the pairing info was removed on the local device but not remotely
if result = 8b then
# Only solved by removing bonds - requires the user to reset the bonds...
end if
if result = 01 then
# Usually solved simply by trying again
# Seems to solve most problems on iOS
# On Android, pairing rejected a few times if Android deleted pairing without informing device
call sm_encrypt_start(0, 1)
end if
if result = 05 || result = 06 then
# Remove local bonding info first, then the remote device needs to reconnect
# If current_bond_handle is $ff, that means we don't have a bonding handle - so not much we can do
if current_bond_handle != $ff then
call sm_delete_bonding(current_bond_handle)
end if
# Sometimes takes a few tries
call connection_disconnect(0)
end if
if result = 08 then
# Remove remote bonding info first, then the remote device needs to reconnect
# Android can recover automatically, iOS cannot
# Instead of disconnecting, just force a re-encryption... Usually works
call sm_encrypt_start(0, 1)
end if
end